关于c#:在图像中查找图像(对象检测)

Find image within image (object detection)

我确实有不同的图像,它们都在"真实"图像周围有某种边界。我想实现的是找到"真实"的图像(以像素为单位的大小和位置)。

real image showing water with shark

对我来说,挑战在于边界并不总是黑色的(可以是任何一种有很多噪音的黑色或灰色),而"真实"图像(本例中的鲨鱼水)可以有任何颜色、饱和度等组合。

现在一般来说,我知道一些算法,比如canny、blob检测、hough行等等,但我刚刚开始使用它们。到目前为止,我设法找到了一个特定图像的边界,但一旦我尝试对下一个图像应用相同的算法和参数,它就不起作用了。我当前的方法如下(伪代码):

  • 转换为灰色CvInvoke.CvtColor(_processedImage, tempMat, CvEnum.ColorConversion.Rgb2Gray)
  • 使用CvInvoke.PyrDown(srcImage, targetImage)CvInvoke.PyrUp(srcImage, targetImage)进行降采样
  • CvInvoke.GaussianBlur(_processedImage, bluredImage, New Drawing.Size(5, 5), 0)模糊图像
  • CvInvoke.Threshold(_processedImage, blackWhiteImage, _parameters.BinarizeThreshold, 255, CvEnum.ThresholdType.Binary)二值化
  • CvInvoke.Canny(_processedImage, imgEdges, 60, 100)检测边缘
  • 使用'cvinvoke.find contours'查找轮廓(_processedimage,contours,nothing,cvenum.retrtype.external,cvenum.chainApprovxMethod.chainApprovxSimple)
  • 假设最大轮廓是真实图像
  • 我已经尝试了不同的方法,例如:

    • 阈值饱和通道和边界框
    • 阈值、精明的边缘和寻找轮廓

    任何提示,特别是如何找到合适的参数(适用于所有图像)的算法,如(自适应)阈值和精明,以及改善处理管道的想法,都将受到高度赞赏。


    如果边界是统一的,那就很容易了。使用cv::reduce查找每行和每列的最小值和最大值,然后计算其最小值和最大值与附近角的像素值相等(或非常接近)的顶部、左侧、底部、右侧行/列。为了保持头脑清醒,可能要检查边框的颜色是否各不相同。

    在您的示例中,边框包含微弱的红色内容,但行/列方法可能仍然是简化问题的一种有用方法。也许,正如诺法尔所建议的,用你认为是背景色的颜色来做一个绝对的区别;将它平方,转换成灰色,然后减少到行和列的总和。您仍然需要查找边,但已将数据从二维缩减为一维。

    如果有一个大的边界和大量的噪声,可以迭代:在第二遍中,从列的统计信息中排除您认为构成边界的行(反之亦然)。

    编辑:以上仅适用于垂直矩形!如果可以旋转,则行/列投影方法将无法工作。在这种情况下,我可能会像上面那样求平方差之和(不要先转换为灰色,因为它可能会丢弃信息),然后是模糊或某些形态,边缘检测,然后是某种hough转换,以找到直边。


    您可以尝试从该图像中减去黑色图像,然后获得内部图像,方法如下:使用图像减法比较C中的图像,