在嘈杂的背景下难以检测到小物体.有什么办法解决这个问题? [英] Having difficulties detecting small objects in noisy background. Any ways to fix this?

查看:70
本文介绍了在嘈杂的背景下难以检测到小物体.有什么办法解决这个问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个计算机视觉程序,该程序可以在海滩等嘈杂的背景(沙子引起的嘈杂)中检测垃圾和随机垃圾.

I am trying to make a computer vision program in which it would detect litter and random trash in a noisy background such as the beach (noisy due to sand).

原始图片:

不进行任何图像处理的Canny Edge检测:

Canny Edge detection without any image processing:

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

I realize that a certain combination of image processing technique will help me accomplish my goal of ignoring the noisy sandy background and detect all trash and objects on the ground.

我试图进行中值模糊处理,调整并调整参数,这给了我:

I tried to preform median blurring, play around and tune the parameters, and it gave me this:

就忽略沙子背景而言,它的预成型效果很好,但是它无法检测到地面上的其他许多物体,可能是因为它模糊了(不太确定).

It preforms well in terms of ignoring the sandy background, but it fails to detect some of the other many objects on the ground, possibly because it is blurred out (not too sure).

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

Is there any way of improving my algorithm or image processing techniques that will ignore the noisy sandy background while allowing canny edge detection to find all objects and have the program detect and draw contours on all objects.

代码:

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()

推荐答案

我从您的问题中了解的是:您想从自然界可变的背景中分割出前景对象(沙子的灰度取决于许多其他条件).

what i am understanding from your problem is: you want to segment out the foreground objects from a background which is variable in nature(sand gray level is depending on many other conditions).

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

there are various ways to approach this kind of problem:

方法1:

从您的图像中可以明显看出,背景颜色像素的数字总是比前景更多,最简单的初始分割方法是:

From your image one thing is clear that, background color pixels will always much more in numbers than foreground, simplest method to start initial segmentation is:

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

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

above three steps give you an idea of background BUT the game is not ends here, now you can put this index value in the center and take a range of values around it like 25 above and below, for example: if your peak index is 207 (as in your case) choose a range of gray level from 75 to 225 and threshold image, As according to nature of your background above method can be used for foreground object detection, after segmentation you have to perform some post processing steps like morphological analysis to segment out different objects after extraction of objects you can apply some classification stuff for finer level of segmentation to remove false positive.

方法2:

播放图像像素的一些统计信息,例如制作少量灰度值和

Play with some statistics of the image pixels, like make a small data set of gray values and

  1. 将它们标记为1类和2类,例如1代表沙子,2代表前景,
  2. 从这两个类别中找出像素的均值和方差(std偏差),并计算这两个类别的概率(num_pix_per_class/total_num_pix),现在将这些统计信息存储起来以供以后使用,
  3. 现在返回到图像并逐个获取每个像素并应用高斯pdf:1/2 * pi sigma (exp(-(pix-mean)/2 * sigma));在均值位置放置较早计算的平均值,在sigma位置放置较早计算的std偏差.
  4. 应用第3阶段后,您将获得两个类别的每个像素的两个概率值,只需选择具有较高概率的类别即可.
  1. Label them class 1 and 2, for example 1 for sand and 2 for foreground,
  2. Find out mean and variance(std deviation) of pixels from both the classes, and also calculate probability for both the class ( num_pix_per_class/total_num_pix), now store these stats for later use,
  3. Now come back to image and take every pixel one by one and apply a gaussian pdf: 1/2*pisigma(exp(-(pix - mean)/2*sigma)); at the place of mean put the mean calculated earlier and at the sigma put std deviation calculated earlier.
  4. after applying stage 3 you will get two probability value for each pixel for two classes, just choose the class which have higher probability.

方法3:

方法3比上述两种方法更复杂:您可以使用一些基于纹理的操作来分割砂型纹理,但是对于应用基于纹理的方法,我建议使用监督分类而不是无监督分类(例如k均值). 您可以使用的不同纹理功能是:

Approach 3 is more complex than above two: you can use some texture based operation to segment out sand type texture, but for applying texture based method i will recommend supervised classification than unsupervised(like k-means). Different texture feature which you can use are:

基本:

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

高级:

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

PS:我认为您应该尝试方法1和2.它可以解决很多工作. :)

PS: In my opinion you should give a try to approach 1 and 2. it can solve lot of work. :)

这篇关于在嘈杂的背景下难以检测到小物体.有什么办法解决这个问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