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

2024-05-14 14:31:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一款使用覆盆子皮的漫游车,它可以清扫房间并捡起落在地上的物体。为了探测这个物体,我使用了一个参考图像,它是在探测器开始工作时拍摄的,还有一个图像(新图像)是每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 !")

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

现在,上面的代码在非常受控制的情况下运行良好,例如,当图像背景非常恒定或没有阴影存在时。但是考虑到漫游者将在房间内移动,并且即使框架中没有真实物体,灯光变化也有可能触发错误的物体检测。差异可能是由阴影效果的假轮廓触发的。

我想知道,是否有其他方法可以在不做前景/背景图像减法的情况下实现这种目标检测。我也考虑过使用超声波传感器来检测物体的存在,但这不是一个非常可靠的选择。我更喜欢基于图像处理的解决方案。

谢谢你。

一、二、二、三、四、四、四、四、四、四、四、四、四、六、六、六、六

编辑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”之后是侵蚀和扩张。之后,我找到最大的轮廓并确定是否有物体。算法中使用的图像如下-

  1. 背景图像- Background Image

  2. 前景图像-Foreground image

  3. 前景阈值-Foreground threshold Image

  4. 背景阈值-Background threshold Image

  5. 差分图像-Final Image with contour and its boundary .

如你所见,检测工作正常。我有一些其他的前景图像,我用它来测试算法。他们取得了令人满意的结果。我想知道,是否还有其他方法能以更好的效率达到同样的结果。

PS-所有的前景图像都是在闪光灯打开的情况下拍摄的。我试过关闭闪光灯,但图像中似乎存在很多噪音。

一、二、二、三、三、四、四、四、四、四、四、四、四、六、六

编辑2-

使用其他图片的算法性能-

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

  1. 对象1-Foreground Image 1
  2. 对象1检测-Foreground Image 1 Result

Tags: 对象代码图像imageimportnpdiff阈值
2条回答

我怀疑这个问题是否像你在问题中描述的那么简单,当我们进入现实世界的场景时,它会变得非常复杂。

但不管怎样,假设只有小物体存在于房间中,然后通过识别捕获的二进制图像中的连接组件来识别它们,并根据它们的相对像素大小来选择它们。

下面是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

您可以考虑的另一种方法是从运动中使用结构,重建环境/点云,并且地板曲面上方的点簇属于您的对象。也可以将其与背景减法结合起来,以移除导致该方法出现问题的错误检测(如阴影)。

相关问题 更多 >

    热门问题