使用Opencv如何检测图像中的盒子,同时消除盒子内打印的对象?

时间:2014-08-01 14:23:06

标签: c++ qt opencv computer-vision vision

我正在尝试在qt中开发盒子排序应用程序并使用opencv。我想测量盒子的宽度和长度。

Input Image

如上图所示,我想只检测最外面的线条(即盒子边缘),这将给出盒子的宽度和长度,无论盒子内部打印的是什么。

我尝试了什么:

  1. 首先,我尝试使用Findcontours()并选择具有最大面积的轮廓,但外边缘的轮廓未被封闭(在精确输出中的某处断开)多次,因此不会被检测为轮廓。 / p>

  2. 霍夫线变换给了我太多的线条,我不知道如何只有四条线感兴趣。

  3. 我尝试了我的算法,

    将图像转换为灰度。

    取一列图像,将每个像素与该列的下一个连续像素进行比较,如果该值的差异大于该像素属于边缘的某个阈值(比如100),则将其存储在数组中。对所有列执行此操作,它将使框的上线与x轴平行。

    按照相同的步骤,但是从最后一列和最后一行(即从下到上),它将给出与x轴平行的下线。

    同样找到与y轴平行的线。现在我有四个点阵,每一个点。

  4. 现在,如果放置方框使其边与X轴和Y轴完全平行,这会给我带来很好的效果。如果盒子在某个方向上稍微朝向放置,它会给我一条明显的对角线,如下图所示。

    Wrong Output

    如下图所示,我从所有四个点阵列(负责绘制对角线)中删除了前10个点和后10个点并绘制了线条,当盒子倾斜得更多时,这些线条无效会出错。

    enter image description here

    现在我的问题是,

    在opencv中是否有任何更简单的方法来获取盒子的外边缘(矩形)并获得尺寸,忽略盒子上印刷的任何东西并朝向任何方向?

    我不一定要求纠正/改进我的算法,但对此的任何建议也欢迎。对不起这么大的帖子。

2 个答案:

答案 0 :(得分:2)

我建议采取以下步骤:

1:使用cv::inRange()documentation)选择背景颜色制作蒙版图像。然后使用cv::not()反转此掩码。这只会给你一个盒子。

2:如果您不关心阴影,深度效果会使您的测量结果不准确,您可以立即尝试再次使用cv::findContours()。您选择最大的轮廓并存储它cv::rotatedRect

3:这个cv::rotatedRect将为您提供一个rotateRect.size,用于定义宽度和盒子的高度(以像素为单位)

答案 1 :(得分:0)

由于盒子放置在对比鲜明的背景中,您应该能够使用Otsu阈值处理。

  • 阈值图像(使用Otsu方法)
  • 过滤掉框区域外的任何杂散像素(让我们希望你不会得到很多这样的像素,并且可以使用中位数或形态滤镜轻松删除它们)
  • 查找轮廓
  • 组合所有轮廓点并获得它们的凸包(这里的想法是找到在框区域中界定所有这些轮廓的凸区域,无论它们的连通性如何)
  • 将多边形近似(approxPolyDP)应用于此凸包,并检查是否有四边形
  • 如果没有透视扭曲,你应该得到一个矩形,否则你将需要纠正它
  • 如果你得到一个矩形,你有它的尺寸。你也可以找到凸包的最小面积矩形(minAreaRect),它应该直接给你一个RotatedRect