由于我正在尝试使用Python增强OpenCV的技能,所以我想知道从深色为主的图像中提取特定灰度的最佳方法是什么。
首先,我创建了一个测试图像,以便使用OpenCV测试不同的方法:
假设我要在此图像中提取特定的颜色并为其添加边框。现在,我在中间选择了带有颜色(33、33、34 RGB)的灰色矩形,请参见以下内容:
(这里是没有红色边框的图像,目的是为了测试您的想法:https://i.stack.imgur.com/Zf8Vb.png]
这是我到目前为止已经尝试过的方法,但是效果不佳:
img = cv2.imread(path) #Read input image
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Convert from BGR to HSV color space
saturation_plane = hsv[:, :, 1] # all black/white/gray pixels are zero, and colored pixels are above zero
_, thresh = cv2.threshold(saturation_plane, 8, 255, cv2.THRESH_BINARY) # Apply threshold on s
contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # draw all contours
contours = contours[0] if len(contours) == 2 else contours[1]
result = img.copy()
for contour in contours:
(x, y, w, h) = cv2.boundingRect(contour) # compute the bounding box for the contour
if width is equal to the width of the rectangle i want to extract:
draw contour
如果矩形的大小不固定怎么办,这样我就无法通过其宽度/高度检测到它?此外,将图像转换为灰度而不是HSV更好吗?我刚刚接触它,我想听听您实现这一目标的方式。
提前感谢。
如果已知特定颜色,则可以从gray = np.all(img == (34, 33, 33), 2)
开始。
结果是一个逻辑矩阵,其中True
为BGR
= (34, 33, 33)
,否则为False。注意:OpenCV颜色顺序是BGR,而不是RGB。
uint8
:gray = gray.astype(np.uint8)*255
findContours
图像上使用gray
。 如果您要查找蓝色矩形而不是具有非常特定的RGB值的灰色矩形,则将图像转换为HSV不会有用。
以下代码用颜色(33、33、34 RGB)找到最大尺寸的轮廓:
import numpy as np
import cv2
# Read input image
img = cv2.imread('rectangles.png')
# Gel all pixels in the image - where BGR = (34, 33, 33), OpenCV colors order is BGR not RGB
gray = np.all(img == (34, 33, 33), 2) # gray is a logical matrix with True where BGR = (34, 33, 33).
# Convert logical matrix to uint8
gray = gray.astype(np.uint8)*255
# Find contours
cnts = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2] # Use index [-2] to be compatible to OpenCV 3 and 4
# Get contour with maximum area
c = max(cnts, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(c)
# Draw green rectangle for testing
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), thickness = 2)
# Show result
cv2.imshow('gray', gray)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
[如果您不知道大多数深色的特定颜色,则可以找到所有轮廓,并搜索灰度值最低的轮廓:
import numpy as np
import cv2
# Read input image
img = cv2.imread('rectangles.png')
# Convert from BGR to Gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply threshold on gray
_, thresh = cv2.threshold(gray, 8, 255, cv2.THRESH_BINARY)
# Find contours on thresh
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2] # Use index [-2] to be compatible to OpenCV 3 and 4
min_level = 255
min_c = []
#Iterate contours, and find the darkest:
for c in cnts:
x, y, w, h = cv2.boundingRect(c)
# Ignore contours that are very thin (like edges)
if w > 5 and h > 5:
level = gray[y+h//2, x+w//2] # Get gray level of center pixel
if level < min_level:
# Update min_level abd min_c
min_level = level
min_c = c
x, y, w, h = cv2.boundingRect(min_c)
# Draw red rectangle for testing
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), thickness = 2)
# Show result
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()