我这里有一个检测激光的代码,但我在不同的光条件下遇到了问题。所以我想如果我添加一个代码来检查那个光是不是一个圆,我可能会解决这个问题。
问题是我不知道如何在这里应用它。这是激光在遮罩中的样子。
我希望你能帮助我完成我的代码。
下面是我的代码:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) convert from bgr to hsv color space
lower = np.array([0,0,255]) #range of laser light
upper = np.array([255, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
maskcopy = mask.copy()
circles = cv2.HoughCircles(maskcopy, cv2.HOUGH_GRADIENT, 1, 500,
param1 = 20, param2 = 10,
minRadius = 1, maxRadius = 3)
_,cont,_ = cv2.findContours(maskcopy, cv2.RETR_LIST,
cv2.CHAIN_APPROX_SIMPLE)
if circles is not None:
circles = np.round(circles[0,:]).astype('int')
for(x,y,r) in circles:
cv2.circle(frame, (x,y), r, (0,255,0),4)
cv2.imshow('mask', mask)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
截图:
发布于 2018-06-08 22:29:28
我试过一次类似的方法,对我来说最好的解决方案是:
(我将你的图片保存到我的硬盘上,并做了一个示例代码)
import cv2
import math
img = cv2.imread('laser.jpg')
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_image,100,255,cv2.THRESH_BINARY)
im2, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
area = sorted(contours, key=cv2.contourArea, reverse=True)
contour = area[0]
(x,y),radius = cv2.minEnclosingCircle(contour)
radius = int(radius)
area = cv2.contourArea(contour)
circ = 4*area/(math.pi*(radius*2)**2)
cv2.drawContours(img, [contour], 0, (0,255,0), 2)
cv2.imshow('img', img)
print(circ)
所以这个想法是用cv2.findContours
(激光点)找到你的等高线,然后用圆圈包围它,这样你就可以得到半径,然后用cv2.contourArea
得到你的等高线的面积,并用公式circ = 4*area/(math.pi*(radius*2)**2)
检查它的圆度。完美的citrcle将返回结果1。它越接近0,你的轮廓就越少(如下图所示)。希望它能帮上忙!
所以你的代码应该是这样的,它不会返回任何错误(试过了,它工作了)
import cv2
import numpy as np
import math
cap = cv2.VideoCapture(0)
while True:
try:
ret, frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) #convert from bgr to hsv color space
lower = np.array([0,0,255]) #range of laser light
upper = np.array([255, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
im2, contours, hierarchy = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
area = sorted(contours, key=cv2.contourArea, reverse=True)
contour = area[0]
(x,y),radius = cv2.minEnclosingCircle(contour)
radius = int(radius)
area = cv2.contourArea(contour)
circ = 4*area/(math.pi*(radius*2)**2)
print(circ)
except:
pass
cv2.imshow('mask', mask)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
发布于 2018-06-08 20:50:50
我想出了一个不同方法的解决方案。
我的想法是创建一个圆圈,圆心在蒙版白色区域的中心,半径等于蒙版白色区域宽度的一半。然后我检查这个圆圈和蒙版有多相似。
代码如下:
white = np.where(mask>250) # you can also make it == 255
white = np.asarray(white)
minx = min(white[0])
maxx = max(white[0])
miny = min(white[1])
maxy = max(white[1])
radius = int((maxx-minx)/2)
cx = minx + radius
cy = miny + radius
black = mask.copy()
black[:,:]=0
cv2.circle(black, (cy,cx), radius, (255,255,255),-1)
diff = cv2.bitwise_xor(black, mask)
diffPercentage = len(diff>0)/diff.size
print (diffPercentage)
然后,你必须想出对你来说“相似”的百分比阈值是多少。
上面的代码是从磁盘读取掩码进行测试的,但视频只是一系列图像。没有你的摄像头输入,我不能用视频测试代码,但它应该是这样工作的:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower = np.array([0,0,255]) #range of laser light
upper = np.array([255, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
white = np.where(mask>250) # you can also make it == 255
white = np.asarray(white)
minx = min(white[0])
maxx = max(white[0])
miny = min(white[1])
maxy = max(white[1])
radius = int((maxx-minx)/2)
cx = minx + radius
cy = miny + radius
black = mask.copy()
black[:,:]=0
cv2.circle(black, (cy,cx), radius, (255,255,255),-1)
diff = cv2.bitwise_xor(black, mask)
diffPercentage = len(diff>0)/diff.size
print (diffPercentage)
cv2.imshow('mask', mask)
cvw.imshow('diff', diff)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
https://stackoverflow.com/questions/50758799
复制相似问题