我正在尝试制作一个计算机视觉程序,它可以在嘈杂的背景(如沙滩)中检测垃圾和随机垃圾。
原始图片:
没有任何图像处理的Canny Edge检测:
我意识到图像处理技术的某种组合将帮助我实现忽略嘈杂的沙质背景并检测地面上所有垃圾和物体的目标。
我试图预先形成中位数模糊,玩耍并调整参数,它给了我这个:
它在忽略沙质背景方面表现良好,但它无法检测到地面上的其他许多物体,可能是因为它模糊了(不太确定)。
有没有办法改进我的算法或图像处理技术,忽略嘈杂的沙质背景,同时允许精确边缘检测找到所有物体,让程序检测并绘制所有物体的轮廓。
代码:
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()
答案 0 :(得分:3)
我从你的问题中理解的是:你想要从背景中分割出前景物体,这些物体本质上是可变的(沙灰色等级取决于许多其他条件)。
有各种方法可以解决这类问题:
方法1:
从你的图像中可以清楚地看出,背景颜色像素的数量总是远远超过前景,开始初始分割的最简单方法是:
以上三个步骤让您了解背景但是游戏不在此处结束,现在您可以将此索引值放在中心并在其周围采用一系列值,如上下25 ,例如:如果你的峰值指数是207(如你的情况),选择一个从75到225的灰度范围和阈值图像,根据你的背景上面的方法的性质可以用于前景物体检测,分割后你必须执行一些后处理步骤,如形态分析,以在提取对象后分割出不同的对象,您可以应用一些分类内容以获得更精细的分割级别以消除误报。
方法2:
使用图像像素的一些统计数据,比如制作一个灰度值的小数据集和
方法3:
方法3比上面两个更复杂:你可以使用一些基于纹理的操作来分割出砂型纹理,但是对于应用基于纹理的方法,我将推荐监督分类而不是无监督(如k-means)。 您可以使用的不同纹理功能是:
基本:
高级强>
PS:在我看来,你应该尝试接近1和2.它可以解决很多工作。 :)
答案 1 :(得分:2)
为了获得更好的效果,您应该应用许多算法。 OpenCV教程始终关注OpenCV的一个特性。真正的CV应用程序应该使用尽可能多的技术和算法。
我已经习惯在嘈杂的图片中检测生物细胞,并且通过应用一些上下文信息获得了非常好的结果:
如果使用边缘检测,沙子会给出相当随机的形状。尝试更改canny参数并检测线条,rects,圆圈和ets。 - 任何形状更可能是垃圾。记住每个参数集的检测对象的位置,并优先考虑那些大多数时间检测到形状的位置(区域)。
使用分色。颜色直方图中的峰值可能是垃圾的暗示,因为沙色的分布应该更均匀。
对于经常出现的一些小物件,如香烟残骸,您可以申请object matching。
P.S: 酷应用!出于好奇,你是不是要用四轴飞机扫描海滩?
答案 2 :(得分:0)
如果要检测这种均匀背景上的物体,首先应检测图像中的主要颜色。就像那样,你将检测到所有的沙子,而物体将在剩下的部分中。您可以查看由Arnaud LeTrotter和Ludovic Llucia发表的论文,他们都使用了这种“主要颜色检测”。