检测图像中的多个彩色区域并为每个区域生成单独的农作物 [英] Detect multiple colored regions in image and produce individual crops for each

查看:140
本文介绍了检测图像中的多个彩色区域并为每个区域生成单独的农作物的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的图片:

我想裁剪图像到红色的任何地方.

And I want to crop the image anywhere there is red.

因此,使用此图像,我将希望生产4种作物:

So with this image I would be looking to produce 4 crops:

很明显,我首先需要检测图像中有红色的任何地方.我可以执行以下操作:

Obviously I first need to detect anywhere there is red in the image. I can do the following:

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()

给出以下结果:

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

The bounding box covers the entire area containing red.

如何在图像的每个红色部分周围找到边框?我研究了多个口罩,但这似乎不起作用.

How can I get bounding boxes around each red piece of the image? I have looked into multiple masks but this doesn't seem to work.

我正在寻找的是:

  • 检测 每个图像中的红色斑点;
  • 在每个红点上返回边界
  • 使用这些边界来生成4个单独的庄稼作为新图像.
  • detect each red spot in the image;
  • return boundaries on each red dot;
  • use those boundaries to produce 4 individual crops as new images.

推荐答案

当前存在几个问题:

  1. 如果您查看蒙版图像,您会看到所有红色痕迹在蒙版上被捕获,包括很小的噪音.您当前正在使用np.nonzero()捕获所有白色像素.这就是导致边界框覆盖整个区域的原因.要解决此问题,我们可以收紧较低的hsv阈值以获得此结果掩码:
  1. If you look at your mask image, you will see that all traces of red are captured on the mask including the small noise. You're currently using np.nonzero() which captures all white pixels. This is what causes the bounding box to cover the entire area. To fix this, we can tighten up the lower hsv threshold to get this resulting mask:

请注意,仍有许多小斑点.您的问题应改为

Note there are still a lot of small blobs. Your question should be rephrased to

如何裁切红色大区域?

How can I crop the large red regions?

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

If you want to capture all red regions, you will obtain much more then 4 crops. So to remedy this, we will perform morphological operations to remove the small noise and keep only the large pronounced red regions. This results in a mask image that contains the large regions

  1. 您不需要多个口罩

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

How can I get bounding boxes around each red piece of the image?

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

You can do this using cv2.findContours() on the mask image to return the bounding rectangles of each red dot.

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

Oh? This is not your desired result. Since your desired result has some space surrounding each red dot, we also need to include a offset to the bounding rectangle. After adding an offset, here's our result

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

Since we have the bounding rectangles, we can simply use Numpy slicing to extract and save each ROI. Here's the saved ROIs

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

So to recap, to detect each red spot in the image, we can use HSV color thresholding. Note this will return all pixels which match this threshold which may be different from what you expect so it is necessary to perform morphological operations to filter the resulting mask. To obtain the bounding rectangles on each red blob, we can use cv2.findContours() which will give us the ROIs using cv2.boundingRect(). Once we have the ROI, we add a offset and extract the ROI using Numpy slicing.

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()

这篇关于检测图像中的多个彩色区域并为每个区域生成单独的农作物的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