使用 opencv(python3 中的 cv2)检测对象是否具有 3 种颜色中的特定颜色
Detect if an object has a specific colour out of 3 colours using opencv (cv2 in python3)
我目前正在开发一个程序,可以检测我的房间里是否有红色物体或是否有蓝色物体。我周围的其余部分不是白色就是黑色。我尽量减少房间内光线的变化。
我已经成功地在给定一定色调范围的对象周围创建了一个遮罩。我想让我的程序为我打印 :
1) "Red"- 如果有红色物体
2) "Blue"- 如果有蓝色物体
我不知道如何进行。以下是我的程序,它在蓝色对象周围创建遮罩。我也给出了一些其他颜色的色调范围。这样你就可以试试了。
程序:
import cv2
import numpy as np
cam = cv2.VideoCapture(1)
while True:
_, frame = cam.read()
denoised = cv2.GaussianBlur(frame, (31, 31), 35)
hsv = cv2.cvtColor(denoised, cv2.COLOR_BGR2HSV)
lower_blue = np.array([110, 50, 50])
upper_blue = np.array([160, 255, 255])
mask = cv2.inRange(hsv, lower_red, upper_red)
res = cv2.bitwise_and(frame, frame, mask=mask)
cv2.imshow('frame', frame)
#cv2.imshow('mask', mask)
cv2.imshow('res', res)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cam.release()
cv2.destroyAllWindows()
不同颜色的色调(我不确定红色的色调,因为它不适用于某些颜色 - 我已经尝试了 Whosebug 的一些解决方案):
lower_red = np.array([0, 100, 100])
upper_red = np.array([0, 255, 255])
lower_yellow = np.array([15, 210, 20])
upper_yellow = np.array([35, 255, 255])
lower_green = np.array([29, 86, 6])
upper_green = np.array([64, 255, 2555])
lower_orange = np.array([10, 100, 20])
upper_orange = np.array([20,255,255])
以下是您可以试验的一些示例图像:
你的方法在某种程度上是正确的。但是要确定图像特定区域的颜色,需要计算颜色的已知数据集与该区域的L*a*b平均值之间的欧式距离。
- 检测您需要颜色的特定感兴趣区域。
参考以下代码确定感兴趣区域内的颜色。
class ColorLabeler:
def __init__(self):
# initialize the colors dictionary, containing the color
# name as the key and the RGB tuple as the value
colors = OrderedDict({
"red": (255, 0, 0),
"green": (0, 255, 0),
"blue": (0, 0, 255)})
# allocate memory for the L*a*b* image, then initialize
# the color names list
self.lab = np.zeros((len(colors), 1, 3), dtype="uint8")
self.colorNames = []
# loop over the colors dictionary
for (i, (name, rgb)) in enumerate(colors.items()):
# update the L*a*b* array and the color names list
self.lab[i] = rgb
self.colorNames.append(name)
# convert the L*a*b* array from the RGB color space
# to L*a*b*
self.lab = cv2.cvtColor(self.lab, cv2.COLOR_RGB2LAB)
def label(self, image, c):
# construct a mask for the contour, then compute the
# average L*a*b* value for the masked region
mask = np.zeros(image.shape[:2], dtype="uint8")
cv2.drawContours(mask, [c], -1, 255, -1)
mask = cv2.erode(mask, None, iterations=2)
mean = cv2.mean(image, mask=mask)[:3]
# initialize the minimum distance found thus far
minDist = (np.inf, None)
# loop over the known L*a*b* color values
for (i, row) in enumerate(self.lab):
# compute the distance between the current L*a*b*
# color value and the mean of the image
d = dist.euclidean(row[0], mean)
# if the distance is smaller than the current distance,
# then update the bookkeeping variable
if d < minDist[0]:
minDist = (d, i)
# return the name of the color with the smallest distance
return self.colorNames[minDist[1]]
- 以上代码是从 PyImageSearch 借用的,为了您的参考,完整的博客 post 可以在这里找到:(https://www.pyimagesearch.com/2016/02/15/determining-object-color-with-opencv/)
我目前正在开发一个程序,可以检测我的房间里是否有红色物体或是否有蓝色物体。我周围的其余部分不是白色就是黑色。我尽量减少房间内光线的变化。
我已经成功地在给定一定色调范围的对象周围创建了一个遮罩。我想让我的程序为我打印 :
1) "Red"- 如果有红色物体
2) "Blue"- 如果有蓝色物体
我不知道如何进行。以下是我的程序,它在蓝色对象周围创建遮罩。我也给出了一些其他颜色的色调范围。这样你就可以试试了。
程序:
import cv2
import numpy as np
cam = cv2.VideoCapture(1)
while True:
_, frame = cam.read()
denoised = cv2.GaussianBlur(frame, (31, 31), 35)
hsv = cv2.cvtColor(denoised, cv2.COLOR_BGR2HSV)
lower_blue = np.array([110, 50, 50])
upper_blue = np.array([160, 255, 255])
mask = cv2.inRange(hsv, lower_red, upper_red)
res = cv2.bitwise_and(frame, frame, mask=mask)
cv2.imshow('frame', frame)
#cv2.imshow('mask', mask)
cv2.imshow('res', res)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cam.release()
cv2.destroyAllWindows()
不同颜色的色调(我不确定红色的色调,因为它不适用于某些颜色 - 我已经尝试了 Whosebug 的一些解决方案):
lower_red = np.array([0, 100, 100])
upper_red = np.array([0, 255, 255])
lower_yellow = np.array([15, 210, 20])
upper_yellow = np.array([35, 255, 255])
lower_green = np.array([29, 86, 6])
upper_green = np.array([64, 255, 2555])
lower_orange = np.array([10, 100, 20])
upper_orange = np.array([20,255,255])
以下是您可以试验的一些示例图像:
你的方法在某种程度上是正确的。但是要确定图像特定区域的颜色,需要计算颜色的已知数据集与该区域的L*a*b平均值之间的欧式距离。
- 检测您需要颜色的特定感兴趣区域。
参考以下代码确定感兴趣区域内的颜色。
class ColorLabeler: def __init__(self): # initialize the colors dictionary, containing the color # name as the key and the RGB tuple as the value colors = OrderedDict({ "red": (255, 0, 0), "green": (0, 255, 0), "blue": (0, 0, 255)}) # allocate memory for the L*a*b* image, then initialize # the color names list self.lab = np.zeros((len(colors), 1, 3), dtype="uint8") self.colorNames = [] # loop over the colors dictionary for (i, (name, rgb)) in enumerate(colors.items()): # update the L*a*b* array and the color names list self.lab[i] = rgb self.colorNames.append(name) # convert the L*a*b* array from the RGB color space # to L*a*b* self.lab = cv2.cvtColor(self.lab, cv2.COLOR_RGB2LAB) def label(self, image, c): # construct a mask for the contour, then compute the # average L*a*b* value for the masked region mask = np.zeros(image.shape[:2], dtype="uint8") cv2.drawContours(mask, [c], -1, 255, -1) mask = cv2.erode(mask, None, iterations=2) mean = cv2.mean(image, mask=mask)[:3] # initialize the minimum distance found thus far minDist = (np.inf, None) # loop over the known L*a*b* color values for (i, row) in enumerate(self.lab): # compute the distance between the current L*a*b* # color value and the mean of the image d = dist.euclidean(row[0], mean) # if the distance is smaller than the current distance, # then update the bookkeeping variable if d < minDist[0]: minDist = (d, i) # return the name of the color with the smallest distance return self.colorNames[minDist[1]]
- 以上代码是从 PyImageSearch 借用的,为了您的参考,完整的博客 post 可以在这里找到:(https://www.pyimagesearch.com/2016/02/15/determining-object-color-with-opencv/)