Если известен указанный c цвет, вы можете начать с 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
изображении.
Преобразование изображения в HSV не имеет смысла, если вы хотите найти синий прямоугольник, но не серый прямоугольник с очень конкретными c значениями RGB.
Следующий код находит контур максимального размера с цветом (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()
Результат:
серый:
img:
Если вы не знаете специфику c цвет в основном темных цветов, вы можете найти все контуры и найти тот, у которого наименьшее значение серого:
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()
Результат: