Обнаружение объектов с помощью Python

Python

Начинаем

Если у вас уже есть Jupyter Notebook или IDE, с помощью которых можно запускать установленные Python и OpenCV, то сразу переходите к разделу Выполнение.

Инструменты

Наш сегодняшний герой — Anaconda. Это бесплатный дистрибутив с открытым кодом, который помогает с установкой различных пакетов и решением разных проблем в изолированной среде.

Вот, что написано об Anaconda в Википедии:

Anaconda — это бесплатный дистрибутив с открытым кодом для программных языков Python и R. Он используется для научных вычислений (data science, приложения для машинного обучения, обработка больших наборов данных, предсказательная аналитика и т.д.) и призван упростить развертывание и управление пакетами. Управление версиями пакетов осуществляется через систему управления пакетами под названием conda. Дистрибутивом Anaconda пользуются свыше 12 млн человек; он включен в 1 400 популярных data science пакетов для Windows, Linux и MacOS.

Вот подробные уроки по скачиванию Anaconda для Windows и Linux.

Создание среды

Откройте bash (cmd) и напечатайте следующее:

$ conda create -n myEnv python=3

На предложение скачать пакеты введите y («да»).

$ source activate myEnv
$ conda install anaconda
$ conda activate myEnv
$ conda install opencv

$ jupyter notebook

Это откроет Jupyter Notebook в вашем браузере.

Несколько важных понятий

Контуры

Контуром называется кривая, которая объединяет все непрерывные точки (по границе) одного цвета или интенсивности. Контуры являются весьма полезными инструментами для анализа форм, обнаружения и распознавания объектов.

Пороговые значения

Пороговая обработка полутонового изображения (в оттенках серого) превращает его в бинарное. Вы задаете некое пороговое значение, и все значения ниже порога становятся черными, а выше — белыми.

Выполнение

Теперь у вас есть все необходимое для работы.

Знакомство с цветовой сегментацией мы начнем с простого примера.

Потерпите, скоро начнется самое интересное.

Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020Круг Омбре

Если захотите повторить все самостоятельно, то скачайте картинку отсюда.
В коде ниже я поделю данное изображение на 17 уровней серого. Затем измерю площадь каждого уровня с помощью оконтуривания.

import cv2
 import numpy as np
def viewImage(image):
 cv2.namedWindow('Display', cv2.WINDOW_NORMAL)
 cv2.imshow('Display', image)
 cv2.waitKey(0)
 cv2.destroyAllWindows()
def grayscale_17_levels (image):
 high = 255
 while(1): 
 low = high - 15
 col_to_be_changed_low = np.array([low])
 col_to_be_changed_high = np.array([high])
 curr_mask = cv2.inRange(gray, col_to_be_changed_low,col_to_be_changed_high)
 gray[curr_mask > 0] = (high)
 high -= 15
 if(low == 0 ):
 break
image = cv2.imread('./path/to/image')
 viewImage(image)
 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 grayscale_17_levels(gray)
 viewImage(gray)
Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020Это же изображение, разделенное на 17 уровней серого
def get_area_of_each_gray_level(im):
## преобразование изображения к оттенкам серого (обязательно делается до оконтуривания) 
 image = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
 output = []
 high = 255
 first = True
 while(1):
low = high - 15
 if(first == False):
