Как соединить концы ребер, чтобы закрыть отверстия между ними? - PullRequest
12 голосов
/ 25 июня 2019

Моя задача - обнаружить трещины на поверхности почвы и рассчитать общую площадь трещины.Для этого я использовал функцию обнаружения краев Canny.

Исходное изображение

Input Image

Результат

Here

Мой следующий шаг - преобразовать плавные края в контуры, так какЯ хочу отфильтровать трещины, используя cv2.mean, и рассчитать их площадь, используя функции cv2.contourArea.На этом этапе я столкнулся с проблемой.Когда я использовал:

canny_cracks = cv2.Canny(gray, 100, 200)
contours, _ = cv2.findContours(canny_cracks, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

Он не конвертируется должным образом из-за отверстий и кончиков краев.Смотрите проблему здесь

here

Мой вопрос: как я могу соединить концы ребер, чтобы закрыть отверстие между ними?

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

Ответы [ 2 ]

5 голосов
/ 26 июня 2019

enter image description here

Исходя из вашего 2-го предоставленного изображения, вот мой подход к решению этой проблемы:

  • Размытие по Гауссу и преобразование в оттенки серого
  • Изолировать почву из горшка
    • Создать круговую маску только из почвы
    • Извлечь ROI почвы
  • Выполнить морфологические преобразования, чтобы закрыть отверстия
  • Поиск контуров и фильтрация по области контуров
  • Сумма областей для получения результата

Мы начинаем с размытия по Гауссу и преобразования изображения в оттенки серого.

image = cv2.imread('5.png')
original = image.copy()

blur = cv2.GaussianBlur(image, (3,3), 0)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))

Цель состоит в том, чтобы изолировать края почвы от краев горшка.Чтобы сделать это, мы находим внешний круг горшка с помощью cv2.HoughCircles(), уменьшаем круг, чтобы захватить область почвы, и создаем маску, используя форму исходного изображения.

circle_mask = np.zeros(original.shape, dtype=np.uint8) 
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.5, 200) 

# Convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
circle_ratio = 0.85

# Loop over the (x, y) coordinates and radius of the circles
for (x, y, r) in circles:
    # Draw the circle, create mask, and obtain soil ROI
    cv2.circle(image, (x, y), int(r * circle_ratio), (0, 255, 0), 2)
    cv2.circle(circle_mask, (x, y), int(r * circle_ratio), (255, 255, 255), -1)
    soil_ROI = cv2.bitwise_and(original, circle_mask)

We loopпо координатам, чтобы найти радиус круга.Отсюда мы рисуем самый большой внешний круг.

enter image description here

Теперь, чтобы изолировать почву и горшок, мы применяем коэффициент масштабирования, чтобы получить это

enter image description here

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

Почвамаска

enter image description here

ROI почвы

enter image description here

Ваш вопрос был

Как соединить концы ребер, чтобы закрыть отверстие между ними?

Для этого вы можете выполнить morphological transformationиспользуя cv2.morphologyEx(), чтобы закрыть отверстия, в результате чего

gray_soil_ROI = cv2.cvtColor(soil_ROI, cv2.COLOR_BGR2GRAY)
close = cv2.morphologyEx(gray_soil_ROI, cv2.MORPH_CLOSE, kernel)

enter image description here

Теперь мы находим контуры, используя cv2.findContours(), и фильтруем, используя cv2.contourArea() сминимальная пороговая площадь для удаления небольших шумов, таких как камни.Вы можете настроить минимальную площадь для контроля силы фильтра.

cnts = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

crack_area = 0
minumum_area = 25
for c in cnts:
    area = cv2.contourArea(c)
    if area > minumum_area:
        cv2.drawContours(original,[c], 0, (36,255,12), 2)
        crack_area += area

enter image description here

Наконец, мы суммируем площадь, которая дает нам общую площадь трещины

3483,5

import cv2
import numpy as np

image = cv2.imread('5.png')
original = image.copy()

blur = cv2.GaussianBlur(image, (3,3), 0)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))

circle_mask = np.zeros(original.shape, dtype=np.uint8) 
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.5, 200) 

# Convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
circle_ratio = 0.85

# Loop over the (x, y) coordinates and radius of the circles
for (x, y, r) in circles:
    # Draw the circle, create mask, and obtain soil ROI
    cv2.circle(image, (x, y), int(r * circle_ratio), (0, 255, 0), 2)
    cv2.circle(circle_mask, (x, y), int(r * circle_ratio), (255, 255, 255), -1)
    soil_ROI = cv2.bitwise_and(original, circle_mask)

gray_soil_ROI = cv2.cvtColor(soil_ROI, cv2.COLOR_BGR2GRAY)
close = cv2.morphologyEx(gray_soil_ROI, cv2.MORPH_CLOSE, kernel)

cnts = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

crack_area = 0
minumum_area = 25
for c in cnts:
    area = cv2.contourArea(c)
    if area > minumum_area:
        cv2.drawContours(original,[c], 0, (36,255,12), 2)
        crack_area += area

print(crack_area)
cv2.imshow('close', close)
cv2.imshow('circle_mask', circle_mask)
cv2.imshow('soil_ROI', soil_ROI)
cv2.imshow('original', original)
cv2.waitKey(0)
2 голосов
/ 26 июня 2019

Вы можете использовать Морфологический Закрыть . Это закрывает промежутки между белыми пикселями. Если вы введете изображение Canny в приведенный ниже скрипт, вы можете попробовать сами.

Результат:

enter image description here

Код:

    import cv2
    import numpy as np  

    # function that handles trackbar changes
    def doClose(val):
            # create a kernel based on trackbar input
            kernel = np.ones((val,val))
            # do a morphologic close
            res = cv2.morphologyEx(img,cv2.MORPH_CLOSE, kernel)
            # display result
            cv2.imshow("Result", res)

    #load image as grayscale
    img = cv2.imread("KbMHp.png",0)

    # create window and add trackbar
    cv2.namedWindow('Result')
    cv2.createTrackbar('KernelSize','Result',0,15,doClose)

    # display image
    cv2.imshow("Result", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()  
...