我试图从我的网络摄像头Feed中检测出球的颜色。我尝试的颜色是红绿蓝和黄色。我写了下面给出的代码。但它显示即使没有球也随机检测到蓝色球。并且当显示绿色或红色时,在其间突然出现蓝色球。请建议一些方法,使其更准确,如何包括黄色。
enter code here
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
lower_green = np.array([45,140,50])
upper_green = np.array([75,255,255])
lower_red = np.array([160,140,50])
upper_red = np.array([180,255,255])
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
foundred = False
while(True):
success,frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
hsv = cv2.medianBlur(hsv,5)
imgThreshHighred = cv2.inRange(hsv, lower_red, upper_red)
imgThreshHighgreen = cv2.inRange(hsv, lower_green, upper_green)
imgThreshHighblue = cv2.inRange(hsv, lower_blue, upper_blue)
circlesred = cv2.HoughCircles(imgThreshHighred,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)
circlesblue = cv2.HoughCircles(imgThreshHighblue,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)
circlesgreen = cv2.HoughCircles(imgThreshHighgreen,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)
if circlesred is not None:
print "found red"
# print circlesred
if circlesgreen is not None:
print "found green"
# print circlesgreen
if circlesblue is not None:
print "found blue"
# print circlesblue
else:
print "no ball"
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
答案 0 :(得分:1)
你正在观察假阳性,并且正如flamelite所指出的那样,它们是由你的图像中属于目标的HSV范围内的其他区域引起的。对于您当前的方法,这是正常的。基于颜色区域检测的检测几乎肯定会在自然图像中产生误报。为了减少或消除误报,你有两种策略。
<强> 1。使用更具体的颜色模型。您可以使用更薄的HSV范围(如熔炉建议)来执行此操作,或者您可以使用OpenCV的高斯混合建模方法为#!/usr/bin/python3
# 2018.01.16 13:07:05 CST
# 2018.01.16 13:54:39 CST
import cv2
import numpy as np
def alphaBlend(img1, img2, mask):
""" alphaBlend img1 and img 2 (of CV_8UC3) with mask (CV_8UC1 or CV_8UC3)
"""
if mask.ndim==3 and mask.shape[-1] == 3:
alpha = mask/255.0
else:
alpha = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)/255.0
blended = cv2.convertScaleAbs(img1*(1-alpha) + img2*alpha)
return blended
img = cv2.imread("test.png")
H,W = img.shape[:2]
mask = np.zeros((H,W), np.uint8)
cv2.circle(mask, (325, 350), 40, (255,255,255), -1, cv2.LINE_AA)
mask = cv2.GaussianBlur(mask, (21,21),11 )
blured = cv2.GaussianBlur(img, (21,21), 11)
blended1 = alphaBlend(img, blured, mask)
blended2 = alphaBlend(img, blured, 255- mask)
cv2.imshow("blened1", blended1);
cv2.imshow("blened2", blended2);
cv2.waitKey();cv2.destroyAllWindows()
类训练每个球的高斯模型。这可用于分段,并将替换调用EM
的3行代码。在这两种方法中,您必须注意您的训练图像与您的测试图像相匹配(特别是光照类似,并且自动白平衡的颜色变化,如果有效,则在训练图像中表示)。
<强> 2。使用其他功能/信息。如果您仍然留下误报,则需要使用颜色以外的属性消除它们。例如,视频中球的半径是近似恒定的吗?如果是这样,您可以拒绝明显太小或太大的区域。这可能非常有效。背景不动吗?如果是这样,您可以尝试使用OpenCV的背景减法方法来消除误报。你一次只能看到一个球吗?如果是这样的话,你可以使用例如高斯颜色模型在每个区域的对数似然的平均值来拒绝除了最可能的“球”区域之外的所有区域。
答案 1 :(得分:0)
我想在你的图像框架中的某个点上必须有一些小部件,其色调值在蓝色范围内,这就是为什么你得到蓝色作为误报的原因。以下是我的建议:
所有三类像素中的最大值将为您提供真实的球色。
我希望有所帮助。