# Делаем значения выше уровня серого черными. 
 ## Так они не будут обнаруживаться 
 to_be_black_again_low = np.array([high])
 to_be_black_again_high = np.array([255])
 curr_mask = cv2.inRange(image, to_be_black_again_low, 
 to_be_black_again_high)
 image[curr_mask > 0] = (0)
 
 # Делаем значения этого уровня белыми. Так мы рассчитаем 
 # их площадь
 ret, threshold = cv2.threshold(image, low, 255, 0)
 contours, hirerchy = cv2.findContours(threshold, 
 cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
if(len(contours) > 0):
output.append([cv2.contourArea(contours[0])])
 cv2.drawContours(im, contours, -1, (0,0,255), 3)
high -= 15
 first = False
 if(low == 0 ):
break
return output

В этой функции я выполняю преобразование шкалы (интенсивности) серого, которую планирую оконтурить (выделить). Для этого я задаю одинаковое значение интенсивности всем уровням, находящимся в диапазоне данной шкалы. Остальная интенсивность (меньшая и большая) становится черной.

Второй шаг — это пороговая обработка изображения. Она делается для того, чтобы цвет, который я сейчас буду оконтуривать, стал белым, а все остальные части окрасились в черный. Этот шаг мало что меняет, но выполнение его обязательно, поскольку лучше всего оконтуривание работает на черно-белых (пороговых) изображениях.

До выполнения пороговой обработки наше изображение будет выглядеть так же, с той лишь разницей, что белое кольцо окрашено серым (интенсивность серого из 10-го уровня (255–15*10 ) )

Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020Показывается только 10–й сегмент для расчета его площади
image = cv2.imread(‘./path/to/image’)
 print(get_area_of_each_gray_level(image))
 viewImage(image)
Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020Контуры 17 уровней серого в исходном изображении
Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020Массив со значениями площадей

Так мы получаем площади каждого уровня серого.

А оно нам нужно?

Перед тем, как продолжить, я бы хотела подчеркнуть всю важность данного этапа.

Я — студентка факультета компьютерной инженерии и работаю над проектом под названием «Машинное обучения для умного обнаружения и идентификации опухолей».

Цветовая сегментация изображений нужна для того, чтобы научить компьютер обнаружению опухолей. Получая МРТ снимок, программа должна определить по нему стадию развития рака. Это делается путем разделения снимка на различные полутоновые уровни, в которых самые темные области заполнены раковыми клетками, а белые — здоровыми. Затем программа рассчитывает степень принадлежности каждого полутонового уровня к раковой опухоли. Благодаря этой информации программа может не только обнаружить опухоль, но и определить ее стадию.

Данный проект основан на мягких вычислениях, нечеткой логике и машинном обучении.

Обнаружение объектов

Скачайте изображение отсюда. Только обрежьте его.

Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020

Здесь мы будем оконтуривать листок. Текстура изображения неровная и неоднородная. Несмотря на то, что на картинке не так много цветов, интенсивность зеленого также меняет и его яркость. Поэтому правильнее всего будет унифицировать зеленый цвет и свести его к одному оттенку. Тогда при оконтуривании лист будет рассматриваться единым объектом.

Примечание: ниже представлен результат оконтуривания без предварительной обработки изображения. Я хотела показать вам, как неравномерная структура листа мешает OpenCV понять, что на картинке изображен один объект.

Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020Оконтуривание без предварительной обработки. Обнаружен 531 контур
import cv2
 import numpy as np
def viewImage(image):
 cv2.namedWindow('Display', cv2.WINDOW_NORMAL)
 cv2.imshow('Display', image)
 cv2.waitKey(0)
 cv2.destroyAllWindows()

Для начала необходимо определить HSV-представление цвета. Это можно сделать путем преобразования его RGB в HSV:

## Получаем HSV-представление для зеленого цвета 
 green = np.uint8([[[0, 255, 0 ]]])
 green_hsv = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
 print( green_hsv)
Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020Зеленый HSV цвет

Конвертация изображения в HSV. С HSV проще получить полный диапазон одного цвета. H здесь означает Hue (тон), S — Saturation (насыщенность), а V — Value (значение). Мы уже знаем, что зеленый цвет — это [60, 255, 255]. Весь зеленый цвет в мире находится в диапазоне с [45, 100, 50] по [75, 255, 255], то есть с [60–15, 100, 50] по [60+15, 255, 255]. 15 — это примерное значение.

Мы берем этот диапазон и превращаем его в [75, 255, 200] или любой другой светлый цвет (третье значение должно быть сравнительно большим). Последняя цифра представляет собой яркость цвета — как раз та величина, которая «покрасит» данную область в белый после порогового преобразования изображения.

image = cv2.imread('./path/to/image.jpg')
 hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
 viewImage(hsv_img) ## 1
green_low = np.array([45 , 100, 50] )
 green_high = np.array([75, 255, 255])
 curr_mask = cv2.inRange(hsv_img, green_low, green_high)
 hsv_img[curr_mask > 0] = ([75,255,200])
 viewImage(hsv_img) ## 2
## Преобразование HSV-изображения к оттенкам серого для дальнейшего
## оконтуривания
 RGB_again = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB)
 gray = cv2.cvtColor(RGB_again, cv2.COLOR_RGB2GRAY)
 viewImage(gray) ## 3
ret, threshold = cv2.threshold(gray, 90, 255, 0)
 viewImage(threshold) ## 4
contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
 cv2.drawContours(image, contours, -1, (0, 0, 255), 3)
 viewImage(image) ## 5
Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020 Слева: изображение после конвертации в HSV (1), справа: изображение после наложения маски для унификации цвета (2)
Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020 Слева: изображение после преобразования HSV к оттенкам серого (3), справа: пороговое изображение, последний этап (4)
Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020 Конечное оконтуривание (5)

На заднем плане все еще заметна неоднородность. С этим методом мы создадим самый крупный контур, и это — конечно же, лист.

Индекс контура листа можно получить из массива contours. Оттуда же берем площадь и центр листа.

Контуры обладают и другими признаками, которые можно использовать в работе: периметр контура, выпуклая оболочка, ограничивающий прямоугольник и т.д. Здесь все описано подробнее.

def findGreatesContour(contours):
 largest_area = 0
 largest_contour_index = -1
 i = 0
 total_contours = len(contours)
 while (i < total_contours ):
 area = cv2.contourArea(contours[i])
 if(area > largest_area):
 largest_area = area
 largest_contour_index = i
 i+=1
 
 return largest_area, largest_contour_index
# Чтобы получить центр контура 
 cnt = contours[13]
 M = cv2.moments(cnt)
 cX = int(M["m10"] / M["m00"])
 cY = int(M["m01"] / M["m00"])
largest_area, largest_contour_index = findGreatesContour(contours)
print(largest_area)
 print(largest_contour_index)
print(len(contours))
print(cX)
 print(cY)
Обнаружение объектов с помощью Python — IT-МИР. ПОМОЩЬ В IT-МИРЕ 2020Результат вывода операторов

Специально для сайта ITWORLD.UZ. Новость взята с сайта NOP::Nuances of programming