检测图像中的多个彩色区域并为每个区域生成单独的作物

Cyb*_*tic 4 python opencv image image-processing bounding-box

我有这样的图像

在此处输入图片说明

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

因此,使用此图像,我将要生产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()
Run Code Online (Sandbox Code Playgroud)

得到以下结果

在此处输入图片说明

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

如何获得每个红色图像周围的边界框?我研究了多个口罩,但这似乎不起作用。

我正在寻找的是:

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

nat*_*ncy 7

当前存在几个问题:

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

在此处输入图片说明

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

如何裁切红色大区域?

如果要捕获所有红色区域,则将获得4种以上的作物。因此,为了解决这个问题,我们将执行形态学操作以消除小的噪声,并仅保留较大的明显红色区域。这将导致包含较大区域的蒙版图像

在此处输入图片说明

  1. 您不需要多个口罩

如何获得每个红色图像周围的边界框?

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

在此处输入图片说明

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

在此处输入图片说明

由于我们具有边界矩形,因此我们可以简单地使用Numpy切片来提取并保存每个ROI。这是保存的投资回报率

在此处输入图片说明


综上所述,要检测图像中的每个红色斑点,我们可以使用HSV颜色阈值。请注意,这将返回与该阈值匹配的所有像素,这些像素可能与您期望的阈值不同,因此有必要执行形态学运算以过滤生成的蒙版。要获取每个红色Blob上的边界矩形,我们可以使用cv2.findContours(),使用将为我们提供ROI cv2.boundingRect()。有了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()
Run Code Online (Sandbox Code Playgroud)

  • 美丽。很棒的答案,带详细说明。谢谢。 (2认同)