【问题标题】:Having difficulties detecting small objects in noisy background. Any ways to fix this?在嘈杂的背景中难以检测小物体。有什么办法可以解决这个问题?
【发布时间】:2015-12-02 12:30:12
【问题描述】:

我正在尝试制作一个计算机视觉程序,它可以在嘈杂的背景(例如海滩)中检测垃圾和随机垃圾(由于沙子而嘈杂)。

原图:

无需任何图像处理的 Canny 边缘检测:

我意识到图像处理技术的某种组合将帮助我实现我的目标,即忽略嘈杂的沙地背景并检测地面上的所有垃圾和物体。

我尝试进行中值模糊、调整和调整参数,它给了我这个:

它在忽略沙地背景方面表现良好,但它无法检测到地面上的其他许多物体,可能是因为它被模糊了(不太确定)。

有没有什么方法可以改进我的算法或图像处理技术,从而忽略嘈杂的沙地背景,同时允许精巧的边缘检测找到所有对象并让程序检测并在所有对象上绘制轮廓。

代码:

from pyimagesearch.transform import four_point_transform
from matplotlib import pyplot as plt
import numpy as np
import cv2
import imutils

im = cv2.imread('images/beach_trash_3.jpg')


#cv2.imshow('Original', im)

# Histogram equalization to improve contrast




###
#im = np.fliplr(im)

im = imutils.resize(im, height = 500)

imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

# Contour detection
#ret,thresh = cv2.threshold(imgray,127,255,0)

#imgray = cv2.GaussianBlur(imgray, (5, 5), 200)
imgray = cv2.medianBlur(imgray, 11)

cv2.imshow('Blurred', imgray)

'''
hist,bins = np.histogram(imgray.flatten(),256,[0,256])
plt_one = plt.figure(1)
cdf = hist.cumsum()
cdf_normalized = cdf * hist.max()/ cdf.max()

cdf_m = np.ma.masked_equal(cdf,0)
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
cdf = np.ma.filled(cdf_m,0).astype('uint8')
imgray = cdf[imgray]

cv2.imshow('Histogram Normalization', imgray)
'''
'''
imgray = cv2.adaptiveThreshold(imgray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY,11,2)
'''

thresh = imgray

#imgray = cv2.medianBlur(imgray,5)
#imgray = cv2.Canny(imgray,10,500)
thresh = cv2.Canny(imgray,75,200)
#thresh = imgray
cv2.imshow('Canny', thresh)


