Обнаружение цветовых блоков и маркировка в OpenCV - PullRequest
0 голосов
/ 05 января 2019

У меня есть план городского изображения:

Urban Plans

Я хочу обнаружить цветовые блоки на изображении и пометить их различными утилитами земель, например, зеленой зоной для газона, розовой для жилой зоны, голубым для коммерческих площадей и т. Д. И, наконец, если возможно, преобразовать из png Файл изображения для формы для использования в ArcGis. Пожалуйста, поделитесь своими идеями, спасибо. Я пробовал с помощью OpenCV Canny Edge, но все еще далек от того, что мне нужно:

import cv2
import numpy as np  

img = cv2.imread("test.png", 0)

img = cv2.GaussianBlur(img,(3,3),0)
canny = cv2.Canny(img, 50, 150)

cv2.imshow('Canny', canny)
cv2.waitKey(0)
cv2.destroyAllWindows()

Canny edge detection

Ответы [ 2 ]

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

Как говорит @Micka, ваше изображение очень легко разделить по цвету. Ниже приведен код, который делает это для темно-зеленого цвета. Вы можете легко редактировать селекторы цвета, чтобы получить другие цвета.

Обратите внимание, что в изображении присутствуют пиксельные артефакты, возможно, из-за сжатия. Текущий результат кажется хорошим, но я надеюсь, что у вас есть доступ к изображениям полного качества - тогда результат будет наилучшим.

Изображение преобразуется в HSV-цветовое пространство ( изображение ), чтобы упростить выбор цветов. ( OpenCV * +1010 *) findContours возвращает список, содержащий координаты вокруг границы для каждой найденной фигуры.

Я ничего не знаю о шейп-файлах, но, возможно, этот мог бы быть полезным.

Результат:

enter image description here

Код:

# load image
img = cv2.imread("city.png")
# add blur because of pixel artefacts 
img = cv2.GaussianBlur(img, (5, 5),5)
# convert to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 
# set lower and upper color limits
lower_val = (40, 100, 100)
upper_val = (60,255,200)
# Threshold the HSV image to get only green colors
mask = cv2.inRange(hsv, lower_val, upper_val)
# apply mask to original image
res = cv2.bitwise_and(img,img, mask= mask)
#show imag
cv2.imshow("Result", res)
# detect contours in image
im2, contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# draw filled contour on result
for cnt in contours:
    cv2.drawContours(res, [cnt], 0, (0,0,255), 2)
# detect edges in mask
edges = cv2.Canny(mask,100,100)
# to save an image use cv2.imwrite('filename.png',img)
#show images
cv2.imshow("Result_with_contours", res)
cv2.imshow("Mask", mask)
cv2.imshow("Edges", edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
0 голосов
/ 05 января 2019

Я работаю в ноутбуке Jupyter. Сначала загрузите ваше изображение:

!wget https://i.stack.imgur.com/SJxo3.png

Затем создайте массив RGBA из вашей картинки:

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

img = Image.open('SJxo3.png').convert('RGBA')
arr = np.array(img)

Мы хотим, чтобы на вашем изображении был набор разных цветов, поэтому мы создаем набор:

colors=set()
for each in arr:
    for EACH in each:
        colors.add(tuple(EACH.tolist()))

Мы хотим зациклить эти цвета и выбрать область, в которой присутствует каждый цвет. Начнем с:

for index, each in enumerate(colors):

Теперь каждый цвет является кортежем, в этом цикле for в настоящее время кортеж, и нам нужен список, поэтому мы делаем:

color=[]
for EACH in each:
    color.append(EACH)

Теперь мы создадим массив, содержащий логические значения, True, если соответствующий компонент RGBA совпадает с цветом, который мы сейчас проверяем:

boolarr=[]
for eachinarr2 in [arr == color]:
    boolarr.append(eachinarr2)

Затем мы выбираем те пиксели, которые совпадают с цветом, который мы проверяем в данный момент, то есть все четыре компонента RGBA совпадают (поэтому у нас один и тот же цвет). Мы храним эти пиксельные кординаты в indexx и INDEXX.

featurepixels=[]
for indexx, eachh in enumerate(boolarr[0]):
    for INDEXX, EACHH in enumerate(eachh):
        if EACHH.all() == True:
            featurepixels.append([indexx, INDEXX])

Теперь мы создаем сетку из нулей:

grid = np.zeros((len(arr[0]),len(arr)))

Мы меняем значение этой сетки с полными нулями на 1 в тех местах, где у нас есть пиксель от определенного цвета, который мы проверяем:

for eachhh in featurepixels:
    grid[eachhh[1],eachhh[0]] = 1

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

plt.figure()
plt.pcolormesh(grid)

Собираем все это вместе:

!wget https://i.stack.imgur.com/SJxo3.png

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

img = Image.open('SJxo3.png').convert('RGBA')
arr = np.array(img)

colors=set()
for eachH in arr:
    for eACH in eachH:
        colors.add(tuple(eACH.tolist()))

for index, each in enumerate(colors):

    if index < 30: # for debugging

        color=[]
        for EACH in each:
            color.append(EACH)



        boolarr=[]
        for eachinarr2 in [arr == color]:
            boolarr.append(eachinarr2)

        featurepixels=[]
        for indexx, eachh in enumerate(boolarr[0]):
            for INDEXX, EACHH in enumerate(eachh):
                if EACHH.all() == True:
                    featurepixels.append([indexx, INDEXX])



        grid = np.zeros((len(arr[0]),len(arr)))

        for eachhh in featurepixels:
            grid[eachhh[1],eachhh[0]] = 1

        plt.figure()
        plt.pcolormesh(grid)

Здесь вы можете создавать различные цветовые группы, чтобы большее количество пикселей классифицировалось как принадлежащие к одной функции. В этой текущей версии одно небольшое различие в цвете пикселя заставляет его классифицироваться как отдельная особенность. Поэтому я предлагаю создать эти цветовые группы / категории. Или используйте изображение, где количество цветов мало, и один элемент состоит только из одних и тех же цветов. Надеюсь, это поможет.

...