通过 python opencv 从图像中提取图案

extract pattern from image via python opencv

我有一堆这样的图片。

从图中可以看出,建筑物有两种,第一种是纯色填充,第二种是斜线填充。

我把第一种标为绿色,第二种标为红色

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

我知道我可以通过训练一个图像分割模型来达到目的,但是是否可以使用纯图像处理的方法来达到目的呢?

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

截止 = 2000

截断 = 4000

截断 = 6000

这是我使用的代码。您需要按 'q' 移动到第一个 window (它用于单击图像以获取颜色)。您可以通过修改截止变量来更改建筑物拆分。

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), (232, 232, 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, -1, (0, 155, 200), -1);

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

编辑:

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

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 color values
cv2.namedWindow("Original");
cv2.setMouseCallback("Original", clicky);
while True:
    cv2.imshow("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,3),np.uint8);
mask = cv2.dilate(mask, kernel, iterations = 5);
mask = cv2.erode(mask, kernel, iterations = 5);

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

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