Plausible Interpretation
In reading the detailed error message, the assertation appears to be testing if A and B conform to the size of D. Presumably this check occurs prior to a computation(cvKalmanPredict
) involving these three matrices.
Matrices A, B and D specified in the error message may be directly related to three or more of the matrices provided in the example(A
corresponds perhaps to kalmA
etc).
More code is required to clarify the relation, if any, between A, B and D and the declared matrices. Setting breakpoints within the openCV library may help.
Listing the matrix sizes may provide an insight:
Variable Size Variable Size Variable Size
kalmA 6x6 kalmQ 6x6 kalmR 3x3
kalmB 6x6 kalmS 6x6
kalmH 6x6 kalmP 6x6
a. Matrix size
As kalmR
is the only matrix differing in size, this matrix could be a source for the assertion failure.
If the assertion exclusively involved any triple combination of the other 6x6 matrices, the assertion would not be triggered, but it does fire. This suggests the matrix variable kalmR
is a useful variable to begin tracking through the code.
This logic presumes A, B and D map to three of the matrices listed in the table.
b. Transposing Matrices
The arrays may be of correct size, but could be incorrectly transposed.
The above table assumes the matrices are interpreted in a 6x6 format rather then as a 1x36 vector or its transpose, 36x1 column-format. Their associated flag in the expression flags & CV_GEMM_B_T
prompted by the compiler, could be set to indicate whether the arrays are MxN or NxM formatted.
Alternatively, the initialization values of the offending matrices could be rewritten to conform to the format expected by openCV's GEMM(Generalized Matrix Multiplication) function. The operation is described as generalized since it encompasses more then just multiplications between two matrices.
c. Compounding errors
The error message could be some combination of both points a. and b.
Alternative explanation
Another interpretation is that the assertion is coded incorrectly. The presence of the B matrix in the error message appears to be inconsisent with the intent of the assertion.
//should that solitary B be an A?
D.rows == .. A.rows && D.cols == .. B.cols && D.type() == A.type()
The final operand in the logical and is testing the type of the two matrices D and A.
D.type() == A.type()
Preceding the type-comparison, is the pair of and-operands comparing the number of rows of D and A, and the number of columns of D and A, respectively.
//simplified assertion with B replaced by A
D.rows == .. A.rows && D.cols == .. A.cols
The assertion appears to be checking if two matrices are of equal dimensions, prior to making an explicit check of their type.
Any two matrices, with differing row or column count would exclude a call to type()
in the assertion, since &&
short-circuits. Yet in the original assertion, only one dimension of D and A is tested for equality, suggesting the check is to determine if the two matrices are compatible for multiplication.
The same logic applies when A is replaced with B:
D.rows == .. B.rows && D.cols == .. B.cols && D.type == B.type()
Assertive Checks Prior to a Matrix operation
Surprisingly, from the convoluted error message emitted by the compiler, we can guess the matrix operation associated with the assertion - this can be achieved without having access to the openCV library's source code and in the absence of any openCV documentation.
There is enough information within the logical and-operands to partially recover a matrix equation(involving A, B and D) that is consistent with the programmed matrix equation in the openCV GEMM function(that fires the error message).
This is different from locating a particular function and line number in a file. The distinction is we are inferring the sequence of matrix operations based on the series of mathematical properties tested in the assertion.
The logic is as follows:
a. Initial guess
The assertion's emphasis is on the variable D as it occurs in each of the and-operands.
The assertion hints that D must be compatible in some way with both A and B, whereas it does not mention the suitability of A with B.
Perhaps these pair of matrices were previously compared and found to be compatible in some sense.(In the error message, the presence of the bitmasks CV_GEMM_A_T
, CV_GEMM_B_T
pertaining to A and B, supports this view - information for A and B, unlike for D, is contained in the singular variable flags
.
This also hints why there is no type-comparison D.type() == B.type()
within the assertion as it would be redundant).
With this in mind and rewritting the assertion with the operands reordered to collect similar terms, we have:
D.rows == .. A.cols && D.type() == A.type() && D.cols == .. B.rows
The comparison of D's row size with the column size of A suggests D * A
, a multiplication operation(an addition operation would require a comparison of each matrix dimension which doesn't occur here).
Likewise for D and B - on this occasion D's column size is checked against the row size of B - this test is consistent with a multiplication operation, so we have B * D
.
Collecting these terms together, suggests D * A + B * D
or possibly D * A - B * D
or some similar matrix combination is executed by the GEMM function.
b. Second guess
Rather then continuing as a multiplicative or additive operand, D is reinvented to store the result of some sequence of matrix operations between A and B. The simplest operation-sequence is A * B
or A + B
.
The row and column checks in the assertion supports the former guess, D = A * B
.
The paired variables A, B are sufficiently related to discount the other combinations such as B = D * A
and A = B * D
The role of D in acting as a destination for the result, is tentatively indicated by the letter designated to this variable.
c. Did any of the guesses recover the matrix operations?
On reading the openCV documentation, the second guess is identified as being closest to the correct description.
In particular, the openCV function, triggering the assertion, could be one of three routines: cvMatMul
, cvMatMulAdd
or cvGEMM
and whose corresponding matrix operations are:
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
Further information on these function declarations are documented here
The bitwise flags
variable for A and B
In the above, we have assumed that the bit fields in the flags
variable identified by CV_GEMM_A_T and CV_GEMM_B_T. A similar discussion applies for various combinations of these flag settings.
When the bits corresponding to CV_GEMM_A_T
and CV_GEMM_B_T
are non-zero, the first of two assertions applies(the prime indicates the transpose operation):
// 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
For comparison, when the subexpressions flags & CV_GEMM_A_T
and flags & CV_GEMM_B_T
are zero, the assertion assumes a different form.
The error message implies the flags variable represents at least the matrices A and B. The openCV documentation specifies that all three input matrices A, B and C are representable by this single variable.
Final Point: Assertive Checks Prior to Matrix operations
In preempting the particular matrix computations the assertion alludes to, we are narrowing down the possible paths through the code and the location where the matrix algorithm resides.
To facilitate this reasoned guessing, assertions for matrix calculations should be written in a form to hint at the underlying matrix operations which they guard.
Here we have looked at simple matrix expressions. When confronted with similar error messages generated by less trivial matrix algorithms, the described approach might prove useful for deciphering the encrypted matrix operations, encoded in the triggered assertion.
Extension: Automatically Generating Assertion Statements
There may be a way to write matrix code to enable the automatic generation of such assertions, using templates perhaps. The matrix class and matrix operations could be coded to facilitate the generation of such checks.
kalman->transition_matrix->data
and others look like after you copied your matrices into them? – vsz