OpenCV Q&A Forum - RSS feedhttp://answers.opencv.org/questions/OpenCV answersenCopyright <a href="http://www.opencv.org">OpenCV foundation</a>, 2012-2018.Fri, 18 Sep 2015 03:40:00 -0500Unable to get Mahalanobis distancehttp://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/ I am trying to find the Mahalanobis distances between a test sample image and a few training data images (At&t database). I took http://answers.opencv.org/question/3494/adding-new-method-in-facerecognizer/ as reference for my code. When I run the code I am getting the following error
"OpenCV Error: Assertion failed (type == v2.type() && type == icovar.type() && sz == v2.size() && len == icovar.rows && len == icovar.cols) in Mahalanobis, file /home/opencv-2.4.9/modules/core/src/matmul.cpp, line 2244
"
Please find the code snippet for mahalanobis distance here http://pastebin.com/Mg8DbFQJ
Mat covar, invcovar, mean;
for(size_t sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) {
calcCovarMatrix(_projections[sampleIdx], covar, mean, CV_COVAR_SCRAMBLED|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
Mon, 07 Sep 2015 04:15:05 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/Answer by lm35 for <p>I am trying to find the Mahalanobis distances between a test sample image and a few training data images (At&t database). I took <a href="http://answers.opencv.org/question/3494/adding-new-method-in-facerecognizer/">http://answers.opencv.org/question/34...</a> as reference for my code. When I run the code I am getting the following error </p>
<p>"OpenCV Error: Assertion failed (type == v2.type() && type == icovar.type() && sz == v2.size() && len == icovar.rows && len == icovar.cols) in Mahalanobis, file /home/opencv-2.4.9/modules/core/src/matmul.cpp, line 2244
"</p>
<p>Please find the code snippet for mahalanobis distance here <a href="http://pastebin.com/Mg8DbFQJ">http://pastebin.com/Mg8DbFQJ</a></p>
<pre><code>Mat covar, invcovar, mean;
for(size_t sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) {
calcCovarMatrix(_projections[sampleIdx], covar, mean, CV_COVAR_SCRAMBLED|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?answer=70838#post-id-70838I modified the code as in the below link
http://pastebin.com/pZGEYNwb
Mat covar, invcovar, mean;
calcCovarMatrix(_projections, covar, mean, CV_COVAR_NORMAL|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
//////For Calculating Mahalanobis distance///////////////"_projections"->Training images(40x10)//////"q" -> TestSample///////
for(size_t sampleIdx = 0; sampleIdx <_projections.size(); sampleIdx++) {
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
And for this I am getting distance vector as below
http://pastebin.com/9KCr7LTs
The above values are the distances calculated between a particular test image and 400 training images, where the test image is one among the training image itself.
So as per your comment, have I went wrong somewhere when I modified.
Can you please tell me whether the distance vector I got is proper or not.
Mon, 14 Sep 2015 23:33:42 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?answer=70838#post-id-70838Comment by lm35 for <p>I modified the code as in the below link</p>
<p><a href="http://pastebin.com/pZGEYNwb">http://pastebin.com/pZGEYNwb</a></p>
<pre><code>Mat covar, invcovar, mean;
calcCovarMatrix(_projections, covar, mean, CV_COVAR_NORMAL|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
//////For Calculating Mahalanobis distance///////////////"_projections"->Training images(40x10)//////"q" -> TestSample///////
for(size_t sampleIdx = 0; sampleIdx <_projections.size(); sampleIdx++) {
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
<p>And for this I am getting distance vector as below</p>
<p><a href="http://pastebin.com/9KCr7LTs">http://pastebin.com/9KCr7LTs</a></p>
<p>The above values are the distances calculated between a particular test image and 400 training images, where the test image is one among the training image itself.</p>
<p>So as per your comment, have I went wrong somewhere when I modified.
Can you please tell me whether the distance vector I got is proper or not.</p>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70935#post-id-70935Could you please tell me, the type of data for which you got negative Mahalanobis distance. The data set which I tried was At&t database with 40 class, where each class has 10 grayscale sample images. For this data I didn't get negative values.Tue, 15 Sep 2015 23:29:39 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70935#post-id-70935Comment by berak for <p>I modified the code as in the below link</p>
<p><a href="http://pastebin.com/pZGEYNwb">http://pastebin.com/pZGEYNwb</a></p>
<pre><code>Mat covar, invcovar, mean;
calcCovarMatrix(_projections, covar, mean, CV_COVAR_NORMAL|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
//////For Calculating Mahalanobis distance///////////////"_projections"->Training images(40x10)//////"q" -> TestSample///////
for(size_t sampleIdx = 0; sampleIdx <_projections.size(); sampleIdx++) {
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
<p>And for this I am getting distance vector as below</p>
<p><a href="http://pastebin.com/9KCr7LTs">http://pastebin.com/9KCr7LTs</a></p>
<p>The above values are the distances calculated between a particular test image and 400 training images, where the test image is one among the training image itself.</p>
<p>So as per your comment, have I went wrong somewhere when I modified.
Can you please tell me whether the distance vector I got is proper or not.</p>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70884#post-id-70884i tried your solution, and found, that it needed a normalization of the covars (to avoid neg numbers in Mahalanobis())
calcCovarMatrix(features, covar, _mean, CV_COVAR_NORMAL|CV_COVAR_ROWS, CV_32F);
covar /= (features.rows-1);
invert(covar, icovar, DECOMP_SVD);Tue, 15 Sep 2015 06:14:48 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70884#post-id-70884Comment by berak for <p>I modified the code as in the below link</p>
<p><a href="http://pastebin.com/pZGEYNwb">http://pastebin.com/pZGEYNwb</a></p>
<pre><code>Mat covar, invcovar, mean;
calcCovarMatrix(_projections, covar, mean, CV_COVAR_NORMAL|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
//////For Calculating Mahalanobis distance///////////////"_projections"->Training images(40x10)//////"q" -> TestSample///////
for(size_t sampleIdx = 0; sampleIdx <_projections.size(); sampleIdx++) {
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
<p>And for this I am getting distance vector as below</p>
<p><a href="http://pastebin.com/9KCr7LTs">http://pastebin.com/9KCr7LTs</a></p>
<p>The above values are the distances calculated between a particular test image and 400 training images, where the test image is one among the training image itself.</p>
<p>So as per your comment, have I went wrong somewhere when I modified.
Can you please tell me whether the distance vector I got is proper or not.</p>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70842#post-id-70842ah, nice, so not the covars of a *single* projection, but from *all* of them, right ?
how long did it take ? (you're calling predict() per test sample, so the expensive covar calculation/inverting should go to a different place, e.g. after the training)
"Can you please tell me whether the distance vector I got is proper or not." - not really. . you will have to loop over your vector, to find the smalles element, and see if labels[indexOfSmallest] is the correct one.Tue, 15 Sep 2015 00:19:45 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70842#post-id-70842Comment by berak for <p>I modified the code as in the below link</p>
<p><a href="http://pastebin.com/pZGEYNwb">http://pastebin.com/pZGEYNwb</a></p>
<pre><code>Mat covar, invcovar, mean;
calcCovarMatrix(_projections, covar, mean, CV_COVAR_NORMAL|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
//////For Calculating Mahalanobis distance///////////////"_projections"->Training images(40x10)//////"q" -> TestSample///////
for(size_t sampleIdx = 0; sampleIdx <_projections.size(); sampleIdx++) {
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
<p>And for this I am getting distance vector as below</p>
<p><a href="http://pastebin.com/9KCr7LTs">http://pastebin.com/9KCr7LTs</a></p>
<p>The above values are the distances calculated between a particular test image and 400 training images, where the test image is one among the training image itself.</p>
<p>So as per your comment, have I went wrong somewhere when I modified.
Can you please tell me whether the distance vector I got is proper or not.</p>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=71142#post-id-71142no idea, if i understand you right, but the value range for the distances should not matter at all for a nearest neighbour search.
was more asking: did you get less false predictions using Mahalanobis or L2 ?
trying to compare the reconstructed images might be a cute idea, have not tried that so far.Fri, 18 Sep 2015 03:40:00 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=71142#post-id-71142Comment by berak for <p>I modified the code as in the below link</p>
<p><a href="http://pastebin.com/pZGEYNwb">http://pastebin.com/pZGEYNwb</a></p>
<pre><code>Mat covar, invcovar, mean;
calcCovarMatrix(_projections, covar, mean, CV_COVAR_NORMAL|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
//////For Calculating Mahalanobis distance///////////////"_projections"->Training images(40x10)//////"q" -> TestSample///////
for(size_t sampleIdx = 0; sampleIdx <_projections.size(); sampleIdx++) {
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
<p>And for this I am getting distance vector as below</p>
<p><a href="http://pastebin.com/9KCr7LTs">http://pastebin.com/9KCr7LTs</a></p>
<p>The above values are the distances calculated between a particular test image and 400 training images, where the test image is one among the training image itself.</p>
<p>So as per your comment, have I went wrong somewhere when I modified.
Can you please tell me whether the distance vector I got is proper or not.</p>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70943#post-id-70943yale. but i alerady strolled far away from the opencv code, so i probably missed something elsewhere.
did your results improve (compared to say L2) ? definitely here.Wed, 16 Sep 2015 00:59:13 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70943#post-id-70943Comment by lm35 for <p>I modified the code as in the below link</p>
<p><a href="http://pastebin.com/pZGEYNwb">http://pastebin.com/pZGEYNwb</a></p>
<pre><code>Mat covar, invcovar, mean;
calcCovarMatrix(_projections, covar, mean, CV_COVAR_NORMAL|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
//////For Calculating Mahalanobis distance///////////////"_projections"->Training images(40x10)//////"q" -> TestSample///////
for(size_t sampleIdx = 0; sampleIdx <_projections.size(); sampleIdx++) {
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
<p>And for this I am getting distance vector as below</p>
<p><a href="http://pastebin.com/9KCr7LTs">http://pastebin.com/9KCr7LTs</a></p>
<p>The above values are the distances calculated between a particular test image and 400 training images, where the test image is one among the training image itself.</p>
<p>So as per your comment, have I went wrong somewhere when I modified.
Can you please tell me whether the distance vector I got is proper or not.</p>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70848#post-id-70848It took only fraction of a second to compute the distance vector. And the smallest distance corresponds to the matching training image.Tue, 15 Sep 2015 01:39:05 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70848#post-id-70848Comment by lm35 for <p>I modified the code as in the below link</p>
<p><a href="http://pastebin.com/pZGEYNwb">http://pastebin.com/pZGEYNwb</a></p>
<pre><code>Mat covar, invcovar, mean;
calcCovarMatrix(_projections, covar, mean, CV_COVAR_NORMAL|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
//////For Calculating Mahalanobis distance///////////////"_projections"->Training images(40x10)//////"q" -> TestSample///////
for(size_t sampleIdx = 0; sampleIdx <_projections.size(); sampleIdx++) {
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
<p>And for this I am getting distance vector as below</p>
<p><a href="http://pastebin.com/9KCr7LTs">http://pastebin.com/9KCr7LTs</a></p>
<p>The above values are the distances calculated between a particular test image and 400 training images, where the test image is one among the training image itself.</p>
<p>So as per your comment, have I went wrong somewhere when I modified.
Can you please tell me whether the distance vector I got is proper or not.</p>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=71141#post-id-71141Apologies if my doubt is silly. I'm not aware of how to do the comparison. mahalanobis distance is within the range 0-1 and Euclidean is in and around 10^3. So how can we get the improvement. I tried reconstruction and then the similarity. Is that one way of doing?Fri, 18 Sep 2015 03:33:48 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=71141#post-id-71141Comment by berak for <p>I modified the code as in the below link</p>
<p><a href="http://pastebin.com/pZGEYNwb">http://pastebin.com/pZGEYNwb</a></p>
<pre><code>Mat covar, invcovar, mean;
calcCovarMatrix(_projections, covar, mean, CV_COVAR_NORMAL|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
//////For Calculating Mahalanobis distance///////////////"_projections"->Training images(40x10)//////"q" -> TestSample///////
for(size_t sampleIdx = 0; sampleIdx <_projections.size(); sampleIdx++) {
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
<p>And for this I am getting distance vector as below</p>
<p><a href="http://pastebin.com/9KCr7LTs">http://pastebin.com/9KCr7LTs</a></p>
<p>The above values are the distances calculated between a particular test image and 400 training images, where the test image is one among the training image itself.</p>
<p>So as per your comment, have I went wrong somewhere when I modified.
Can you please tell me whether the distance vector I got is proper or not.</p>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70850#post-id-70850again, apologies for being misleading before, i did not get, that you're doing this on PCA/LDA projections, which are fairly small.Tue, 15 Sep 2015 02:00:00 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?comment=70850#post-id-70850Answer by berak for <p>I am trying to find the Mahalanobis distances between a test sample image and a few training data images (At&t database). I took <a href="http://answers.opencv.org/question/3494/adding-new-method-in-facerecognizer/">http://answers.opencv.org/question/34...</a> as reference for my code. When I run the code I am getting the following error </p>
<p>"OpenCV Error: Assertion failed (type == v2.type() && type == icovar.type() && sz == v2.size() && len == icovar.rows && len == icovar.cols) in Mahalanobis, file /home/opencv-2.4.9/modules/core/src/matmul.cpp, line 2244
"</p>
<p>Please find the code snippet for mahalanobis distance here <a href="http://pastebin.com/Mg8DbFQJ">http://pastebin.com/Mg8DbFQJ</a></p>
<pre><code>Mat covar, invcovar, mean;
for(size_t sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++) {
calcCovarMatrix(_projections[sampleIdx], covar, mean, CV_COVAR_SCRAMBLED|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
double dist=Mahalanobis( _projections[sampleIdx], q, invcovar );
// Add to the resulting distance array:
if(distances.needed()) {
distances.getMat().at<double>(sampleIdx) = dist;
}
if((dist < minDist) && (dist < _threshold)) {
minDist = dist;
minClass = _labels.at<int>((int)sampleIdx);
}
}
</code></pre>
http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?answer=70332#post-id-70332this condition: `len == icovar.rows && len == icovar.cols` can only be satisfied, if you took the covar mat of an `1d` column vector, like `img.reshape(1,img.total())`.
think of the covar Mat similar to `v * v.t()`
here's some simulation code:
Mat img = imread("im/lena.png",0);
resize(img,img,Size(8,8)); //haha, dare more ;)
img.convertTo(img,CV_64F);
img = img.reshape(1,img.total());
Mat q = img * 1.25; // simulate q, needs same shape/type as img
Mat covar, invcovar, mean;
calcCovarMatrix(img, covar, mean, CV_COVAR_SCRAMBLED|CV_COVAR_ROWS,CV_64F); //Calculating the covariance matrix
cerr << "cov " << covar.size() << endl;
invert(covar, invcovar, DECOMP_SVD); //Calculating the inverse covariance matrix
cerr << "inv " << invcovar.size() << endl;
double dist=Mahalanobis( img, q, invcovar );
cerr << dist << endl;
// output:
cov [64 x 64]
inv [64 x 64]
0.25
now, here's the **bummer**:
if your img was 100x100, we're talking about a 10000x10000 covar Mat, then you have to invert *that* ....
i guess, this not feasible at all, even for a smallish db, like att_faces, it will sit weeks around doing only that.
maybe you can try the 'negated mahalanobis cosine distance' instead, which is **much** cheaper to calculate:
static double cosdistance(const cv::Mat &testFeature, const cv::Mat &trainFeature)
{
double a = trainFeature.dot(testFeature);
double b = trainFeature.dot(trainFeature);
double c = testFeature.dot(testFeature);
return -a / sqrt(b*c);
}
Tue, 08 Sep 2015 02:02:11 -0500http://answers.opencv.org/question/70292/unable-to-get-mahalanobis-distance/?answer=70332#post-id-70332