You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python+OpenCV将手部X光凸包外部区域涂黑?

如何使用OpenCV将手部X光图像的凸包外部区域涂黑

我已经从手部X光图像中提取了手部边缘轮廓并生成了凸包,现在想通过Python的OpenCV库将凸包外部的区域全部涂黑,该怎么实现?

以下是我目前生成凸包的代码:

img_path = 'sample_image.png'

# 获取图像阈值
image = cv2.imread(img_path)
original = image.copy() 
blank = np.zeros(image.shape[:2], dtype = np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 140, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# 绘制手部边缘轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, 
cv2.CHAIN_APPROX_SIMPLE)
contours = max(contours, key = lambda x: cv2.contourArea(x))
cv2.drawContours(image, [contours], -1, (255,255,0), 2)

# 绘制凸包
hull = cv2.convexHull(contours)
cv2.drawContours(image, [hull], -1, (0, 255, 255), 2)

核心实现方案

思路

通过**掩码(Mask)**实现区域筛选:

  1. 创建与原图尺寸一致的黑色掩码图像
  2. 在掩码上绘制填充的凸包区域(白色)
  3. 将原图与掩码进行bitwise_and运算,仅保留掩码白色区域对应的原图内容,外部自动变为黑色

完整代码

在现有代码基础上添加掩码与位运算步骤即可实现需求:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img_path = 'sample_image.png'

# 获取图像阈值
image = cv2.imread(img_path)
original = image.copy() 
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 140, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# 提取手部轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = max(contours, key = lambda x: cv2.contourArea(x))

# 生成凸包
hull = cv2.convexHull(contours)

# 创建掩码并填充凸包(参数-1表示填充轮廓内部)
mask = np.zeros_like(image)
cv2.drawContours(mask, [hull], -1, (255, 255, 255), -1)

# 保留凸包内部区域,外部自动涂黑
masked_image = cv2.bitwise_and(original, mask)

# 展示结果
plt.imshow(cv2.cvtColor(masked_image, cv2.COLOR_BGR2RGB))
plt.show()

优化方案(针对轮廓断裂问题)

如果原阈值图像的手部轮廓存在断裂、不连续的情况,可先对阈值图进行膨胀操作,让分散的轮廓合并为一个整体,再提取轮廓和凸包,确保凸包能完整包裹手部:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img_path = 'sample_image.png'

image = cv2.imread(img_path)
original = image.copy() 
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 140, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# 膨胀操作合并断裂轮廓
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
dilate = cv2.dilate(thresh, kernel, iterations = 2)

# 提取合并后的完整轮廓
contours, hierarchy = cv2.findContours(dilate, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = max(contours, key = lambda x: cv2.contourArea(x))

# 生成凸包
hull = cv2.convexHull(contours)

# 创建掩码并填充凸包
mask = np.zeros_like(image)
cv2.drawContours(mask, [hull], -1, (255, 255, 255), -1)

# 保留凸包内部区域
masked_image = cv2.bitwise_and(original, mask)

# 展示结果
plt.imshow(cv2.cvtColor(masked_image, cv2.COLOR_BGR2RGB))
plt.show()

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 00:15:37