gpt4 book ai didi

c++ - OpenCV卡尔曼滤波器错误

转载 作者:行者123 更新时间:2023-12-02 00:12:25 38 4
gpt4 key购买 nike

我使用OpenCV来预测使用网络摄像头看到的球的运动。但是,我在cvKalmanPredict状态上总是遇到错误,因此我将代码简化为以下几行,并尝试单独测试过滤器:

        CvKalman* kalman = cvCreateKalman(6,3,1);
kalman->temp2 = cvCreateMat(1, 1, CV_32FC1);

float alpha = 0.1, beta = 0.2;

float kalmA[] = {1.0+t0/t1, 0, 0, -t0/t1, 0, 0,
0, 1.0+t0/t1, 0, 0, -t0/t1, 0,
0, 0, 1.0+t0/t1, 0, 0, -t0/t1,
1, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0};
float kalmB[] = {0, 0, 1, 0, 0, 0};
float kalmH[] = {1, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0};
float kalmQ[] = {alpha, 0, 0, 0, 0, 0,
0, alpha, 0, 0, 0, 0,
0, 0, beta, 0, 0, 0,
0, 0, 0, alpha, 0, 0,
0, 0, 0, 0, alpha, 0,
0, 0, 0, 0, 0, beta};
float kalmR[] = {alpha, 0, 0,
0, alpha, 0,
0, 0, beta};
float kalmS[] = {0,0,0, 0, 0, 0};
float kalmP[] = {480, 0, 0, 0, 0, 0,
0, 480, 0, 0, 0, 0,
0, 0, 480, 0, 0, 0,
0, 0, 0, 480, 0, 0,
0, 0, 0, 0, 480, 0,
0, 0, 0, 0, 0, 480};

memcpy( kalman->transition_matrix->data.fl, kalmA, sizeof(kalmA) );
memcpy( kalman->control_matrix->data.fl, kalmB, sizeof(kalmB) );
memcpy( kalman->measurement_matrix->data.fl, kalmH, sizeof(kalmH) );
memcpy( kalman->process_noise_cov->data.fl, kalmQ, sizeof(kalmQ) );
memcpy( kalman->measurement_noise_cov->data.fl, kalmR, sizeof(kalmR) );


// initialize state and covariance
memcpy( kalman->state_post->data.fl, kalmS, sizeof(kalmS) );
cvSetIdentity( kalman->error_cov_post, cvRealScalar(3));

// update the control
float t0 = 0.3;
cvSetReal2D( kalman->temp2, 0, 0, -490 * t0 * t0 );

const CvMat* kalmanPred = cvKalmanPredict(kalman, kalman->temp2);

CvMat* kalmMeas = cvCreateMat(3,1,CV_32FC1);
cvSetReal2D(kalmMeas, 0, 0, 3);
cvSetReal2D(kalmMeas, 1, 0, 2);
cvSetReal2D(kalmMeas, 2, 0, 5.5);
cvKalmanCorrect(kalman, kalmMeas);
cvReleaseMat(&kalmMeas);

// release memory

