如何检测多条图案?

时间:2018-04-04 15:14:14

标签: c++ opencv image-processing template-matching

我想检测一个自定义"多条形图案"在图像中。

图案看起来像这样,有一组平行的黑色条,宽度相同但高度不同,请看这个图片:

image 1

这种模式可能在图像上,甚至没有,但如果是 - 我希望得到它的位置。

注意:在每种情况下,图案的颜色都是黑色

注意:模式的大小未知,因此可能很大或可能超小。

注意:图案条数是固定数。每次出现都是一样的(在这种情况下为7)。

图片可能如下所示:

Image

执行代码搜索算法后,应该会发生这种情况:

enter image description here

非常感谢任何帮助。感谢提前一百万,Tempi。

注意:到目前为止我得到的代码(不工作)

Mat myImage; // this is the mat of the photo you can see above
Mat algorithmImage;
myImage.coptyTo(algorithmImage); 
cvtColor(algorithmImage, algorithmImage, CV_RGB2HSV);

double imgThreshold = 20;
cv::inRange(algorithmImage, cv::Scalar(0, 0, 0, 0), cv::Scalar(180, 255, 30, 0), 20);

Mat canny;
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;

Canny( algorithmImage, canny, 3, 6, 3 );
findContours( canny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

for( int i = 0; i<contours.size(); i++ ) {
  // ??
}

bool isLineAlreadyFound(const Vec4i& _l1, const Vec4i& _l2) {
    Vec4i l1(_l1), l2(_l2);

    float length1 = sqrtf((l1[2] - l1[0])*(l1[2] - l1[0]) + (l1[3] - l1[1])*(l1[3] - l1[1]));
    float length2 = sqrtf((l2[2] - l2[0])*(l2[2] - l2[0]) + (l2[3] - l2[1])*(l2[3] - l2[1]));

    float product = (l1[2] - l1[0])*(l2[2] - l2[0]) + (l1[3] - l1[1])*(l2[3] - l2[1]);

    if (fabs(product / (length1 * length2)) < cos(CV_PI / 30))
        return false;

    float mx1 = (l1[0] + l1[2]) * 0.5f;
    float mx2 = (l2[0] + l2[2]) * 0.5f;

    float my1 = (l1[1] + l1[3]) * 0.5f;
    float my2 = (l2[1] + l2[3]) * 0.5f;
    float dist = sqrtf((mx1 - mx2)*(mx1 - mx2) + (my1 - my2)*(my1 - my2));

    if (dist > std::max(length1, length2) * 0.5f)
        return false;

    return true;
}

2 个答案:

答案 0 :(得分:0)

以下是我如何解决您的问题。

  • 由于您的图案完全是黑色的,因此您可以从中受益 然后做一个门槛。尝试一个非常低的门槛(如果它是一个完美的 黑色,使用1作为阈值。)

  • 完成上述步骤后,使用findContours应该已经做好了 检测形状。但是你需要的是一种识别你的方式 图案。由于您的图案可能会以不同的比例和/或显示出来 方向,您将需要一个缩放/方向不变的描述符。一世 这里的意思是形状描述符。你可以看看 胡锦涛https://en.wikipedia.org/wiki/Image_moment

  • 每个模式中只有一个条形图。你应该完成 通过为您的模式设计特定功能来进行搜索 帮助从每个栏中提取的功能。

答案 1 :(得分:0)

这里的技巧是你有14个平行边。那些是不可能错过的。如其他答案中所述,隔离它们的阈值。在此之后,运行边缘检测器。这会将黑色和白色边缘变成线条,而图像的其余部分可能会产生一些分散的像素。想象一下,亲眼看看。

接下来,从OpenCV运行Hough变换。这为您提供了{offset,direction}格式的行。即使一些分散的背景像素恰好排成一行,它们也不会形成具有相同方向的14条线。

您可以计算最大偏移差异以查找条形图案的比例,并仔细检查相对偏移以检查单个条形宽度和间距。请记住,14条线是边缘,所以你需要配对它们。

此时您已确定条形图案的方向和比例。意识到你实际上并没有确定实际的酒吧位置可能有点令人惊讶。这个程序的原因是我们首先解决了这个难题。我们现在回到边缘检测的输出,并将那里的所有边缘分成三类:平行边缘,两对平行边缘之间的圆形端盖(遵循轮廓)和随机背景像素。您可能需要MORPH_CLOSE操作来关闭轮廓中的间隙。