在特定颜色上查找并绘制 opencv 中的最大轮廓 (Python)
Find and draw the largest contour in opencv on a specific color (Python)
我正在尝试获取红皮书的最大轮廓。
我的代码有点问题,因为它得到的是最小对象(blob)的轮廓而不是最大的对象,我似乎无法弄清楚为什么会这样
我使用的代码:
camera = cv2.VideoCapture(0)
kernel = np.ones((2,2),np.uint8)
while True:
#Loading Camera
ret, frame = camera.read()
blurred = cv2.pyrMeanShiftFiltering(frame, 3, 3)
hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
lower_range = np.array([150, 10, 10])
upper_range = np.array([180, 255, 255])
mask = cv2.inRange(hsv, lower_range, upper_range)
dilation = cv2.dilate(mask,kernel,iterations = 1)
closing = cv2.morphologyEx(dilation, cv2.MORPH_GRADIENT, kernel)
closing = cv2.morphologyEx(dilation, cv2.MORPH_CLOSE, kernel)
#Getting the edge of morphology
edge = cv2.Canny(closing, 175, 175)
_, contours,hierarchy = cv2.findContours(edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Find the index of the largest contour
areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
cnt=contours[max_index]
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('threshold', frame)
cv2.imshow('edge', edge)
if cv2.waitKey(1) == 27:
break
camera.release()
cv2.destroyAllWindows()
As you can see on this picture
希望有人能提供帮助
您可以先定义一个掩码,在您要找的书的红色色调范围内。
那你就可以找到面积最大的等高线,画出书本的长方形
import numpy as np
import cv2
# load the image
image = cv2.imread("path_to_your_image.png", 1)
# red color boundaries [B, G, R]
lower = [1, 0, 20]
upper = [60, 40, 220]
# create NumPy arrays from the boundaries
lower = np.array(lower, dtype="uint8")
upper = np.array(upper, dtype="uint8")
# find the colors within the specified boundaries and apply
# the mask
mask = cv2.inRange(image, lower, upper)
output = cv2.bitwise_and(image, image, mask=mask)
ret,thresh = cv2.threshold(mask, 40, 255, 0)
if (cv2.__version__[0] > 3):
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
else:
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
if len(contours) != 0:
# draw in blue the contours that were founded
cv2.drawContours(output, contours, -1, 255, 3)
# find the biggest countour (c) by the area
c = max(contours, key = cv2.contourArea)
x,y,w,h = cv2.boundingRect(c)
# draw the biggest contour (c) in green
cv2.rectangle(output,(x,y),(x+w,y+h),(0,255,0),2)
# show the images
cv2.imshow("Result", np.hstack([image, output]))
cv2.waitKey(0)
使用您的图片:
如果你想要这本书旋转你可以使用 rect = cv2.minAreaRect(cnt)
因为你可以找到它 here.
编辑:
您还应该考虑除 RGB 之外的其他颜色空间,例如 HSV 或 HLS。通常,人们使用 HSV,因为 H 通道在阴影或过度亮度方面保持相当一致。换句话说,如果你使用 HSV 颜色空间,你应该会得到更好的结果。
具体来说,在OpenCV中Hue的范围是[0,179]
。在下图中(由 @Knight 制作),您可以在 V = 255
中找到该圆柱体的二维切片,其中水平轴为 H
,垂直轴为 [=15] =].从该图中可以看出,要捕获红色,您需要同时包含色调值的较低区域(例如,H=0 到 H=10)和较高区域(例如,H=170 到 H=179)。
使用此工具将灰度蒙版转换为矩形
def mask_to_rect(image):
'''
Give rectangle cordinates according to the mask image
Params: image : (numpy.array) Gray Scale Image
Returns: Cordinates : (list) List of cordinates [x, y, w h]
'''
# Getting the Thresholds and ret
ret,thresh = cv2.threshold(image, 0, 1, 0)
# Checking the version of open cv I tried for (version 4)
# Getting contours on the bases of thresh
if (int(cv2.__version__[0]) > 3):
contours, hierarchy = cv2.findContours(thresh.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
else:
im2, contours, hierarchy = cv2.findContours(thresh.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Getting the biggest contour
if len(contours) != 0:
# draw in blue the contours that were founded
cv2.drawContours(output, contours, -1, 255, 3)
# find the biggest countour (c) by the area
c = max(contours, key = cv2.contourArea)
x,y,w,h = cv2.boundingRect(c)
return [x, y, w, h]
结果
我正在尝试获取红皮书的最大轮廓。 我的代码有点问题,因为它得到的是最小对象(blob)的轮廓而不是最大的对象,我似乎无法弄清楚为什么会这样
我使用的代码:
camera = cv2.VideoCapture(0)
kernel = np.ones((2,2),np.uint8)
while True:
#Loading Camera
ret, frame = camera.read()
blurred = cv2.pyrMeanShiftFiltering(frame, 3, 3)
hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
lower_range = np.array([150, 10, 10])
upper_range = np.array([180, 255, 255])
mask = cv2.inRange(hsv, lower_range, upper_range)
dilation = cv2.dilate(mask,kernel,iterations = 1)
closing = cv2.morphologyEx(dilation, cv2.MORPH_GRADIENT, kernel)
closing = cv2.morphologyEx(dilation, cv2.MORPH_CLOSE, kernel)
#Getting the edge of morphology
edge = cv2.Canny(closing, 175, 175)
_, contours,hierarchy = cv2.findContours(edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Find the index of the largest contour
areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
cnt=contours[max_index]
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('threshold', frame)
cv2.imshow('edge', edge)
if cv2.waitKey(1) == 27:
break
camera.release()
cv2.destroyAllWindows()
As you can see on this picture
希望有人能提供帮助
您可以先定义一个掩码,在您要找的书的红色色调范围内。
那你就可以找到面积最大的等高线,画出书本的长方形
import numpy as np
import cv2
# load the image
image = cv2.imread("path_to_your_image.png", 1)
# red color boundaries [B, G, R]
lower = [1, 0, 20]
upper = [60, 40, 220]
# create NumPy arrays from the boundaries
lower = np.array(lower, dtype="uint8")
upper = np.array(upper, dtype="uint8")
# find the colors within the specified boundaries and apply
# the mask
mask = cv2.inRange(image, lower, upper)
output = cv2.bitwise_and(image, image, mask=mask)
ret,thresh = cv2.threshold(mask, 40, 255, 0)
if (cv2.__version__[0] > 3):
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
else:
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
if len(contours) != 0:
# draw in blue the contours that were founded
cv2.drawContours(output, contours, -1, 255, 3)
# find the biggest countour (c) by the area
c = max(contours, key = cv2.contourArea)
x,y,w,h = cv2.boundingRect(c)
# draw the biggest contour (c) in green
cv2.rectangle(output,(x,y),(x+w,y+h),(0,255,0),2)
# show the images
cv2.imshow("Result", np.hstack([image, output]))
cv2.waitKey(0)
使用您的图片:
如果你想要这本书旋转你可以使用 rect = cv2.minAreaRect(cnt)
因为你可以找到它 here.
编辑:
您还应该考虑除 RGB 之外的其他颜色空间,例如 HSV 或 HLS。通常,人们使用 HSV,因为 H 通道在阴影或过度亮度方面保持相当一致。换句话说,如果你使用 HSV 颜色空间,你应该会得到更好的结果。
具体来说,在OpenCV中Hue的范围是[0,179]
。在下图中(由 @Knight 制作),您可以在 V = 255
中找到该圆柱体的二维切片,其中水平轴为 H
,垂直轴为 [=15] =].从该图中可以看出,要捕获红色,您需要同时包含色调值的较低区域(例如,H=0 到 H=10)和较高区域(例如,H=170 到 H=179)。
使用此工具将灰度蒙版转换为矩形
def mask_to_rect(image):
'''
Give rectangle cordinates according to the mask image
Params: image : (numpy.array) Gray Scale Image
Returns: Cordinates : (list) List of cordinates [x, y, w h]
'''
# Getting the Thresholds and ret
ret,thresh = cv2.threshold(image, 0, 1, 0)
# Checking the version of open cv I tried for (version 4)
# Getting contours on the bases of thresh
if (int(cv2.__version__[0]) > 3):
contours, hierarchy = cv2.findContours(thresh.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
else:
im2, contours, hierarchy = cv2.findContours(thresh.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Getting the biggest contour
if len(contours) != 0:
# draw in blue the contours that were founded
cv2.drawContours(output, contours, -1, 255, 3)
# find the biggest countour (c) by the area
c = max(contours, key = cv2.contourArea)
x,y,w,h = cv2.boundingRect(c)
return [x, y, w, h]
结果