Я пытаюсь извлечь определенный цвет из изображения в пределах определенного диапазона RGB, используя модуль cv2. В приведенном ниже примере я пытаюсь изолировать огонь от выхлопа космического челнока между значениями RGB желтого и белого, а затем распечатать процент значений RGB в этом диапазоне по сравнению с остальной частью изображения.
Вот мой минимальный рабочий пример:
import cv2
import numpy as np
from matplotlib import pyplot as plt
import imageio
img = imageio.imread(r"shuttle.jpg")
plt.imshow(img)
Это выходное изображение. Это из Википедии.
img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
color1 = (255,255,0) #yellow
color2 = (255,255,255) #white
boundaries = [([color1[0], color1[1], color1[2]], [color2[0], color2[1], color2[2]])]
for (lower, upper) in boundaries:
lower = np.array(lower, dtype=np.uint8)
upper = np.array(upper, dtype=np.uint8)
mask = cv2.inRange(img, lower, upper)
output = cv2.bitwise_and(img, img, mask=mask)
ratio = cv2.countNonZero(mask)/(img.size/3)
print('pixel percentage:', np.round(ratio*100, 2))
plt.imshow(mask)
Однако, похоже, это не работает, потому что я получаю 0% пикселей между желтым и белым значениями. Я не совсем уверен, где я иду не так:
[([255, 255, 0], [255, 255, 255])]
pixel percentage: 0.0
А выходной график выглядит пустым с сине-фиолетовым изображением:
Примечание. Я не использовал встроенные средства просмотра изображений в cv2, такие как cv2.imshow (), cv2.waitKey () и cv2.destroyAllWindows (), потому что их вызовы приводили к сбою моей IDE (Spyder 3.3.1) в Windows 8.1. Не уверен, что именно поэтому изображение выглядит синим / фиолетовым?
Также, когда я просто пытаюсь вывести исходное изображение, оно появляется в странном перевернутом цветовом формате:
plt.imshow(img)
Во всяком случае, я пытался следовать аналогичному методу, чтобы обнаружить определенный диапазон цветов, ранее описанный здесь 1037 * однако этот конкретный метод доставлял мне проблемы во время компиляции и несколько раз зависал и приводил к падению компьютера, когда я пытался реализовать что-то вроде этого:
imask = mask>0
exhaust_color = np.zeros_like(img, np.uint8)
green[imask] = img[exhaust_color]
Полагаю, что я пытаюсь добиться здесь чего-то вроде изображения ниже, где отображаются только цвета между желтым и белым, а затем распечатать процент пикселей, состоящих из этих цветов. Для изображения ниже я только что отфильтровал все цвета ниже RGB (255, 255, 0) с помощью основного программного обеспечения для обработки изображений.
Есть ли способ добиться этого с помощью кода, который я уже написал или аналогичного?
РЕДАКТ. 1: Следуйте приведенным ниже советам, чтобы сначала преобразовать в цветовое пространство HSV. Однако это все еще не работает, и процент пикселей от желтого до белого все еще равен 0% Выходные графики все те же и показывают все черное или фиолетовое. Также мне удалось заставить работать cv2.imshow (), передав 1 в cs2.waitKey (1). (По какой-то причине не работает с 0).
#CONVERT TO HSV COLORS
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
color1 = np.uint8([[[0, 255, 255 ]]]) #yellow
color2 = np.uint8([[[255, 255, 255]]]) #white
hsv_color1 = cv2.cvtColor(color1,cv2.COLOR_BGR2HSV)
hsv_color2 = cv2.cvtColor(color2,cv2.COLOR_BGR2HSV)
print(hsv_color1)
print(hsv_color2)
#Define threshold color range to filter
mask = cv2.inRange(hsv_img, hsv_color1, hsv_color2)
# Bitwise-AND mask and original image
res = cv2.bitwise_and(hsv_img, hsv_img, mask=mask)
ratio = cv2.countNonZero(mask)/(hsv_img.size/3)
print('pixel percentage:', np.round(ratio*100, 2))
#plt.imshow(mask)
cv2.imshow('mask',res)
cv2.waitKey(1)
выход
[[[ 30 255 255]]]
[[[ 0 0 255]]]
pixel percentage: 0.0