cv::solve 与 DECOMP_SVD 一起使用 C++ 的结果与 Python 和 Java(Kotlin) 不同

cv::solve with DECOMP_SVD using C++ has different results from Python and Java(Kotlin)

提问人:Danil Valov 提问时间:7/5/2023 最后编辑:Danil Valov 更新时间:7/5/2023 访问量:61

问:

我在我的项目中发现了一个有趣的问题,即 SVD(奇异值分解)的不同结果。 我需要通过线(4 点)找到交叉点。 我有 2 条垂直线和 2 条水平线。

我为 Python 编写了以下代码,它可以正常工作:

a = numpy.array([
    [0.99773484, -0.06726905],
    [0.02908471, 0.9995769]
])
b = numpy.array([
    [180.0],
    [264.66666]
])
_, (x0, y0) = cv2.solve(a, b, flags=cv2.DECOMP_SVD)
# x0 = 197.87232204
# y0 = 259.02119276

此外,我使用 Kotlin 编写了相同的代码,它也可以正常工作:

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++ 编写这段代码时,我得到了不同的结果:

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

这是我的语法问题还是 iOS 的 opencv2.framework 的问题? 我在 opencv2.framework v.3.4.19 和 v.4.1.0 上进行了测试。

P.S. 我在这个答案中得到的查找交叉点的函数:https://stackoverflow.com/a/46572063

蟒蛇 C++ OpenCVV SVD

评论


答:

0赞 Danil Valov 7/5/2023 #1

ChatGPT 帮助了我。 正确的语法是:

double x0 = linearFit.at<float>(0, 0);
double y0 = linearFit.at<float>(1, 0);
1赞 Christoph Rackwitz 7/5/2023 #2

类型问题。

Vec3b表示 的三个值。uint8_t

cv::solve()可能返回 () 值。它可能返回了 ,即单通道,或 ,即三通道。floatCV_32FCV_32FC1CV_32FC3

如果生成的 Mat 是 3 通道,则可能需要使用 。如果没有,那将是正确的。Vec3ffloat

如果它不是 32 位浮点数,则可能需要不同的类型。 是一种可能性。CV_64F