Android绘图应用中OpenCV检测手绘圆、椭圆、五边形的问题
Android绘图应用:圆形、五边形及椭圆检测问题解决方案
核心问题分析
当前遇到的问题本质是:
- 圆度特征无法区分五边形与圆/椭圆
- SimpleBlobDetector的参数设置偏向圆形,导致椭圆被过滤,同时误判五边形为Blob
一、优先采用轮廓分析+多特征组合判断(推荐方案)
BlobDetector更适合实心无规则的 blob 识别,对有明确边缘的几何形状,基于轮廓的分析精度更高。具体步骤:
1. 图像预处理
先做灰度化、二值化、边缘检测,提取清晰轮廓:
Mat gray = new Mat(); Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY); Mat binary = new Mat(); Imgproc.threshold(gray, binary, 0, 255, Imgproc.THRESH_BINARY_INV | Imgproc.THRESH_OTSU); Mat edges = new Mat(); Imgproc.Canny(binary, edges, 50, 150);
2. 提取轮廓并计算特征
遍历每个轮廓,计算三个核心特征:
- 顶点数:用
approxPolyDP拟合轮廓得到近似多边形的顶点数量,直接区分五边形(固定5个顶点) - 圆度:公式为
4π*面积/(周长²),圆形接近1,五边形约0.9,椭圆随扁率在0.7~0.95之间 - 惯性率:椭圆的惯性率(短轴/长轴的平方)远小于圆形,五边形的惯性率则和圆形接近
3. 形状匹配规则
List<MatOfPoint> contours = new ArrayList<>(); Imgproc.findContours(edges, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); for (MatOfPoint contour : contours) { // 计算面积和周长 double area = Imgproc.contourArea(contour); double perimeter = Imgproc.arcLength(new MatOfPoint2f(contour.toArray()), true); if (perimeter == 0) continue; // 圆度 double circularity = 4 * Math.PI * area / (perimeter * perimeter); // 轮廓近似,获取顶点数 MatOfPoint2f contour2f = new MatOfPoint2f(contour.toArray()); double epsilon = 0.03 * perimeter; MatOfPoint2f approx = new MatOfPoint2f(); Imgproc.approxPolyDP(contour2f, approx, epsilon, true); int vertexCount = (int) approx.total(); // 惯性率 Moments moments = Imgproc.moments(contour); double mu20 = moments.get_mu20(); double mu02 = moments.get_mu02(); double inertiaRatio = Math.min(mu20, mu02) / Math.max(mu20, mu02); // 形状判断 if (vertexCount == 5 && circularity >= 0.85) { // 五边形 Imgproc.drawContours(src, Collections.singletonList(contour), -1, new Scalar(0, 255, 0), 2); } else if (vertexCount > 10) { if (circularity >= 0.95) { // 圆形 Imgproc.drawContours(src, Collections.singletonList(contour), -1, new Scalar(255, 0, 0), 2); } else if (circularity >= 0.7 && inertiaRatio < 0.8) { // 椭圆 Imgproc.drawContours(src, Collections.singletonList(contour), -1, new Scalar(0, 0, 255), 2); } } }
二、SimpleBlobDetector参数调整(备选方案)
如果坚持使用BlobDetector,调整参数适配椭圆并过滤五边形:
blobDetectorParams.set_filterByInertia(true); blobDetectorParams.set_filterByCircularity(true); blobDetectorParams.set_filterByConvexity(true); blobDetectorParams.set_filterByArea(true); // 开启面积过滤,排除异常尺寸 // 惯性率:过滤五边形(惯性率接近1),保留椭圆(惯性率较低) blobDetectorParams.set_minInertiaRatio(0.3F); blobDetectorParams.set_maxInertiaRatio(1.0F); // 圆度:降低阈值让椭圆通过 blobDetectorParams.set_minCircularity(0.6F); blobDetectorParams.set_maxCircularity(1.0F); blobDetectorParams.set_minConvexity(0.87F); blobDetectorParams.set_minThreshold(0); blobDetectorParams.set_maxThreshold(300); blobDetectorParams.set_thresholdStep(10); blobDetectorParams.set_minRepeatability(1); // 根据你的绘图尺寸设置合理的面积范围 blobDetectorParams.set_minArea(100.0F); blobDetectorParams.set_maxArea(10000.0F);
注意事项
- 预处理时可添加形态学操作(如
Imgproc.dilate)平滑笔画边缘,减少轮廓噪声 - 轮廓近似的
epsilon参数需根据实际绘图调整,建议设为周长的0.02~0.05倍
内容的提问来源于stack exchange,提问作者gabry2298
相关产品推荐
相关产品推荐

