通过python opencv从图像中提取模式

问题描述

我有一堆这样的图像。

the source image

图片中我们可以看到,有两种建筑物,第一种是纯色填充,第二种是斜线填充。

我用绿色标记第一种,用红色标记第二种。

two kinds of buildings

我想我可以只用彩色蒙版提取第一种风格的建筑,但第二种风格呢?

我知道我可以通过训练图像分割模型来达到目标​​,但是否可以使用纯图像处理方法来实现?

解决方法

我根据颜色对图像进行阈值处理,然后使用 findContours 来获取每个单独的建筑物。然后我将它们按大小分类为“大建筑物”或“小建筑物”,具体取决于它们是大于还是小于“截止”值。

截止值 = 2000

docs

截止值 = 4000

enter image description here

截止值 = 6000

enter image description here

这是我使用的代码。您需要按“q”移过第一个窗口(用于单击图像以获取颜色)。您可以通过修改截止变量来更改建筑分割。

import cv2
import numpy as np

# get pixel value under mouse
def clicky(event,x,y,flags,params):
    if event == cv2.EVENT_LBUTTONUP:
        global img;
        print(img[y][x]);

# load image
img = cv2.imread("town.png");

# find values
cv2.namedWindow("Original");
cv2.setMouseCallback("Original",clicky);
while True:
    cv2.imshow("Original",img);
    if cv2.waitKey(1) == ord('q'):
        break;

# threshold values
# [232 232 238]
mask = cv2.inRange(img,(232,232,238),238));

# erode to get some seperation
kernel = np.ones((3,3),np.uint8)
mask = cv2.erode(mask,kernel,iterations = 1);

# get contours 
# Opencv 3.4,if using a different major version (4.0 or 2.0),remove the first underscore
_,contours,_ = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE);

# filter by size
cutoff = 6000; # change this to change how they are classified
big_contours = [];
small_contours = [];
for contour in contours:
    area = cv2.contourArea(contour);
    if area > cutoff: 
        big_contours.append(contour);
    else:
        small_contours.append(contour);

# draw contours on mask
colored_mask = np.zeros_like(img);
cv2.drawContours(colored_mask,big_contours,-1,(155,200,0),-1);
cv2.drawContours(colored_mask,small_contours,(0,155,200),-1);

# show
cv2.imshow("town",img);
cv2.imshow("mask",mask);
cv2.imshow("colored_mask",colored_mask);
cv2.waitKey(0);

编辑:

这是一些用于查找“细线”建筑物的代码。不过,这种按特定颜色进行分割的方法有点笨拙,尤其是对于这些建筑物,因为它们没有单一颜色。

enter image description here

import cv2
import numpy as np

# get pixel value under mouse
def clicky(event,params):
    if event == cv2.EVENT_LBUTTONUP:
        global img;
        print(img[y][x]);

# load image
img = cv2.imread("town.png");

# find color values
cv2.namedWindow("Original");
cv2.setMouseCallback("Original",img);
    if cv2.waitKey(1) == ord('q'):
        break;

# set color values
colors = [];
colors.append((227,228,228));
colors.append((248,251,251));
colors.append((229,241,238));
colors.append((240,242,242));
colors.append((234,236,238));

# threshold values
mask = np.zeros_like(img[:,:,0]);
for color in colors:
    next_mask = cv2.inRange(img,color,color);
    mask = cv2.bitwise_or(mask,next_mask);

# dilate and erode
kernel = np.ones((3,np.uint8);
mask = cv2.dilate(mask,iterations = 5);
mask = cv2.erode(mask,iterations = 5);

# colored
img[mask == 255] = (155,0);

# show
cv2.imshow("town",mask);
cv2.waitKey(0);