You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用OpenCV裁剪二值图像中最大的1-3个Blob

嘿,这问题我太熟了!用OpenCV处理这种二值图像里的Blob裁剪其实没那么复杂,我给你一步步拆解清楚怎么做:

步骤分解:

1. 读取图像并提取轮廓

首先咱们得把二值图像读进来,然后提取出所有的Blob轮廓。这里推荐用RETR_EXTERNAL模式只找最外层轮廓,避免嵌套轮廓干扰;CHAIN_APPROX_SIMPLE可以压缩轮廓点,节省内存:

import cv2
import numpy as np

# 读取二值图像(灰度模式)
img = cv2.imread('your_binary_image.png', cv2.IMREAD_GRAYSCALE)

# 提取所有外层轮廓
contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

2. 按面积排序,选中目标Blob

接下来把所有轮廓按面积从大到小排序,这样就能轻松拿到最大的几个Blob。你可以选最大的1个,或者前3个,全看需求:

# 按轮廓面积降序排序
contours_sorted = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=True)

# 选择要保留的Blob数量,比如前3个(改成1就是只取最大的)
top_n = 3
selected_contours = contours_sorted[:top_n]

3. 提取目标区域(两种方式可选)

这里有两种常用的处理方式,你可以根据需求选:

方式A:保留原图尺寸,只显示选中的Blob

这种方式会生成一张和原图一样大的图像,只保留你选中的Blob,其余区域还是黑色:

# 创建和原图一样大的黑色掩码
mask = np.zeros_like(img)

# 在掩码上填充选中的轮廓(白色)
cv2.drawContours(mask, selected_contours, -1, 255, thickness=cv2.FILLED)

# 用掩码提取目标区域
result = cv2.bitwise_and(img, mask)

# 保存或查看结果
cv2.imwrite('selected_blobs.png', result)
cv2.imshow('Selected Blobs', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

方式B:单独裁剪每个Blob的最小包围框

如果需要把每个大Blob单独切出来保存,就遍历选中的轮廓,用boundingRect找到每个Blob的边界框,然后裁剪:

# 遍历选中的轮廓,逐个裁剪
for idx, cnt in enumerate(selected_contours):
    # 获取当前Blob的边界框坐标(x,y)和宽高(w,h)
    x, y, w, h = cv2.boundingRect(cnt)
    # 裁剪出Blob区域
    cropped_blob = img[y:y+h, x:x+w]
    # 保存裁剪后的图像
    cv2.imwrite(f'cropped_blob_{idx+1}.png', cropped_blob)
    # 显示结果
    cv2.imshow(f'Cropped Blob {idx+1}', cropped_blob)

cv2.waitKey(0)
cv2.destroyAllWindows()

一些实用小提示

  • 如果你的图像里有零星的小噪声白点,建议先做个开运算清理一下,避免噪声干扰排序结果:
# 用3x3的核做开运算,去除小噪声
kernel = np.ones((3,3), np.uint8)
img_cleaned = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# 之后用清理后的图像提取轮廓即可
  • 要是你的二值图像是黑色Blob、白色背景,记得先用cv2.bitwise_not(img)反转一下,确保目标是白色的,这样后续步骤才会正常工作。

内容的提问来源于stack exchange,提问作者kaptsea

火山引擎 最新活动