如何填充岩石岩心分割图像的复杂闭合轮廓并生成3D模型?
问题分析与解决方案
问题原因
- 填充对象与颜色参数错误:你直接在原岩石图像(白色区域为岩石)上用黑色填充轮廓范围,导致原本的白色岩石被完全覆盖成黑色;同时灰度图应使用单通道颜色值(如
255),而非三通道的(0,0,0)。 - 轮廓层级未处理:使用
cv2.RETR_TREE会获取所有层级的轮廓,但未区分内外轮廓,容易导致填充区域混乱。
修正后的代码
import cv2 import numpy as np from skimage import measure from stl import mesh path = "" # 替换为你的文件实际路径 # 读取灰度分割图像 imageExtract = cv2.imread(path+'maskExtract.png', cv2.IMREAD_GRAYSCALE) # 反转图像:将黑色空隙转为白色,便于提取空隙轮廓(若需填充岩石内部孔洞可跳过此步) inv_image = cv2.bitwise_not(imageExtract) # 提取最外层轮廓,避免内层轮廓干扰填充 contours, hierarchy = cv2.findContours(inv_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 创建空白图像用于填充 fill_image = np.zeros_like(imageExtract) # 填充轮廓内部为白色(此处填充的是空隙区域) cv2.fillPoly(fill_image, pts=contours, color=255) # 合并原岩石区域与填充后的空隙,得到完整无空隙的岩石图像 filled_rock = cv2.bitwise_or(imageExtract, fill_image) cv2.imshow('Filled Result', filled_rock) cv2.waitKey(0) cv2.destroyAllWindows() # 提取坐标生成3D模型 contour_coords = np.column_stack(np.where(filled_rock == 255)) print(contour_coords.shape) height, width = filled_rock.shape print(height, width) depth = 10 # extrusion depth volume = np.zeros((height, width, depth), dtype=np.uint8) for coord in contour_coords: x, y = coord for z in range(depth): volume[x, y, z] = 255 # 生成并保存3D模型 verts, faces, normals, values = measure.marching_cubes(volume, 0) obj_3d = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) scaling_factor = 0.001 scaled_verts = verts * scaling_factor for i, f in enumerate(faces): obj_3d.vectors[i] = scaled_verts[f] obj_3d.save('rocheExtract_contour.stl')
关键修改说明
- 反转图像:针对“填充岩石空隙”的需求,反转图像后可更方便地提取黑色空隙的轮廓。
- 轮廓提取优化:改用
cv2.RETR_EXTERNAL仅提取最外层轮廓,避免内层细碎轮廓干扰填充结果。 - 填充逻辑修正:在空白图像上执行填充操作,避免破坏原图像;使用单通道颜色值适配灰度图格式。
- 图像合并:通过
bitwise_or合并原岩石区域与填充后的空隙,得到完整的岩石区域图像,确保3D模型生成的准确性。
内容的提问来源于stack exchange,提问作者SALIC TOM
相关产品推荐
相关产品推荐

