在Java(Android)中用OpenCV计算Blob凸性时遇contourArea断言失败
解决OpenCV Java版convexHull结果无法传入contourArea的问题
问题原因
这不是OpenCV的Bug,而是Java与C++版convexHull的行为差异导致的:
- C++中,输入
vector<Point>类型的轮廓时,convexHull默认返回凸包的点坐标集合(vector<Point>),可直接传入contourArea计算。 - Java中,默认调用
Imgproc.convexHull(contour, hull)时,返回的是原轮廓点的索引集合(单通道MatOfInt),而contourArea要求输入是2通道的点坐标Mat(如MatOfPoint),因此触发checkVector(2)的断言失败。
解决方案
方法1:直接获取凸包点坐标(推荐)
调用convexHull的重载方法,指定returnPoints=true,直接得到凸包的点坐标集合:
// 假设已通过findContours得到contour(MatOfPoint类型) MatOfPoint hull = new MatOfPoint(); // 参数说明: // 1. 输入轮廓;2. 输出凸包;3. 是否顺时针排列;4. 是否返回点坐标(设为true) Imgproc.convexHull(contour, hull, false, true); // 直接计算凸包面积 double hullArea = Imgproc.contourArea(hull); // 结合原轮廓面积计算凸性 double contourArea = Imgproc.contourArea(contour); double convexity = contourArea / hullArea;
方法2:从索引集合重构凸包点坐标
如果已得到索引类型的hull,可手动从原轮廓中提取对应点:
MatOfInt hullIndices = new MatOfInt(); Imgproc.convexHull(contour, hullIndices); // 将索引转换为点集 List<Point> contourPoints = contour.toList(); List<Point> hullPoints = new ArrayList<>(); int[] indices = hullIndices.toArray(); for (int idx : indices) { hullPoints.add(contourPoints.get(idx)); } MatOfPoint hull = new MatOfPoint(); hull.fromList(hullPoints); // 计算面积与凸性 double hullArea = Imgproc.contourArea(hull); double contourArea = Imgproc.contourArea(contour); double convexity = contourArea / hullArea;
凸性计算补充
SimpleBlobDetector中的凸性逻辑为原轮廓面积 / 凸包面积,值越接近1,轮廓越接近凸形。
内容的提问来源于stack exchange,提问作者steve
相关产品推荐
相关产品推荐

