【问题标题】:Detect multiple colored regions in image and produce individual crops for each检测图像中的多个彩色区域并为每个区域生成单独的作物
【发布时间】:2019-10-25 18:58:07
【问题描述】:

我有一张这样的图片:

而且我想在红色的任何地方裁剪图像。

所以有了这张图片,我会希望生产 4 种作物:

显然,我首先需要检测图像中任何有红色的地方。我可以做到以下几点:

import cv2
import numpy as np
from google.colab.patches import cv2_imshow

## (1) Read and convert to HSV
img = cv2.imread("my_image_with_red.png")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

## (2) Find the target red region in HSV
hsv_lower = np.array([0,50,50])
hsv_upper = np.array([10,255,255])
mask = cv2.inRange(hsv, hsv_lower, hsv_upper)

## (3) morph-op to remove horizone lines
kernel = np.ones((5,1), np.uint8)
mask2 = cv2.morphologyEx(mask, cv2.MORPH_OPEN,  kernel)


## (4) crop the region
ys, xs = np.nonzero(mask2)
ymin, ymax = ys.min(), ys.max()
xmin, xmax = xs.min(), xs.max()

croped = img[ymin:ymax, xmin:xmax]

pts = np.int32([[xmin, ymin],[xmin,ymax],[xmax,ymax],[xmax,ymin]])
cv2.drawContours(img, [pts], -1, (0,255,0), 1, cv2.LINE_AA)


cv2_imshow(croped)
cv2_imshow(img)
cv2.waitKey()

这给出了以下结果:

边界框覆盖了包含红色的整个区域。

如何在图像的每个红色部分周围设置边界框?我已经研究了 multiple mask 但这似乎不起作用。

我要找的是:

  • 检测 每个图像中的红点;
  • 在每个红点上返回边界;
  • 使用这些边界生成 4 个单独的作物作为新图像。

【问题讨论】:

  • 把所有不是红色的都变成黑色。把红色的一切都变成白色。现在找到轮廓。当你拥有它们时,在原始图像上使用它们。

标签: python image opencv image-processing computer-vision


【解决方案1】:

目前存在几个问题:

  1. 如果您查看蒙版图像,您会看到在蒙版上捕获了所有红色痕迹,包括小噪声。您当前正在使用 np.nonzero() 捕获所有白色像素。这就是导致边界框覆盖整个区域的原因。为了解决这个问题,我们可以收紧较低的 hsv 阈值以获得这个结果掩码:

请注意,仍然有很多小斑点。你的问题应该改写为

如何裁剪大的红色区域?

如果你想占领所有个红色区域,你将获得超过 4 种作物。因此,为了解决这个问题,我们将执行形态学操作以去除小噪声并仅保留大的明显红色区域。这会产生一个包含大区域的掩码图像

  1. 您不需要多个掩码

如何在图像的每个红色部分周围设置边界框?

您可以在遮罩图像上使用cv2.findContours() 来执行此操作,以返回每个红点的边界矩形。

哦?这不是您想要的结果。由于您想要的结果在每个红点周围都有一些空间,我们还需要在边界矩形中包含一个offset。添加偏移量后,这是我们的结果

由于我们有边界矩形,我们可以简单地使用 Numpy 切片来提取和保存每个 ROI。这是保存的 ROIs


回顾一下,为了检测图像中的每个红点,我们可以使用 HSV 颜色阈值。请注意,这将返回与此阈值匹配的 所有 像素,这可能与您的预期不同,因此有必要执行形态学操作来过滤生成的蒙版。要获得每个红色斑点上的边界矩形,我们可以使用cv2.findContours(),这将为我们提供使用cv2.boundingRect() 的ROI。获得 ROI 后,我们添加偏移量并使用 Numpy 切片提取 ROI。

import cv2
import numpy as np

image = cv2.imread("1.png")
original = image.copy()
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

hsv_lower = np.array([0,150,50])
hsv_upper = np.array([10,255,255])
mask = cv2.inRange(hsv, hsv_lower, hsv_upper)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=1)

cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
offset = 20
ROI_number = 0
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x - offset, y - offset), (x + w + offset, y + h + offset), (36,255,12), 2)
    ROI = original[y-offset:y+h+offset, x-offset:x+w+offset]

    cv2.imwrite('ROI_{}.png'.format(ROI_number), ROI)
    ROI_number += 1

cv2.imshow('mask', mask)
cv2.imshow('close', close)
cv2.imshow('image', image)
cv2.waitKey()

【讨论】:

  • 美丽。很好的答案,有详细的解释。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
  • 2015-05-30
相关资源
最近更新 更多