Android中OpenCV目标检测置信度异常,求正确转Java代码
问题分析与修正代码
核心错误点
- 遍历维度错误:原Python代码中
detections是4维数组(shape为(1,1,N,7),N为检测结果数量),遍历的是第三维度的索引(i从0到N-1)。你在Java中错误地用detections.rows()作为遍历上限,而实际上detections.rows()为1,完全没遍历到正确的检测结果。 - 元素访问方式错误:Python中通过
detections[0,0,i,2]访问4维数组的元素,Java中OpenCV的4维Mat需要用get(int[] indices)方法指定4个维度的索引,你用detections.get(i,2)是按2维数组访问,取到的是完全错误的数值,导致置信度为负、idx异常。 - 边界框计算错误:原Python直接提取
startX, startY, endX, endY,你错误地将第5个值当成宽度、第6个值当成高度,应该直接计算endX - startX和endY - startY。
修正后的Java代码
float confidenceThreshold = 0.8f; // 获取检测结果的数量 int numDetections = detections.size(2); // 遍历所有检测结果 for (int i = 0; i < numDetections; i++) { // 提取置信度:对应Python的detections[0,0,i,2] double confidence = detections.get(new int[]{0, 0, i, 2})[0]; // 过滤低置信度结果 if (confidence > confidenceThreshold) { // 提取类别索引:对应Python的detections[0,0,i,1] int idx = (int) detections.get(new int[]{0, 0, i, 1})[0]; // 提取边界框坐标并转换为图像实际尺寸 float startX = (float) detections.get(new int[]{0, 0, i, 3})[0] * input_image.cols(); float startY = (float) detections.get(new int[]{0, 0, i, 4})[0] * input_image.rows(); float endX = (float) detections.get(new int[]{0, 0, i, 5})[0] * input_image.cols(); float endY = (float) detections.get(new int[]{0, 0, i, 6})[0] * input_image.rows(); // 绘制标签和边界框 String label = imgLabels.get(idx) + ": " + String.format("%.2f", confidence * 100) + "%"; // 调整标签位置,避免超出图像顶部 double labelY = startY - 15 > 15 ? startY - 15 : startY + 15; Imgproc.putText(input_image, label, new Point(startX, labelY), Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(0, 255, 0), 2); Imgproc.rectangle(input_image, new Point(startX, startY), new Point(endX, endY), new Scalar(0, 255, 0), 2); } }
额外说明
- 确保
imgLabels数组的索引与模型输出的类别索引完全对应,避免出现数组越界或标签错误。 - 如果你的
detectionsMat维度不是4维(比如部分版本OpenCV输出为2维1xN,每个元素是7个值),可以调整访问方式为detections.get(0, i*7 + 2)[0],但根据原Python代码,应该是4维输出,优先使用上述代码。
内容的提问来源于stack exchange,提问作者Mich
相关产品推荐
相关产品推荐

