Какой алгоритм использовать для выделения объекта с градациями серого, аналогичными фону? - PullRequest
0 голосов
/ 19 января 2019

https://i.stack.imgur.com/3seCh.png

Я должен обнаружить объект очень близко к земле.Он имеет большую площадь, схожую с дорожным покрытием с точки зрения оттенков серого, но визуально он имеет правильную форму.Я пробовал с ручной порог, заполнение изображения и контуровНо нет хороших результатов.Контуры худшие.Моя цель - получить двоичное изображение с объектом в качестве переднего плана (белый).

1 Ответ

0 голосов
/ 20 января 2019

Это небольшое изображение: p

Вот как я подошел к вашей проблеме: сначала я обнаружил края на изображении.Затем я использовал морфологическое закрытие , чтобы соединить линии, которые расположены близко друг к другу.Это очень хорошо работает с внешними краями, контуром формы.Тогда контур этой фигуры может быть обнаружен (cv2.RETR_EXTERNAL возвращает только самый внешний контур).Из-за некоторого шума я добавил порог размера, а оставшийся контур нарисован заполненным на новом изображении.

Я добавил вторую опцию, которая более эффективна, но может не работать для остальной части вашего проекта,потому что он менее гибок для других изображений.Здесь берутся края и делается большое морфологическое закрытие, которое объединяет всю форму.Чтобы удалить шум, выполняется меньшее морфологическое отверстие.Как вы можете видеть ниже, результаты почти идентичны, хотя разница может быть больше для других изображений.

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

Результат:

enter image description here

Код:

import numpy as np 
import cv2

# load image 
image = cv2.imread("image.png")
# detect edges in image
edges = cv2.Canny(image,100,100)


#option 1: use contours
# solidify / join edges
kernel =  np.ones((10,10),np.uint8)
mask = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
# create black image with the size of image
result = np.zeros(image.shape[:2])
# detect contours in the mask (outer edges only)
im, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# draw contour 
for cnt in contours:
    if cv2.contourArea(cnt) > 100:
        # draw filled contour in white on result
        cv2.drawContours(result, [cnt], 0, (255), -1)
        # draw outline of contour in red on original image
        cv2.drawContours(image, [cnt], 0, (0,0,255), 2)


#option 2: morphology only
# solidify / join edges
kernel2 =  np.ones((20,20),np.uint8)
mask2 = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel2)
# remove noise 
kernel3 =  np.ones((5,5),np.uint8)
result2 = cv2.morphologyEx(mask2, cv2.MORPH_OPEN, kernel3)


# show image and results
cv2.imshow("image", image)
cv2.imshow("edges", edges)
cv2.imshow("Result_option1", result)
cv2.imshow("Result_option2", result2)
# release recourses
cv2.waitKey(0)
cv2.destroyAllWindows()
...