【问题标题】:extract pattern from image via python opencv通过python opencv从图像中提取模式
【发布时间】:2021-05-11 19:32:26
【问题描述】:

我有一堆这样的图像。

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

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

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

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

【问题讨论】:

  • 你想区分大小建筑吗?还是直接提取所有建筑物?
  • 如果我能把所有的建筑物都提取出来,并且把这两种区分出来就好了。如果我不能,我认为只提取建筑物就可以了。

标签: python opencv image-processing pattern-matching image-segmentation


【解决方案1】:

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

截止值 = 2000

截止值 = 4000

截止值 = 6000

这是我使用的代码。您需要按“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), (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);

【讨论】:

  • 感谢您的工作,这看起来很棒。但是,这并不是我真正想要的......我无法在此处添加图像,因此我修改了问题以获得更好的解释。我认为真正的障碍在于提取我用红色标记的第二种样式的块。
  • 哦,哈哈。我什至没有看到那些建筑!
  • 哈哈哈,模棱两可~有什么好办法提取吗?
  • 在它们周围单击表明它们也具有独特的颜色。 [227 228 228] 和 [248, 251, 251]。这将使您将每个建筑物的一些作为一堆线。您可以根据距离将线条组合成一个建筑物,然后在它们周围绘制一个 minRect。我今晚可能没有时间尝试这个。
猜你喜欢
  • 1970-01-01
  • 2019-10-29
  • 1970-01-01
  • 2012-02-21
  • 2018-06-04
  • 2019-07-17
  • 1970-01-01
  • 2017-03-18
  • 1970-01-01
相关资源
最近更新 更多