试图在激光笔 OpenCV 上画圆
Trying to draw circle on Laser pointer, OpenCV
所以我从@bradmontgomer 的Github 那里获取了代码并尝试对其进行修改。该代码首先将帧转换为 HSV 颜色 space,将视频帧拆分为颜色通道,然后对 HSV 组件执行与以识别激光。我无法找到检测到的激光点的轮廓。这是我的代码;
def threshold_image(self, channel):
if channel == "hue":
minimum = self.hue_min
maximum = self.hue_max
elif channel == "saturation":
minimum = self.sat_min
maximum = self.sat_max
elif channel == "value":
minimum = self.val_min
maximum = self.val_max
(t, tmp) = cv2.threshold(
self.channels[channel], # src
maximum, # threshold value
0, # we dont care because of the selected type
cv2.THRESH_TOZERO_INV #t type
)
(t, self.channels[channel]) = cv2.threshold(
tmp, # src
minimum, # threshold value
255, # maxvalue
cv2.THRESH_BINARY # type
)
if channel == 'hue':
# only works for filtering red color because the range for the hue is split
self.channels['hue'] = cv2.bitwise_not(self.channels['hue'])
def detect(self, frame):
# resize the frame, blur it, and convert it to the HSV
# color space
frame = imutils.resize(frame, width=600)
hsv_img = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# split the video frame into color channels
h, s, v = cv2.split(hsv_img)
self.channels['hue'] = h
self.channels['saturation'] = s
self.channels['value'] = v
# Threshold ranges of HSV components; storing the results in place
self.threshold_image("hue")
self.threshold_image("saturation")
self.threshold_image("value")
# Perform an AND on HSV components to identify the laser!
self.channels['laser'] = cv2.bitwise_and(
self.channels['hue'],
self.channels['value']
)
self.channels['laser'] = cv2.bitwise_and(
self.channels['saturation'],
self.channels['laser']
)
# Merge the HSV components back together.
hsv_image = cv2.merge([
self.channels['hue'],
self.channels['saturation'],
self.channels['value'],
])
thresh = cv2.threshold(self.channels['laser'], 25, 255, cv2.THRESH_BINARY)[1]
#find contours in the mask and initialize the current
#(x, y) center of the ball
#cnts = cv2.findContours(self.channels['laser'].copy(), cv2.RETR_EXTERNAL,
#cv2.CHAIN_APPROX_SIMPLE)
(_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
center = None
# only proceed if at least one contour was found
if len(cnts) > 0:
# find the largest contour in the mask, then use
# it to compute the minimum enclosing circle and
# centroid
c = max(cnts, key=cv2.contourArea)
((x, y), radius) = cv2.minEnclosingCircle(c)
M = cv2.moments(c)
center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
# only proceed if the radius meets a minimum size
if radius > 10:
# draw the circle and centroid on the frame,
# then update the list of tracked points
cv2.circle(frame, (int(x), int(y)), int(radius),
(0, 255, 255), 2)
cv2.circle(frame, center, 5, (0, 0, 255), -1)
cv2.imshow('LaserPointer', self.channels['laser'])
################################################
return hsv_image
我在行 "if len(cnts) > 0:" 中得到的 cnts 大于 0,但看不到激光指示器中绘制的圆圈。
还有另一个函数 (display()) 正在显示激光帧 (self.channel['laser']),
def display(self, img, frame):
"""Display the combined image and (optionally) all other image channels
NOTE: default color space in OpenCV is BGR.
"""
cv2.imshow('RGB_VideoFrame', frame)
cv2.imshow('LaserPointer', self.channels['laser'])
我注释掉了此函数中的这些 cv2.iamshow 行,然后我能够看到激光指示器周围的圆圈。这是因为现在函数 "detect(self, frame):" 中 cv2.iamshow 行的帧被执行了。然后我在指针上应用了进一步的编码来检测它的位置。
所以我从@bradmontgomer 的Github 那里获取了代码并尝试对其进行修改。该代码首先将帧转换为 HSV 颜色 space,将视频帧拆分为颜色通道,然后对 HSV 组件执行与以识别激光。我无法找到检测到的激光点的轮廓。这是我的代码;
def threshold_image(self, channel):
if channel == "hue":
minimum = self.hue_min
maximum = self.hue_max
elif channel == "saturation":
minimum = self.sat_min
maximum = self.sat_max
elif channel == "value":
minimum = self.val_min
maximum = self.val_max
(t, tmp) = cv2.threshold(
self.channels[channel], # src
maximum, # threshold value
0, # we dont care because of the selected type
cv2.THRESH_TOZERO_INV #t type
)
(t, self.channels[channel]) = cv2.threshold(
tmp, # src
minimum, # threshold value
255, # maxvalue
cv2.THRESH_BINARY # type
)
if channel == 'hue':
# only works for filtering red color because the range for the hue is split
self.channels['hue'] = cv2.bitwise_not(self.channels['hue'])
def detect(self, frame):
# resize the frame, blur it, and convert it to the HSV
# color space
frame = imutils.resize(frame, width=600)
hsv_img = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# split the video frame into color channels
h, s, v = cv2.split(hsv_img)
self.channels['hue'] = h
self.channels['saturation'] = s
self.channels['value'] = v
# Threshold ranges of HSV components; storing the results in place
self.threshold_image("hue")
self.threshold_image("saturation")
self.threshold_image("value")
# Perform an AND on HSV components to identify the laser!
self.channels['laser'] = cv2.bitwise_and(
self.channels['hue'],
self.channels['value']
)
self.channels['laser'] = cv2.bitwise_and(
self.channels['saturation'],
self.channels['laser']
)
# Merge the HSV components back together.
hsv_image = cv2.merge([
self.channels['hue'],
self.channels['saturation'],
self.channels['value'],
])
thresh = cv2.threshold(self.channels['laser'], 25, 255, cv2.THRESH_BINARY)[1]
#find contours in the mask and initialize the current
#(x, y) center of the ball
#cnts = cv2.findContours(self.channels['laser'].copy(), cv2.RETR_EXTERNAL,
#cv2.CHAIN_APPROX_SIMPLE)
(_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
center = None
# only proceed if at least one contour was found
if len(cnts) > 0:
# find the largest contour in the mask, then use
# it to compute the minimum enclosing circle and
# centroid
c = max(cnts, key=cv2.contourArea)
((x, y), radius) = cv2.minEnclosingCircle(c)
M = cv2.moments(c)
center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
# only proceed if the radius meets a minimum size
if radius > 10:
# draw the circle and centroid on the frame,
# then update the list of tracked points
cv2.circle(frame, (int(x), int(y)), int(radius),
(0, 255, 255), 2)
cv2.circle(frame, center, 5, (0, 0, 255), -1)
cv2.imshow('LaserPointer', self.channels['laser'])
################################################
return hsv_image
我在行 "if len(cnts) > 0:" 中得到的 cnts 大于 0,但看不到激光指示器中绘制的圆圈。
还有另一个函数 (display()) 正在显示激光帧 (self.channel['laser']),
def display(self, img, frame):
"""Display the combined image and (optionally) all other image channels
NOTE: default color space in OpenCV is BGR.
"""
cv2.imshow('RGB_VideoFrame', frame)
cv2.imshow('LaserPointer', self.channels['laser'])
我注释掉了此函数中的这些 cv2.iamshow 行,然后我能够看到激光指示器周围的圆圈。这是因为现在函数 "detect(self, frame):" 中 cv2.iamshow 行的帧被执行了。然后我在指针上应用了进一步的编码来检测它的位置。