首页 文章

如何使用OpenCV检测图像帧中的对象?

提问于
浏览
1

我正在开发一个使用Raspberry Pi的流浪者,它将扫过一个房间并拾取倒在地上的物体 . 为了检测物体,我使用的是参考图像,它是在流动站操作开始时拍摄的,以及每10秒钟点击一次的图像(新图像) . 为了确定图像帧是否有变化,我在参考图像和新图像之间进行图像相减 . 如果发现任何差异,它将在其周围绘制轮廓,如果轮廓区域大于某个阈值(警告步骤),则得出结论存在一个对象 .

我使用以下代码 -

import numpy as np
import cv2,time

img=cv2.imread("object1.jpg")
img1=cv2.imread("object2.jpg")
sub=cv2.subtract(img,img1)

gray=cv2.cvtColor(sub,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(3,3),0)
_, contours, _= cv2.findContours(blur,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
c=max(contours,key=cv2.contourArea)
print(cv2.contourArea(c))

if cv2.contourArea>20000:
   print("Object detected !")

上面的代码只使用2个图像来计算它们的差异并确定是否存在对象 . 请注意,我没有在此处发布我将在我的项目中使用的原始代码 .

现在,上面的代码适用于非常受控的情况,例如,当图像背景非常恒定或者没有阴影时 . 但考虑到漫游车将在房间内移动的事实,并且即使在框架中没有真实物体,照明变化也可能触发虚假物体检测 . 由于阴影效果的错误轮廓,可能会触发差异 .

我想知道,如果有任何其他方法来实现此对象检测而不进行前景/背景图像减法 . 我还考虑使用超声波传感器来检测物体的存在,但这不是一个非常可靠的选择 . 我更喜欢基于图像处理的解决方案 .

谢谢 .

================================================== ========================

EDIT 1 -

所以,我决定稍微改变算法 . 我已经对前景和背景图像进行了阈值处理,然后在二进制图像之间执行了absdiff,以获得任何帧更改(对象) . 代码如下 -

import numpy as np
import cv2,time

img1=cv2.imread("back.jpeg")
blur1 = cv2.GaussianBlur(img1,(5,5),0)
gray1=cv2.cvtColor(blur1,cv2.COLOR_BGR2GRAY)
ret,thresh1 = cv2.threshold(gray1,65,255,cv2.THRESH_BINARY_INV)

img2=cv2.imread("front.jpeg")
blur2 = cv2.GaussianBlur(img2,(5,5),0)
gray2=cv2.cvtColor(blur2,cv2.COLOR_BGR2GRAY)
ret,thresh2 = cv2.threshold(gray2,65,255,cv2.THRESH_BINARY_INV)

diff=cv2.absdiff(thresh2,thresh1)
diff=cv2.bitwise_xor(diff,thresh1)

kernel = np.ones((2,2),np.uint8)
diff=cv2.erode(diff,kernel,iterations = 1)
diff=cv2.dilate(diff,kernel,iterations = 8)

_, contours, _= cv2.findContours(diff,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
c=max(contours,key=cv2.contourArea)
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(diff,(x,y),(x+w,y+h),(125,125,125),2)


cv2.imshow("thresh",diff)
cv2.waitKey(0)

“absdiff”之后是侵蚀和膨胀 . 之后,我找到最大的轮廓并确定是否有物体 . 算法中使用的图像如下 -

如您所见,检测工作正常 . 我用了很少的其他前景图像来测试算法 . 他们给出了令人满意的结果 . 我想知道,如果有任何其他方法可以获得更好的效率同样的结果 .

PS-所有前景图像都是在闪光灯开启时拍摄的 . 我尝试使用Flash OFF,但图像中似乎存在很多噪音 .

================================================== ===========

EDIT 2-

使用其他图片的算法表现 -

注意: - 背景图像保持不变 .

2 回答

  • 0

    我怀疑这个问题是否像你在问题中所描述的那么简单,当我们在真实场景中移动时会变得非常复杂 .

    但无论如何假设您只在房间中出现小物体,那么您可以通过识别捕获的二进制图像中的 connected components 来识别它们,并根据它们的相对像素大小选择它们 .

    这是相同的Python实现:

    img = cv2.imread('D:/Image/objects.jpg')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # binarize the image
    ret, bw = cv2.threshold(gray, 128, 255, 
    cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    
    # find connected components
    connectivity = 4
    nb_components, output, stats, centroids = 
    cv2.connectedComponentsWithStats(bw, connectivity, cv2.CV_32S)
    sizes = stats[1:, -1]; nb_components = nb_components - 1
    min_size = 250 #threshhold value for objects in scene
    img2 = np.zeros((img.shape), np.uint8)
    for i in range(0, nb_components+1):
        # use if sizes[i] >= min_size: to identify your objects
        color = np.random.randint(255,size=3)
        # draw the bounding rectangele around each object
        cv2.rectangle(img2, (stats[i][0],stats[i][1]),(stats[i][0]+stats[i][2],stats[i][1]+stats[i][3]), (0,255,0), 2)
        img2[output == i + 1] = color
    

    包含对象的图像:

    Original Image

    使用连接的组件标签检测到的对象:

    CNN image

  • 2

    您可以考虑的另一种方法是使用运动结构,重建环境/点 Cloud ,地板表面上方的点群属于您的对象 . 也可以将此与您的背景减法方法结合使用,以消除错误检测,如导致该方法问题的阴影 .

相关问题