Мы знаем, что фон имеет зеленый цвет и отличается от объекта по цвету, поэтому я предлагаю использовать цветовой порог. Для этого я написал простой код OpenCV Python, чтобы продемонстрировать результаты.
Сначала нам нужно установить OpenCV.
sudo apt update
pip3 install opencv-python
# verify installation
python3 -c "import cv2; print(cv2.__version__)"
Затем мы создадим скрипт с именем * 1006. * в одном каталоге с изображениями.
import cv2
import numpy as np
def show_result(winname, img, wait_time):
scale = 0.2
disp_img = cv2.resize(img, None, fx=scale, fy=scale)
cv2.imshow(winname, disp_img)
cv2.waitKey(wait_time)
img = cv2.imread('skull.jpg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# define range of green color in HSV
lower_green = np.array([70, 200, 100])
upper_green = np.array([90, 255, 255])
# Threshold the HSV image to extract green color
mask = cv2.inRange(hsv, lower_green, upper_green)
mask = cv2.bitwise_not(mask)
#cv2.imwrite('mask.png', mask)
show_result('mask', mask, 0)
cv2.destroyAllWindows()
Вы можете легко найти учебное пособие по цветовым операциям HSV, используя OpenCV. Я не буду go рассматривать функции, используемые здесь, но важна одна часть. Операции с изображениями обычно выполняются в цветовом пространстве RGB, которое содержит красные, зеленые и синие компоненты. Тем не менее, HSV больше похож на систему человеческого зрения, которая содержит компоненты оттенка, насыщенности и значения. Вы можете найти преобразование здесь . Поскольку мы разделяем цвет на основе нашего восприятия, HSV больше подходит для этой задачи.
Важной частью является правильный выбор пороговых значений. При осмотре я выбрал около 80 для оттенка (что составляет максимум 180) и выше 200 и 100 для насыщенности и значения (максимум 255) соответственно. Вы можете напечатать значения определенного пикселя следующими строками:
rows,cols,channels = hsv.shape
print(hsv[row, column])
Обратите внимание, что начало координат находится в левом верхнем углу.
Вот результат:
Может потребоваться две вещи. Один делает операцию для набора изображений, который тривиально использовать для циклов. Другая причина в том, что если вам не нравится какая-то часть результата, вы можете узнать местоположение пикселя и соответственно изменить пороговое значение. Это возможно при использовании событий мыши.
for i in range(1, 100):
img = imread(str(i) + '.jpg')
def mouse_callback(event, x, y, flags, params):
if event == cv2.EVENT_LBUTTONDOWN:
row = y
column = x
print(row, column)
winname = 'img'
cv2.namedWindow(winname)
cv2.setMouseCallback(winname, mouse_callback)
Имейте в виду, что функция show_result
изменяет размер изображения по коэффициенту масштабирования.
Если вы не хотите иметь дело с позициями пикселей Скорее, вы хотите сгладить результаты, вы можете применить морфологические преобразования . Особенно открытие и закрытие сделают работу.
kernel = np.ones((11,11), np.uint8)
opened = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
closed = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
Результат с открытием (ядро = 11x11):