Извлечение краев здания из изображения карты с использованием Python - PullRequest
0 голосов
/ 24 июня 2019

Я получил изображение карты здесь.Мне нужно извлечь края зданий для дальнейшего процесса, результат будет похож на шаг 2 для поста здесь .

Поскольку я не знаком с этим полем, это можно сделать с помощьютакие библиотеки, как OpenCV?

map image

Ответы [ 2 ]

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

Кажется, вы хотите выбрать отдельные здания, поэтому я использовал цветоделение.Стены темнее, что обеспечивает хорошее разделение в цветовом пространстве HSV .Обратите внимание, что конечный результат может быть улучшен путем увеличения масштаба и / или использования типа изображения с меньшим сжатием, например PNG.

Выбор стен
Сначала я определил хорошие значения дляразделение.Для этого я использовал этот скрипт .Я обнаружил, что наилучшим результатом было бы разделить желтый и серый отдельно, а затем объединить полученные маски.Не все стены закрылись идеально, поэтому я улучшил результат, немного закрыв маску.Результатом является маска, отображающая все стены:

enter image description here Слева направо: желтая маска, серая маска, комбинированная и затвердевшая маска

Поиск зданий
Далее я использовал findCountours , чтобы отделить здания.Поскольку контуры стен, вероятно, не будут очень полезными (поскольку стены взаимосвязаны), я использовал иерархию , чтобы найти «самые низкие» контуры (у которых нет других контуров внутри них).Это здания.

enter image description here Результат findContours: контур всех контуров в зеленом, контур отдельных зданий в красном

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

Код:

    import cv2
    import numpy as np  

    #load image and convert to hsv
    img = cv2.imread("fLzI9.jpg")

    # draw gray box around image to detect edge buildings
    h,w = img.shape[:2]
    cv2.rectangle(img,(0,0),(w-1,h-1), (50,50,50),1)

    # convert image to HSV
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    # define color ranges
    low_yellow = (0,28,0)
    high_yellow = (27,255,255)

    low_gray = (0,0,0)
    high_gray = (179,255,233)

    # create masks
    yellow_mask = cv2.inRange(hsv, low_yellow, high_yellow )
    gray_mask = cv2.inRange(hsv, low_gray, high_gray)

    # combine masks
    combined_mask = cv2.bitwise_or(yellow_mask, gray_mask)
    kernel = np.ones((3,3), dtype=np.uint8)
    combined_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_DILATE,kernel)

    # findcontours
    contours, hier = cv2.findContours(combined_mask,cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    # find and draw buildings
    for x in range(len(contours)):
            # if a contour has not contours inside of it, draw the shape filled
            c = hier[0][x][2]
            if c == -1:
                    cv2.drawContours(img,[contours[x]],0,(0,0,255),-1)

    # draw the outline of all contours
    for cnt in contours:
            cv2.drawContours(img,[cnt],0,(0,255,0),2)

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

Результат:
Со зданиями, нарисованными сплошным красным и все контуры в виде зеленого наложения

enter image description here

0 голосов
/ 24 июня 2019

Вот простой подход

  • Преобразование изображения в градации серого и размытие по Гауссу в сглаженные края
  • Пороговое изображение
  • Выполнить обнаружение края Канни
  • Найти контуры и нарисовать контуры

Пороговое изображение с использованием cv2.threshold()

enter image description here

Выполнить обнаружение Canny Edge с помощью cv2.Canny()

enter image description here

Поиск контуров с использованием cv2.findContours() и cv2.drawContours()

enter image description here

import cv2

image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
thresh = cv2.threshold(blurred, 240 ,255, cv2.THRESH_BINARY_INV)[1]
canny = cv2.Canny(thresh, 50, 255, 1)

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

for c in cnts:
    cv2.drawContours(image,[c], 0, (36,255,12), 2)

cv2.imshow('thresh', thresh)
cv2.imshow('canny', canny)
cv2.imshow('image', image)
cv2.imwrite('thresh.png', thresh)
cv2.imwrite('canny.png', canny)
cv2.imwrite('image.png', image)
cv2.waitKey(0)
...