简体   繁体   English

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

[英]How can I detect an object in image frame using OpenCV?

I am developing a rover using Raspberry Pi , that will sweep a room and pick up objects fallen on the ground . 我正在使用Raspberry Pi开发流浪者,它将扫荡整个房间并捡起掉落在地上的物体。 To detect the object , I am using a reference Image , that is taken right at the start of the rover's operation , and an Image (new Image) that is clicked every 10 seconds . 为了检测物体,我使用了参考图像,该图像在流动站操作开始时即获取,并且每10秒单击一次图像(新图像)。 To determine if there is a change in the image frame , I do a image subtraction between the reference image and the new image . 为了确定图像帧中是否有变化,我在参考图像和新图像之间进行了图像减法。 If any difference is found , it'll draw a contour around it , and if the contour area is greater than a certain threshold (cautionary step) , it concludes that there exists an object . 如果发现任何差异,它将在其周围绘制一个轮廓,并且如果轮廓区域大于某个阈值(警告步骤),则得出存在对象的结论。

I am using the following code - 我正在使用以下代码-

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 !")

The above code just uses 2 images to calculate their difference and determine if there is an object present .Please note that I have not posted the original code here that I will be using in my project . 上面的代码仅使用2张图像来计算它们之间的差异并确定是否存在对象。请注意,我没有在此处发布将在我的项目中使用的原始代码。

Now , the above code works fine for very controlled situations, say ,when the image background is very constant or there is no presence of shadow in it . 现在,上述代码适用于非常受控的情况,例如,当图像背景非常恒定或其中不存在阴影时。 But considering the fact that the rover will be moving around in the room , and there are chances that the lighting variations might trigger a false object detection , even if there is no real object in the frame . 但是考虑到流动站将在房间中四处走动的事实,并且即使框架中没有真实物体,照明变化也有可能触发虚假物体检测。 The difference might be triggered due to false contouring from shadow effects . 差异可能是由于阴影效果造成的轮廓错误而触发的。

I want to know , if there is any other way of achieving this object detection without doing foreground/background image subtraction . 我想知道,是否还有其他方法可以在不进行前景/背景图像减法的情况下实现此目标检测。 I have also considered using a ultrasonic sensor to detect the object's presence , however that is not a very reliable option . 我还考虑过使用超声波传感器来检测物体的存在,但是这不是一个非常可靠的选择。 I would prefer a Image processing based solution . 我更喜欢基于图像处理的解决方案。

Thank you . 谢谢 。

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

EDIT 1 - 编辑1-

So , I decided to change the algorithm a bit . 因此,我决定对算法进行一些更改。 I have done thresholding on both the foreground and background Images and then performed absdiff between the binary images , to obtain any frame change(object) . 我已经对前景图像和背景图像都进行了阈值处理,然后在二进制图像之间进行了抽象处理,以获得任何帧change(object)。 The code is as follows - 代码如下-

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" is followed by Erosion and Dilation . 紧随其后的是“侵蚀”和“膨胀”。 After that , I find the largest contour and determine if there is an object . 之后,我找到最大的轮廓并确定是否有物体。 The images used in the algorithm are as follows - 该算法中使用的图像如下-

  1. Background Image - Background Image 背景图片- 背景图片

  2. Foreground Image - Foreground image 前景图像- 前景图像

  3. Foreground Threshold - Foreground threshold Image 前景阈值- 前景阈值图像

  4. Background Threshold - Background threshold Image 背景阈值- 背景阈值图像

  5. Difference Image - Final Image with contour and its boundary . 具有轮廓及其边界的差分图像- 最终图像。

As you can see , the detection works fine . 如您所见,检测正常。 I have few other foreground images which I have used to test the algorithm . 我还有其他一些用于测试算法的前景图像。 They have given satisfactory results .I wanted to know , if there is any other way of achieving the same result with better efficiency . 他们给出了令人满意的结果。我想知道,是否还有其他方法可以更好地实现相同的结果。

PS- All of the foreground Images have been taken with Flash ON . PS-所有的前景图像都是在闪光灯打开的情况下拍摄的。 I have tried with Flash OFF but there seems to exist a lot of noise in the image . 我曾尝试过关闭Flash,但图像中似乎存在很多噪点。

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

EDIT 2- 编辑2-

Performance of the algo using other pictures - 使用其他图片的算法性能-

Note :- The Background Image has remained same . 注意:-背景图像保持不变。

  1. Object 1 - Foreground Image 1 对象1- 前景图像1
  2. Object 1 Detection - Foreground Image 1 Result 对象1检测- 前景图像1结果

I doubt if this problem is that much simple as you have described in the question, it will be get very complex when we move in real world scenario. 我怀疑这个问题是否像您在问题中所描述的那么简单,当我们在现实世界中移动时,它将变得非常复杂。

But anyway assuming you have small objects only present in the room then you identify them by identifying connected components in the binary image captured and choose them based on their relative pixels sizes. 但是无论如何,假设您只在房间中存在小物体,那么您可以通过识别捕获的二进制图像中的连接组件来识别它们,并根据其相对像素大小进行选择。

Here is Python implementation for the same: 这是相同的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

Image containing objects: 包含对象的图像:

原始图片

Detected objects using connected components labels: 使用连接的组件标签检测到的对象:

CNN图片

Another approach you can consider is to use structure from motion, reconstruct the environment / point cloud, and the point cluster above the floor surface belongs to your object. 您可以考虑的另一种方法是使用运动的结构,重建环境/点云,并且地板表面上方的点簇属于您的对象。 Also could combine this with your background subtraction method to remove false detection like shadows that are causing issue for that method. 也可以将其与背景扣除方法结合使用,以消除导致该方法出现问题的错误检测,例如阴影。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM