OpenCV如何获取轮廓的精确多边形?现有方法精度不足
解决二值图像精确外轮廓多边形绘制问题
问题根源
你当前通过np.column_stack(np.where(img_binary.transpose() > 0))获取的是所有前景像素的坐标集合,这些点没有按轮廓顺序排列,直接传入fillPoly会导致绘制的多边形完全失真,这就是左下角区域不匹配的核心原因。
修正方案
1. 优化二值化结果(可选)
先通过形态学操作去除小噪点、填补缝隙,减少轮廓的毛刺干扰:
import cv2 import numpy as np img_color = cv2.imread('carved.png') img_gray = cv2.cvtColor(img_color, cv2.COLOR_BGR2GRAY) cv2.imwrite('ex1_gray.png', img_gray) # 二值化后加入形态学闭运算优化 img_binary = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV, 11, 2) kernel = np.ones((3,3), np.uint8) img_binary = cv2.morphologyEx(img_binary, cv2.MORPH_CLOSE, kernel, iterations=1) cv2.imwrite('ex1_binary_optimized.png', img_binary)
2. 提取轮廓并生成精确多边形
提取最大外轮廓后,使用cv2.approxPolyDP控制多边形精度,参数epsilon越小,多边形越贴近原轮廓;若要最高精度,直接用原始轮廓点即可:
# 获取最大外轮廓 contours = cv2.findContours(img_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) contours = contours[0] if len(contours) == 2 else contours[1] big_contour = max(contours, key=cv2.contourArea) # 方案A:生成可控制精度的近似多边形(推荐) # epsilon设为轮廓周长的0.001倍,可根据需求调整数值 epsilon = 0.001 * cv2.arcLength(big_contour, True) approx_poly = cv2.approxPolyDP(big_contour, epsilon, True) # 方案B:使用原始轮廓点(最高精度) # approx_poly = big_contour # 绘制填充的精确多边形mask mask = np.zeros_like(img_binary) cv2.fillPoly(mask, [approx_poly], 255) cv2.imwrite('ex1_precise_mask.png', mask) # 绘制多边形轮廓到图像查看效果 contr = cv2.cvtColor(img_binary.copy(), cv2.COLOR_GRAY2BGR) cv2.drawContours(contr, [approx_poly], 0, (0,0,255), 2) cv2.imwrite('ex1_precise_poly.png', contr)
关键说明
cv2.approxPolyDP的epsilon参数是控制精度的核心:它是轮廓周长的比例值,比如0.001*周长表示近似多边形与原轮廓的最大距离不超过周长的0.1%,值越小精度越高,多边形的顶点数也越多。- 绝对不要用所有前景像素点来绘制多边形,必须使用按轮廓顺序排列的轮廓点或近似多边形点。
内容的提问来源于stack exchange,提问作者Danyel
相关产品推荐
相关产品推荐

