我是opencv的新手,对于一个学校项目,我需要用相机检测红色和绿色圆圈,所以我使用blobdetection,但它检测到我的两种颜色,我认为我的面具很糟糕,每种颜色都与特定动作相关联。
目前我的代码在同一页面上检测到红色和绿色的圆圈,但我希望它只检测白页上的红色圆圈。
感谢您的帮助
# Standard imports
import cv2
import numpy as np;
# Read image
im = cv2.VideoCapture(0)
# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()
# Change thresholds
params.minThreshold = 100;
params.maxThreshold = 200;
# Filter by Area.
params.filterByArea = True
params.minArea = 200
params.maxArea = 20000
# Filter by Circularity
params.filterByCircularity = True
params.minCircularity = 0.1
# Filter by Convexity
params.filterByConvexity = True
params.minConvexity = 0.1
# Filter by Inertia
params.filterByInertia = True
params.minInertiaRatio = 0.1
blueLower = (0,85,170) #100,130,50
blueUpper = (140,110,255) #200,200,130
while(1):
ret, frame=im.read()
mask = cv2.inRange(frame, blueLower, blueUpper)
mask = cv2.erode(mask, None, iterations=0)
mask = cv2.dilate(mask, None, iterations=0)
frame = cv2.bitwise_and(frame,frame,mask = mask)
# Set up the detector with default parameters.
detector = cv2.SimpleBlobDetector_create(params)
# Detect blobs.
keypoints = detector.detect(mask)
# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures the size of the circle corresponds to the size of blob
im_with_keypoints = cv2.drawKeypoints(mask, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# Display the resulting frame
frame = cv2.bitwise_and(frame,im_with_keypoints,mask = mask)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
im.release()
cv2.destroyAllWindows()
编辑1:代码更新
现在我遇到了一个未检测到完整圆圈的问题。
# Standard imports
import cv2
import numpy as np;
# Read image
im = cv2.VideoCapture(0)
while(1):
ret, frame=im.read()
lower = (130,150,80) #130,150,80
upper = (250,250,120) #250,250,120
mask = cv2.inRange(frame, lower, upper)
lower, contours, upper = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
blob = max(contours, key=lambda el: cv2.contourArea(el))
M = cv2.moments(blob)
center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
canvas = im.copy()
cv2.circle(canvas, center, 2, (0,0,255), -1)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
im.release()
cv2.destroyAllWindows()
答案 0 :(得分:1)
你需要弄清楚你的果岭的BGR数字是什么(让我们为了论证[0, 255, 0]
而说),然后创建一个遮挡绿色周围公差之外的任何颜色的面具:
mask = cv2.inRange(image, lower, upper)
逐步查看this教程。
使用较低和较高的游戏来获得正确的行为。然后你可以在面具中找到轮廓:
_, contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_NONE)
然后浏览contours
列表找到最大的一个(过滤掉任何可能的噪音):
blob = max(contours, key=lambda el: cv2.contourArea(el))
那是你的最后一次'。您可以通过以下方式找到该中心:
M = cv2.moments(blob)
center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
您可以将此中心绘制到图像的副本上,以便进行检查:
canvas = im.copy()
cv2.circle(canvas, center, 2, (0,0,255), -1)
显然,这假设图像中只有一个绿球而没有其他绿色。但这是一个开始。
编辑 - 对第二次发布的回复
我认为以下内容应该有效。我还没有对它进行过测试,但你应该至少可以使用画布和掩码进行更多调试:
# Standard imports
import cv2
import numpy as np;
# Read image
cam = cv2.VideoCapture(0)
while(1):
ret, frame = cam.read()
if not ret:
break
canvas = frame.copy()
lower = (130,150,80) #130,150,80
upper = (250,250,120) #250,250,120
mask = cv2.inRange(frame, lower, upper)
try:
# NB: using _ as the variable name for two of the outputs, as they're not used
_, contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
blob = max(contours, key=lambda el: cv2.contourArea(el))
M = cv2.moments(blob)
center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
cv2.circle(canvas, center, 2, (0,0,255), -1)
except (ValueError, ZeroDivisionError):
pass
cv2.imshow('frame',frame)
cv2.imshow('canvas',canvas)
cv2.imshow('mask',mask)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
im.release()
cv2.destroyAllWindows()
答案 1 :(得分:1)
如果您想按颜色进行过滤,则应使用HSV颜色空间以获得更好的效果。
ret, frame=im.read()
frame = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)# 将此添加到您的代码中
mask = cv2.inRange(frame, blueLower, blueUpper)