颜色检测对网络摄像头图像效率不高

Color Detection not efficient on webcam images

我正在做一个项目,试图检测特定表面(竞技场)上的绿色和红色圆圈。当我尝试使用该竞技场的数字版本(PNG 图像)执行此操作时,我可以成功检测到两个彩色圆圈。

这是表面的数字图像:

现在,我在 flex 上打印了这个竞技场(没有那两个彩色圆圈),并手动将彩色圆形硬币放在上面。但是在通过 1.3 MP 网络摄像头捕获其图像后,颜色检测不起作用并给出错误结果。

这是通过网络摄像头拍摄的印刷竞技场:

为什么检测不到颜色?我需要对网络摄像头图像进行 post 处理吗? 我试过通过 cv2.filter2D 锐化图像,但它也没有用。

这是从我的 Python 代码中检测红色圆圈的片段:

ip_image=cv2.imread("image.png")
kernel = np.array([[-1,-1,-1],[-1,9,-1],[-1,-1,-1]])
ip_image=cv2.filter2D(ip_image,-1,kernel)
#cv2.imshow("Hi",ip_image)
hsv=cv2.cvtColor(ip_image,cv2.COLOR_BGR2HSV)
red_low=np.array([0,255,255])
red_up=np.array([10,255,255])
mask0= cv2.inRange(hsv,red_low,red_up)
red_low=np.array([170,255,255])
red_up=np.array([180,255,255])
mask1=cv2.inRange(hsv,red_low,red_up)
mask_red=mask1+mask0
r_img= ip_image.copy()
r_img[np.where(mask_red==0)] = 0
gray_img0 = cv2.cvtColor(r_img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_img0,0,255,0)
M = cv2.moments(thresh)
rX=int(M["m10"] / M["m00"])
rY=int(M["m01"] / M["m00"])
cv2.circle(ip_image,(rX,rY), 17, (255,255,255), 2)
cv2.imshow("Output",ip_image)

此外,cv2.threshold() 中的第四个参数在设置为“0”时可以正确处理数字图像,而对于网络摄像头图像,它会在以下行抛出零除法错误:

rX=int(M["m10"]/M["m00"])

由于光线的变化,硬阈值无法帮助您找到所需的圆圈,您应该考虑目标颜色的间隔。例如找到所有绿色值在 200 到 255 之间的像素(通过反复试验设置)以确保您始终捕捉到小圆圈。

现在图像的其他一些部分也可能在阈值处理后幸存下来。在这种情况下,您可以通过霍夫圆检测器等形状分析方法或根据它们的大小来过滤那些不需要的部分。

绝对值得尝试改善初始条件(视角、光线、分辨率等)。网络摄像头产生的当前结果有些糟糕,因此与其花费大量时间进行修复,不如使用更便宜的硬件。

您可以使用一些奇特的方法来改善您的形象,但是,最好有更多有价值的输入。

无论如何,这是有用的部分。您的标记不是唯一的,因此任何使用颜色的尝试都需要额外的形状分析。以下是使用颜色分割的一些结果:

如您所见,某些区域的颜色非常相似。 我使用更高级的颜色相似度函数来处理复杂的情况。基本上,我指定了一些阈值的红色和绿色。 Delta E 将是正确的起点。让我们看看实际的形状:

根据这些结果,您可以进行简单的形状分析或仅比较区域以找到您的标记。我希望有更多独特的颜色和更好的初始条件。

无论如何,任何现实生活场景都需要您非常小心地处理颜色:

(see in action)

类似问题: