在图像中查找图像(对象检测)

时间:2017-10-26 05:21:06

标签: c# algorithm opencv image-processing emgucv

我确实有不同的图像,这些图像都围绕着"真实的"图片。我想要实现的是找到真实的"图像(大小和位置,以像素为单位)。

real image showing water with shark

对我而言,挑战在于边框并非总是黑色(可以是任何一种带有很多噪音的黑色或灰色)和“真实的”#34;图像(本例中带有鲨鱼的水)可以具有颜色,饱和度的任意组合......

现在我一般都知道Canny,Blob检测,hough行等算法,但我刚刚开始使用它们。到目前为止,我设法找到特定图像的边框,但是一旦我尝试将相同的算法和参数应用到下一个图像,它就无法工作。我目前的方法看起来像这样(伪代码):

  1. 转换为灰色CvInvoke.CvtColor(_processedImage, tempMat, CvEnum.ColorConversion.Rgb2Gray)
  2. 使用CvInvoke.PyrDown(srcImage, targetImage)CvInvoke.PyrUp(srcImage, targetImage)
  3. 进行缩减示例
  4. 使用CvInvoke.GaussianBlur(_processedImage, bluredImage, New Drawing.Size(5, 5), 0)
  5. 模糊图像
  6. 使用CvInvoke.Threshold(_processedImage, blackWhiteImage, _parameters.BinarizeThreshold, 255, CvEnum.ThresholdType.Binary)
  7. 进行二值化
  8. 使用CvInvoke.Canny(_processedImage, imgEdges, 60, 100)
  9. 检测边缘
  10. 使用`CvInvoke.FindContours(_processedImage,contours,Nothing,CvEnum.RetrType.External,CvEnum.ChainApproxMethod.ChainApproxSimple)查找轮廓
  11. 假设最大轮廓是真实图像
  12. 我已经尝试过基于例如的不同方法:

    任何关于如何为(自适应)阈值和canny等算法找到适当参数(适用于所有图像)的提示以及改进处理流程的想法都将受到高度赞赏。

2 个答案:

答案 0 :(得分:1)

您可以尝试从此图像中减去黑色图像,然后您将获得内部图像,方法是: Use image subtraction to compare images in C#

答案 1 :(得分:1)

如果边框是均匀的,这很容易。使用cv::reduce查找每行和每列的MIN和MAX;然后计算其中MIN和MAX与附近角落中的像素值相等(或非常接近)的顶部,左侧,底部,右侧行/列。为了理智,也许检查边框颜色是否相同。

在您的示例中,边框包含微弱的红色内容,但行/列方法可能仍然是简化问题的有用方法。也许,正如Nofar建议的那样,与你认为的背景色完全不同;将它平方,转换为灰色,然后减少为行和列的总和。您仍然需要找到边缘,但已将数据从两个维度减少到一个。

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

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