但是,调用cvKalmanPredict时仍然出现相同的错误:
        OpenCV Error: Assertion failed ((D.rows == ((flags & CV_GEMM_A_T) == 0 ? A.rows : A.cols)) && (D.cols == ((flags & CV_GEMM_B_T) == 0 ? B.cols : B.rows)) && D.type() == A.type() in unknown function. file C:\Users\opencv\modules\core\src\matmul.cpp. line 2930

我正在将cmake与MS Visual C++ 10一起编译。

最佳答案

合理的解释

在阅读详细的错误消息时,该断言似乎正在测试A和B是否符合D的大小。大概此检查发生在涉及这三个矩阵的计算(cvKalmanPredict)之前。

错误消息中指定的矩阵A,B和D可能与示例中提供的三个或更多矩阵直接相关(A可能对应于kalmA等)。

需要更多代码来阐明A,B和D与声明的矩阵之间的关系(如果有)。在openCV库中设置断点可能会有所帮助。

列出矩阵大小可以提供一个见解:

Variable  Size   Variable  Size   Variable  Size 
kalmA 6x6 kalmQ 6x6 kalmR 3x3
kalmB 6x6 kalmS 6x6
kalmH 6x6 kalmP 6x6

一种。矩阵大小

由于 kalmR是唯一大小不同的矩阵,因此该矩阵可能是断言失败的来源。

如果断言仅涉及其他6x6矩阵的任何三重组合,则不会触发断言,但会触发。这表明矩阵变量 kalmR是开始跟踪代码的有用变量。

该逻辑假定A,B和D映射到表中列出的三个矩阵。

b。转置矩阵

数组的大小可能正确,但可能会错误地转置。

上表假设矩阵以6x6格式解释,而不是1x36 vector 或其转置,36x1列格式。可以设置它们在编译器提示的 flags & CV_GEMM_B_T表达式中的关联标志,以指示阵列是MxN还是NxM格式。

或者,可以重写违规矩阵的初始化值,使其符合openCV的GEMM(通用矩阵乘法)功能所期望的格式。该操作被描述为通用的,因为它包含的内容不止于两个矩阵之间的乘法。

C。复合错误

错误消息可能是两点a的某种组合。和b。

替代解释

另一种解释是断言的编码不正确。错误消息中B矩阵的出现似乎与断言的意图不一致。
//should that solitary B be an A?
D.rows == .. A.rows && D.cols == .. B.cols && D.type() == A.type()

逻辑和中的最后一个操作数正在测试两个矩阵D和A的类型。
D.type() == A.type()
在类型比较之前,是一对和操作数,分别比较D和A的行数以及D和A的列数。
//simplified assertion with B replaced by A
D.rows == .. A.rows && D.cols == .. A.cols

在明确检查两个矩阵的类型之前,断言似乎是在检查两个矩阵是否相等。

由于 type()短路,因此具有不同行数或列数的任意两个矩阵将排除对断言中对 &&的调用。然而,在最初的断言中,仅测试D和A的一个维度是否相等,这表明检查是确定两个矩阵是否兼容乘法。

将A替换为B时,适用相同的逻辑:
D.rows == .. B.rows && D.cols == .. B.cols && D.type == B.type()
矩阵运算之前的肯定检查

令人惊讶的是,从编译器发出的复杂错误消息中,我们可以猜测与断言关联的矩阵运算-无需访问openCV库的源代码且无需任何openCV文档即可实现此操作。

逻辑和操作数中有足够的信息来部分恢复与openCV GEMM函数中的已编程矩阵方程式一致(触发错误消息)的矩阵方程式(涉及A,B和D)。

这与在文件中查找特定功能和行号不同。区别在于我们根据断言中测试的一系列数学特性来推断矩阵运算的顺序。

逻辑如下:

一种。初步猜测

断言的重点是变量D,因为它出现在每个和操作数中。

该断言暗示D必须以某种方式与A和B兼容,而没有提及A与B的适用性。

也许这对矩阵先前已经比较过并且在某种意义上是兼容的。(在错误消息中,与A和B有关的位掩码 CV_GEMM_A_TCV_GEMM_B_T的存在支持此 View -A和B的信息,与D不同包含在单数 flags中。

这也暗示了为什么断言中没有类型比较 D.type() == B.type(),因为它会是多余的)。

考虑到这一点,并用重新排序以收集相似项的操作数重新编写断言,我们有:
D.rows == .. A.cols && D.type() == A.type() && D.cols == .. B.rows

D的行大小与A的列大小的比较建议使用 D * A,这是一个乘法运算(加法运算将需要比较此处未发生的每个矩阵维度)。

同样对于D和B-在这种情况下,将D的列大小与B的行大小进行检查-此测试与乘法运算一致,因此我们有 B * D

建议将这些术语收集在一起,建议 D * A + B * D或可能的 D * A - B * D或一些类似的矩阵组合由GEMM函数执行。

b。二次猜测

而不是继续作为乘法或加法操作数,D被重新发明为存储A和B之间的某些矩阵运算序列的结果。最简单的运算序列是 A * BA + B

断言中的行和列检查支持以前的猜测 D = A * B

配对的变量A,B与折减 B = D * AA = B * D等其他组合充分相关

暂时用指定给该变量的字母表示D在作为结果目标的过程中的作用。

C。有任何猜测能恢复矩阵运算吗?

阅读openCV文档时,第二个猜测被标识为最接近正确的描述。

特别是,触发断言的openCV函数可以是以下三个例程之一: cvMatMulcvMatMulAddcvGEMM,其相应的矩阵运算是:
D =   A * B         // cvMatMul
D = A * B + C // cvMatMulAdd
D = α A * B + β C // cvGEMM - Generalized Matrix Multiplication
// alpha, beta are scalars unlike A, B, C, D

有关这些函数声明的更多信息,请参见 here

A和B的按位 flags变量

在上面,我们假设 flags变量中的位字段由CV_GEMM_A_T和CV_GEMM_B_T标识。类似的讨论适用于这些标志设置的各种组合。

当与 CV_GEMM_A_TCV_GEMM_B_T对应的位不为零时,将应用两个断言中的第一个(素数表示转置操作):
// matrix-size selected by the conditional operator when the ...
D.rows == .. A'.rows && D.cols == .. B'.cols // ... bit fields are set
D.rows == .. A .cols && D.cols == .. B .rows // ... bit fields are unset

为了进行比较,当子表达式 flags & CV_GEMM_A_Tflags & CV_GEMM_B_T为零时,断言采用不同的形式。

错误消息暗示flags变量至少代表矩阵A和B。openCV文档指定所有三个输入矩阵A,B和C都可以由单个变量表示。

最后一点:矩阵操作之前的肯定检查

在抢占断言所暗示的特定矩阵计算之前,我们缩小了通过代码的可能路径以及矩阵算法所驻留的位置。

为了便于进行这种合理的猜测,应以某种形式编写用于矩阵计算的断言,以暗示它们所保护的基础矩阵运算。

在这里,我们研究了简单的矩阵表达式。当遇到较少的琐碎矩阵算法生成的类似错误消息时,所描述的方法可能被证明对解密在触发的断言中编码的加密矩阵操作很有用。

扩展:自动生成断言语句

也许可以使用模板来编写矩阵代码以实现此类断言的自动生成。可以对矩阵类和矩阵操作进行编码,以促进此类检查的生成。

关于c++ - OpenCV卡尔曼滤波器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10459126/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com