python - 基于颜色python的对象边界框
问题描述
我尝试在这张图片中的每个对象上绘制一个边界框,我从文档中编写了这段代码
import cv2 as cv2
import os
import numpy as np
img = cv2.imread('1 (2).png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);
ret,thresh = cv2.threshold(img,127,255,0)
im2,contours,hierarchy = cv2.findContours(thresh, 1, 2)
for item in range(len(contours)):
cnt = contours[item]
if len(cnt)>20:
print(len(cnt))
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
当我将此行中的值 127 更改为 200 时,ret,thresh = cv2.threshold(img,127,255,0)
我得到了不同的对象。
问题是我如何一次检测所有对象?
解决方案
该方法相当简单。我们首先转换为 HSV 并仅获取色调通道。
image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
h,_,_ = cv2.split(image_hsv)
接下来,我们找到主要的色调——首先计算每个色调的出现次数numpy.bincount
(我们flatten
使用色调通道图像使其成为一维):
bins = np.bincount(h.flatten())
然后使用以下方法找到哪些足够常见numpy.where
:
MIN_PIXEL_CNT_PCT = (1.0/20.0)
peaks = np.where(bins > (h.size * MIN_PIXEL_CNT_PCT))[0]
现在我们已经确定了所有的主要色调,我们可以重复处理图像以找到对应于它们中的每一个的区域:
for i, peak in enumerate(peaks):
我们首先创建一个掩码,选择该色调的所有像素 ( cv2.inRange
,然后从输入 BGR 图像 ( cv2.bitwise_and
.
mask = cv2.inRange(h, peak, peak)
blob = cv2.bitwise_and(image, image, mask=mask)
接下来,我们找到这个色调的所有连续区域的轮廓 ( cv2.findContours
,这样我们就可以单独处理它们中的每一个
_, contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
现在,对于每个已识别的连续区域
for j, contour in enumerate(contours):
我们确定边界框 ( ,并通过用白色 (和)cv2.boundingRect
填充轮廓多边形来创建与该轮廓对应的掩码numpy.zeros_like
cv2.drawContours
bbox = cv2.boundingRect(contour)
contour_mask = np.zeros_like(mask)
cv2.drawContours(contour_mask, contours, j, 255, -1)
然后我们可以只额外增加与边界框对应的 ROI
region = blob.copy()[bbox[1]:bbox[1]+bbox[3],bbox[0]:bbox[0]+bbox[2]]
region_mask = contour_mask[bbox[1]:bbox[1]+bbox[3],bbox[0]:bbox[0]+bbox[2]]
region_masked = cv2.bitwise_and(region, region, mask=region_mask)
或可视化(cv2.rectangle
边界框:
result = cv2.bitwise_and(blob, blob, mask=contour_mask)
top_left, bottom_right = (bbox[0], bbox[1]), (bbox[0]+bbox[2], bbox[1]+bbox[3])
cv2.rectangle(result, top_left, bottom_right, (255, 255, 255), 2)
或者做你想做的任何其他处理。
完整脚本
import cv2
import numpy as np
# Minimum percentage of pixels of same hue to consider dominant colour
MIN_PIXEL_CNT_PCT = (1.0/20.0)
image = cv2.imread('colourblobs.png')
if image is None:
print("Failed to load iamge.")
exit(-1)
image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# We're only interested in the hue
h,_,_ = cv2.split(image_hsv)
# Let's count the number of occurrences of each hue
bins = np.bincount(h.flatten())
# And then find the dominant hues
peaks = np.where(bins > (h.size * MIN_PIXEL_CNT_PCT))[0]
# Now let's find the shape matching each dominant hue
for i, peak in enumerate(peaks):
# First we create a mask selecting all the pixels of this hue
mask = cv2.inRange(h, peak, peak)
# And use it to extract the corresponding part of the original colour image
blob = cv2.bitwise_and(image, image, mask=mask)
_, contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for j, contour in enumerate(contours):
bbox = cv2.boundingRect(contour)
# Create a mask for this contour
contour_mask = np.zeros_like(mask)
cv2.drawContours(contour_mask, contours, j, 255, -1)
print "Found hue %d in region %s." % (peak, bbox)
# Extract and save the area of the contour
region = blob.copy()[bbox[1]:bbox[1]+bbox[3],bbox[0]:bbox[0]+bbox[2]]
region_mask = contour_mask[bbox[1]:bbox[1]+bbox[3],bbox[0]:bbox[0]+bbox[2]]
region_masked = cv2.bitwise_and(region, region, mask=region_mask)
file_name_section = "colourblobs-%d-hue_%03d-region_%d-section.png" % (i, peak, j)
cv2.imwrite(file_name_section, region_masked)
print " * wrote '%s'" % file_name_section
# Extract the pixels belonging to this contour
result = cv2.bitwise_and(blob, blob, mask=contour_mask)
# And draw a bounding box
top_left, bottom_right = (bbox[0], bbox[1]), (bbox[0]+bbox[2], bbox[1]+bbox[3])
cv2.rectangle(result, top_left, bottom_right, (255, 255, 255), 2)
file_name_bbox = "colourblobs-%d-hue_%03d-region_%d-bbox.png" % (i, peak, j)
cv2.imwrite(file_name_bbox, result)
print " * wrote '%s'" % file_name_bbox
控制台输出
Found hue 32 in region (186, 184, 189, 122).
* wrote 'colourblobs-0-hue_032-region_0-section.png'
* wrote 'colourblobs-0-hue_032-region_0-bbox.png'
Found hue 71 in region (300, 197, 1, 1).
* wrote 'colourblobs-1-hue_071-region_0-section.png'
* wrote 'colourblobs-1-hue_071-region_0-bbox.png'
Found hue 71 in region (301, 195, 1, 1).
* wrote 'colourblobs-1-hue_071-region_1-section.png'
* wrote 'colourblobs-1-hue_071-region_1-bbox.png'
Found hue 71 in region (319, 190, 1, 1).
* wrote 'colourblobs-1-hue_071-region_2-section.png'
* wrote 'colourblobs-1-hue_071-region_2-bbox.png'
Found hue 71 in region (323, 176, 52, 14).
* wrote 'colourblobs-1-hue_071-region_3-section.png'
* wrote 'colourblobs-1-hue_071-region_3-bbox.png'
Found hue 71 in region (45, 10, 330, 381).
* wrote 'colourblobs-1-hue_071-region_4-section.png'
* wrote 'colourblobs-1-hue_071-region_4-bbox.png'
Found hue 109 in region (0, 0, 375, 500).
* wrote 'colourblobs-2-hue_109-region_0-section.png'
* wrote 'colourblobs-2-hue_109-region_0-bbox.png'
Found hue 166 in region (1, 397, 252, 103).
* wrote 'colourblobs-3-hue_166-region_0-section.png'
* wrote 'colourblobs-3-hue_166-region_0-bbox.png'
示例输出图像
黄色边界框:
黄色提取区域:
最大的绿色边界框(还有其他几个不相交的小区域):
...以及相应的提取区域:
推荐阅读
- java - 在 Java 中实现枚举时的最佳实践是什么?
- python - 使用 Selenium 仅通过其 XPath 的一部分查找元素
- amazon-web-services - Amazon RDS 实例被自动删除
- azure-devops - 术语“Get-AzureRmPolicyDefinition”未被识别为 cmdlet、函数、脚本文件或可运行程序的名称
- javascript - 当通过 Object.setPrototypeOf() 向函数原型添加属性时,对象为空
- javascript - 如何使用 EXTEND_ESLINT 环境变量扩展 CRA ESLint 规则
- mule - Mule 如何忽略 GRIZZLY0013:FilterChain 执行期间的异常
- python - 将二维矩阵的每一行与一个向量卷积
- c++ - 将向量复制到队列中
- javascript - 为什么控制台会在我已经定义变量时记录我的变量未定义的错误?