OpenCV中色块的检测与标注

2024-06-01 14:16:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一张城市规划图如下:

Urban Plans

我想检测图像中的色块,并用不同的土地公用设施对其进行标记,例如,绿地用于草坪,粉色用于住宅区,浅蓝色用于商业区等。最后,如果可能,将png图片转换为形状文件以供ArcGis使用。请分享你的想法,谢谢。 我尝试过使用OpenCV Canny边缘检测,但仍远未达到我的要求:

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


Tags: 标记图像importimgpngcv2土地公用设施
2条回答

我在Jupyter笔记本上工作。首先下载您的图像:

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

然后从您的pic创建一个RGBA数组:

^{pr2}$

我们希望在您的图片上有一组不同的颜色,因此我们创建了一组:

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)

我们现在创建一个包含布尔值的数组,如果相应的RGBA组件与我们当前检查的颜色相同,则为True:

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

然后我们选择与我们当前检查的颜色相同的像素,即RGBA的四个分量都匹配(因此我们有相同的颜色)。我们将这些像素cordinate存储在indexxINDEXX中。在

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)

从这里你可以创建不同的颜色组,这样更多的像素将被归类为同一个特征。在当前的版本中,像素颜色的一个微小差异导致它被归类为一个单独的特征。所以我建议创建那些颜色组/类别。或者使用颜色较少的图像,而单个特征只包含相同的颜色。希望这有帮助。在

正如@Micka所说,你的形象在颜色上很容易区分。我已经提供了下面的代码,为深绿色。你可以很容易地编辑颜色选择器来获得其他颜色。在

请注意,图像中有像素瑕疵,可能是由于压缩。目前的结果似乎很好,但我希望你可以访问完整的质量图像-然后结果将是最好的。在

图像将转换为HSV-colorspaceimage),以便更容易地选择颜色。(openCVfindContours返回一个列表,其中包含找到的每个形状的边框周围的坐标。在

我对shapefile一无所知,但是this可能会有一些用处。在

结果:

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()

相关问题 更多 >