如何用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)**实现区域筛选:
- 创建与原图尺寸一致的黑色掩码图像
- 在掩码上绘制填充的凸包区域(白色)
- 将原图与掩码进行
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
相关产品推荐
相关产品推荐

