使用DECOMP_SVD的cv::solve在C++与Python/Kotlin结果不一致
OpenCV跨语言SVD求解直线交点结果不一致问题排查
问题背景
项目中通过4个点(2条竖线、2条横线)求解直线交点,使用OpenCV的SVD(奇异值分解)方法时,发现Python、Kotlin版本能得到正确结果,但iOS端C++版本结果异常。
各语言实现及结果
Python版本(正确结果)
import numpy as np import cv2 a = np.array([ [0.99773484, -0.06726905], [0.02908471, 0.9995769] ]) b = np.array([ [180.0], [264.66666] ]) _, (x0, y0) = cv2.solve(a, b, flags=cv2.DECOMP_SVD) # x0 = 197.87232204 # y0 = 259.02119276
Kotlin版本(正确结果)
import org.opencv.core.Core import org.opencv.core.CvType import org.opencv.core.Mat val a = Mat.zeros(2, 2, CvType.CV_32F) a.put(0, 0, 0.99773484) a.put(0, 1, -0.06726905) a.put(1, 0, 0.02908471) a.put(1, 1, 0.9995769) val b = Mat.zeros(2, 1, CvType.CV_32F) b.put(0, 0, 180.0) b.put(1, 0, 264.66666) val linearFit = Mat() Core.solve(a, b, linearFit, Core.DECOMP_SVD) val x0 = linearFit.get(0, 0)[0] val y0 = linearFit.get(1, 0)[0] // x0 = 197.87232971191406 // y0 = 259.02117919921875
C++ iOS版本(异常结果)
#include <opencv2/opencv.hpp> cv::Mat a = cv::Mat::zeros(2, 2, CV_32F); a.at<float>(0, 0) = 0.99773484; a.at<float>(0, 1) = -0.06726905; a.at<float>(1, 0) = 0.02908471; a.at<float>(1, 1) = 0.9995769; cv::Mat b = cv::Mat::zeros(2, 1, CV_32F); b.at<float>(0, 0) = 180.0; b.at<float>(1, 0) = 264.66666; cv::Mat linearFit; cv::solve(a, b, linearFit, cv::DECOMP_SVD); double x0 = linearFit.at<cv::Vec3b>(0, 0)[0]; double y0 = linearFit.at<cv::Vec3b>(1, 0)[0]; // x0 = 81.000000 // y0 = 182.000000
问题原因及解决方案
这是类型匹配错误,并非OpenCV iOS框架问题:
- 输入的
a和b都是CV_32F(单精度浮点型),cv::solve返回的linearFit默认会保持相同的类型,即单通道浮点型Mat。 - 代码中错误使用
cv::Vec3b(三通道uchar类型)去访问linearFit的元素,导致内存解析错误,得到完全无关的异常数值。
修正方法:将访问元素的类型改为float,对应代码修改为:
float x0 = linearFit.at<float>(0, 0); float y0 = linearFit.at<float>(1, 0);
或如需转换为double:
double x0 = static_cast<double>(linearFit.at<float>(0, 0)); double y0 = static_cast<double>(linearFit.at<float>(1, 0));
内容的提问来源于stack exchange,提问作者Danil Valov
相关产品推荐
相关产品推荐