contours, hierarchy = cv2.findContours(thresh.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

cnts = sorted(contours, key = cv2.contourArea, reverse = True)[:5]

test = im.copy()
cv2.drawContours(test, cnts, -1,(0,255,0),2)
cv2.imshow('All contours', test)

print '---------------------------------------------'
#####  Code to show each contour #####
main = np.array([[]])
for c in cnts:
    epsilon = 0.02*cv2.arcLength(c,True)
    approx = cv2.approxPolyDP(c,epsilon,True)

    test = im.copy()
    cv2.drawContours(test, [approx], -1,(0,255,0),2)
    #print 'Contours: ', contours
    if len(approx) == 4:
        print 'Found rectangle'
        print 'Approx.shape: ', approx.shape
        print 'Test.shape: ', test.shape

        # frame_f = frame_f[y: y+h, x: x+w]
        frame_f = test[approx[0,0,1]:approx[2,0,1], approx[0,0,0]:approx[2,0,0]]

        print 'frame_f.shape: ', frame_f.shape
        main = np.append(main, approx[None,:][None,:])
        print 'main: ', main


    # Uncomment in order to show all rectangles in image
    #cv2.imshow('Show Ya', test)


    #print 'Approx: ', approx.shape
    #cv2.imshow('Show Ya', frame_f)
    cv2.waitKey()
print '---------------------------------------------'
cv2.drawContours(im, cnts, -1,(0,255,0),2)
print main.shape
print main
cv2.imshow('contour-test', im)
cv2.waitKey()

【问题讨论】:

  • 我不确定这个问题是否离题,因为您似乎在询问使用哪种算法的建议。
  • 在 HSV 图像(H 通道)上尝试模糊和精巧,而不是灰度图像。和/或使用双边滤波器而不是中值。
  • 您可以在不进行任何修改和添加且不进行有损压缩的情况下以完整尺寸发布原始输入图像吗?任何想向您展示一些算法的人都会很好。
  • 沙子检测示例:HALACCI、Ibrahim 等。行星探测漫游车的地形分类和分类器融合。在:航空航天会议,2007 年 IEEE。 IEEE,2007 年。 1-11。 web.mit.edu/mobility/publications/Iagnemma_Aero_07b.pdf
  • This 会有所帮助。它有点类似于下面 Ankit 建议的方法 1。我用算法测试了给定的图像,它给出了合理的分割。

标签: opencv image-processing computer-vision edge-detection opencv-contour


【解决方案1】:

为了获得更好的结果,您应该应用许多算法。 OpenCV 教程始终关注 OpenCV 的一个特性。真正的 CV 应用程序应该使用尽可能多的技术和算法。

我曾经在嘈杂的图片中检测生物细胞,并且应用一些上下文信息获得了非常好的结果:

  • 单元格的预期大小
  • 事实上所有单元格的大小都相似
  • 预期的单元格数 因此,我更改了许多参数并尝试检测我要查找的内容。

如果使用边缘检测,沙子会给出相当随机的形状。尝试更改 canny 参数并检测线、矩形、圆等。 - 更可能是垃圾的任何形状。记住每个参数集和 at 检测到的对象的位置,并优先考虑那些最常检测到形状的位置(区域)。

使用颜色分离。颜色直方图中的峰值可能是对垫料的暗示,因为沙子颜色的分布应该更均匀。

对于一些经常出现的小物件,如烟头,您可以申请object matching

附注: 很酷的应用程序!只是出于好奇,你打算用四轴飞行器扫描海滩吗?

【讨论】:

  • 您还有其他关于如何系统地组合多个检测器的参考资料吗?
  • 没有。有些部分我已经硬编码,有些部分我使用了 SVM。一开始,我花了很多时间在 OpenCV 中寻找“合适的即用型解决方案”,以便“不重新发明轮子”。最后,我将我的代码与 OpenCV 结合使用。后来一位 OpenCV 专家证实了我,不要太从字面上理解 OpenCV。他们不可能考虑到所有用例。我什至自己实现了自动特征选择,以便能够考虑上下文或域信息。
【解决方案2】:

如果你想检测这种均匀背景上的物体,你应该从检测图像中的主要颜色开始。像这样你会检测到所有的沙子,而物体将在剩余的部分。你可以看看 Arnaud LeTrotter 和 Ludovic Llucia 发表的论文,他们都使用了这种类型的“主色检测”。

【讨论】:

  • 背景绝不统一!沙子可能是干的或湿的,沙子的颜色可能不同。阴影,一天中的时间会大大改变颜色,等等。
  • 对于给定的图像应该是统一的!他们使用的算法是在每张图像上计算的,而不是一劳永逸的。
【解决方案3】:

我对您的问题的理解是:您想从本质上可变的背景中分割出前景对象(沙子灰度取决于许多其他条件)。

有多种方法可以解决此类问题:

方法一:

从您的图像中可以清楚地看出,背景颜色像素的数量总是比前景像素多得多,开始初始分割的最简单方法是:

  1. 将图像转换为灰色。
  2. 创建直方图。
  3. 查找直方图的峰值索引,即具有最大像素的索引。

以上三个步骤让您了解背景但是游戏并没有到此结束,现在您可以将这个索引值放在中心并在它周围取一系列值,例如上下 25 ,例如:如果您的峰值指数为 207(如您的情况),请选择从 75 到 225 的灰度范围和阈值图像,根据您的背景性质,上述方法可用于前景对象检测,分割后您必须执行一些后处理步骤,例如形态分析,以在提取对象后分割出不同的对象,您可以应用一些分类内容进行更精细的分割以消除误报。

方法2:

玩一些图像像素的统计数据,比如制作一个小的灰度值数据集和

  1. 将它们标记为 1 和 2 类,例如 1 表示沙子,2 表示前景,
  2. 找出两个类像素的均值和方差(标准偏差),并计算这两个类的概率 (num_pix_per_class/total_num_pix),现在存储这些统计信息以备后用,
  3. 现在回到图像并逐个获取每个像素并应用高斯 pdf:1/2*pisigma(exp(-(pix - mean)/2*sigma));在平均值的位置放置较早计算的平均值,在 sigma 放置较早计算的标准偏差。
  4. 应用阶段 3 后,您将获得两个类别的每个像素的两个概率值,只需选择概率较高的类别即可。

方法 3:

方法 3 比上述两种更复杂:您可以使用一些基于纹理的操作来分割沙子类型的纹理,但是对于应用基于纹理的方法,我会推荐监督分类而不是无监督分类(如 k-means)。 您可以使用的不同纹理特征是:

基本:

  1. 已定义邻域内的灰度范围。
  2. 局部均值和方差或熵。
  3. 灰度共现矩阵 (GLCM)。

高级:

  1. 本地二进制模式。
  2. 小波变换。
  3. Gabor 变换。等

PS:我认为你应该尝试接近1和2。它可以解决很多工作。 :)

【讨论】:

  • @user3377126 您能否就您在方法 1、2、3 之间的体验给出一些解释/建议?
  • 2015 年提出的建议方法,现在我将选择任何基于深度学习的对象检测器,例如 Yolo 或 SSD。
猜你喜欢
  • 2019-11-21
  • 1970-01-01
  • 2021-03-07
  • 2010-11-25
  • 2020-12-29
  • 1970-01-01
  • 2021-01-17
  • 2012-03-28
  • 1970-01-01
相关资源
最近更新 更多