TriangulatePoints and vector<Point2f> or CV_XXFC2 Matrices (Bug #2167)
Description
I noticed that triangulatePoints does not work if used with vector<Point2f> or CV_XXFC2 matrices as input. This is because the underlying C function cvTriangulatePoints only works with points placed in 2xN matrices, while triangulatePoints uses the new way with InputArray, which usually means that everything is converted to a matrix of 2 channels (for 2D data)
So either cvTriangulate has to be changed to deal with the m-channel matrices or (more simply) we need to reshape the matrices before passing them to cvTriangulatePoints.
I don't know if it's the better way to do it but maybe at line 432 of triangulate.cpp we should put
Mat points1 = _projPoints1.getMat().reshape(1,2), points2 = _projPoints2.getMat().reshape(1,2);
so that the matrices passed to cvTriangulate are in the proper format.
Associated revisions
fixed #2167
git-svn-id: file://localhost/home/tolik/svnrepo/trunk@9047 c5418bc3-7546-4aae-8bad-fa6f2f3e53e6
fixed #2167
revert my incorrect fix of #2167
git-svn-id: file://localhost/home/tolik/svnrepo/trunk@9049 c5418bc3-7546-4aae-8bad-fa6f2f3e53e6
revert my incorrect fix of #2167
fixed #2167
git-svn-id: file://localhost/home/tolik/svnrepo/trunk@9050 c5418bc3-7546-4aae-8bad-fa6f2f3e53e6
fixed #2167
updated doc on triangulatePoints (#2167)
Merge pull request #2167 from ilya-lavrenov:tapi_kern_warn
History
Updated by Simone Gasparini over 12 years ago
Sorry, it seems that the solution is a bit more complicated than that.
In order to convert a vector<Point2f> P into a single-channel matrix 2xN we have to do this
Mat(P).reshape( 1, P.size() ).t()
So a rough patch may be something like this
Mat points1 = _projPoints1.getMat(), points2 = _projPoints2.getMat(); int npts1 = points1.checkVector(2); int npts2 = points2.checkVector(2); CV_Assert( npts1 == npts2 && npts1 > 0); points1 = points1.reshape( 1, npts1 ).t(); points2 = points2.reshape( 1, npts2 ).t();
But I'm sure you guys have a smarter and better way to do that :)
S.
Updated by Maria Dimashova over 12 years ago
Thanks! Fixed in r9047.
- Status changed from Open to Done
- Assignee set to Maria Dimashova
Updated by Simone Gasparini over 12 years ago
Sorry I gave you the wrong line number, line 432 belongs to the correctMatches, the correct line is 416.
Also, as i wrote in the update of this bug .reshape(1,2) is not correct, the output matrix shape will be correct (2xN) but the data inside it won't, because the points will be now in this format
[x0 y0 x1 y2... x(N/2) y(N/2); x(N/2 + 1) y(N/2 + 1) .... x(N) y(N)]
Here is what i had proposed instead
Mat points1 = _projPoints1.getMat(), points2 = _projPoints2.getMat(); int npts1 = points1.checkVector(2); int npts2 = points2.checkVector(2); CV_Assert( npts1 == npts2 && npts1 > 0); points1 = points1.reshape( 1, npts1 ).t(); points2 = points2.reshape( 1, npts2 ).t();
instead of
[x0 x1... x(N); y0 y1 .... y(N)]
I'm really sorry for the wrong reference for the line number :(
PS
I attach a sample of the code showing the conversion problem.
- File testbug.cpp added
Updated by Maria Dimashova over 12 years ago
Thanks again! It's also my fault. I had to be more careful. Fixed in 839761fa.
Updated by Ilya Lysenkov over 12 years ago
Documentation should be updated too.
- Status changed from Done to Open
Updated by Andrey Kamaev over 12 years ago
- Target version set to 2.4.3
Updated by Pavel Gurevich over 12 years ago
Updated from the trunk yesterday, but still see wrong behavior of reshape(). The number of channels does not change under any condition via reshape().
#include <opencv2/core/core.hpp> #include <iostream> #include <vector> using namespace std; using namespace cv; void print_size( const Mat& k ) { cout << k.size( ).width << "x" << k.size( ).height << "@" << k.channels( ) << endl; } template < typename T > void show_mat( const Mat& k ) { print_size( k ); for ( int j = 0; j < k.size( ).height; ++ j ) { for ( int i = 0; i < k.size( ).width; ++ i ) cout << k.at < T > ( j, i ) << ' '; cout << endl; } } int main( int argc, char *argv[ ] ) { vector < Point2f > pts; pts.push_back( Point2f( 1, 2 ) ); pts.push_back( Point2f( 3, 4 ) ); Mat m( pts ); show_mat < float >( m ); Mat m2; m.copyTo( m2 ); m2.reshape( 1 ); show_mat < float >( m2 ); Mat m3; m.copyTo( m3 ); m3.reshape( 1, m.size( ).area( ) * m.channels( ) ); show_mat < float >( m3 ); return 0; }
Output:
-------
*
1x2@2 1 3 1x2@2 1 3 1x2@2 1 3*