Не изменяется цвет пикселей при регулировки изображения
Задача такая:
необходимо сделать скриншот
далее обработать этот скриншот
в полученном скриншоте необходимо заменить цвета на черный цвет, например, если выкручиваю ползунки красного цвета на 0, все красные цвета на скриншоте должны заменяться на черный. Но такого не происходит, в чем я ошибся?
import cv2
import numpy as np
from PIL import ImageGrab, Image
def nothing(x):
pass
# Создаём окно с ползунками
cv2.namedWindow("Color Filters")
cv2.createTrackbar("Red Min", "Color Filters", 0, 255, nothing)
cv2.createTrackbar("Red Max", "Color Filters", 255, 255, nothing)
cv2.createTrackbar("Green Min", "Color Filters", 0, 255, nothing)
cv2.createTrackbar("Green Max", "Color Filters", 255, 255, nothing)
cv2.createTrackbar("Blue Min", "Color Filters", 0, 255, nothing)
cv2.createTrackbar("Blue Max", "Color Filters", 255, 255, nothing)
if __name__ == '__main__':
# 1. Делаем скриншот
screenshot = ImageGrab.grab()
# 2. Конвертируем в массив NumPy для обработки
img_array = np.array(screenshot)
while True:
# Получаем значения с ползунков
r_min = cv2.getTrackbarPos("Red Min", "Color Filters")
r_max = cv2.getTrackbarPos("Red Max", "Color Filters")
g_min = cv2.getTrackbarPos("Green Min", "Color Filters")
g_max = cv2.getTrackbarPos("Green Max", "Color Filters")
b_min = cv2.getTrackbarPos("Blue Min", "Color Filters")
b_max = cv2.getTrackbarPos("Blue Max", "Color Filters")
# Определяем диапазоны цветов в BGR
lower_color = np.array([b_min, g_min, r_min])
upper_color = np.array([b_max, g_max, r_max])
# Создаём маску и применяем её
mask = cv2.inRange(img_array , lower_color, upper_color)
result = cv2.bitwise_and(img_array , img_array , mask=~mask) # Инвертируем маску
# Показываем результат
cv2.imshow("Original", img_array)
cv2.imshow("Filtered", result)
# Выход по клавише ESC
if cv2.waitKey(1) == 27:
break
cv2.destroyAllWindows()
Ответы (1 шт):
Для выделения отдельного цвета рекомендуют пользоваться моделью HSV, для яркости - GRAY. В случае RGB/BGR всё гораздо сложнее. cv2.inRange будет проверять каналы только если все три попадут под условие.
Например, если заданы границы [20,20,20]-[200,200,200], то за диапазон попадут лишь тёмные тона, например [10,10,10]. Синий с примесью красного [180,0,10] не попадёт.
Если вам надо именно отрезание каждого цвета по заданному диапазону, я бы предложил попробовать сделать три отдельные маски, а потом их сложить:
#сюда попадут все цвета, у которых синий канал в нужном диапазоне
lower_color = np.array([b_min, 0, 0])
upper_color = np.array([b_max, 255, 255])
#Если надо синие тона с незначительной примесью других, например до 70
lower_color = np.array([b_min, 0, 0])
upper_color = np.array([b_max, 70, 70])
#создаём маску для синего
b_mask = cv2.inRange(img_array, lower_color, upper_color)
#Аналогично создаём маски для других каналов
#Потом складываем маски
#(возможно вам понадобится bitwise_and, я всё ещё не понял что нужно)
mask = cv2.bitwise_or(b_mask, g_mask)
mask = cv2.bitwise_or(mask, r_mask)
#если нужна инверсия:
mask = cv2.bitwise_not(mask)
#напоследок накладываем маску на картинку
result = cv2.bitwise_and(img_array, img_array, mask=mask)