From b434835c52b1c12ba8cfc855e10bd4e551dbab7f Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Mon, 16 Feb 2015 14:06:45 +0800 Subject: [PATCH 01/10] Split files. --- gocv/gocv.swigcxx | 276 +--------------------------- gocv/{gocv.cpp => gocv_calib3d.cpp} | 2 +- gocv/{gocv.hpp => gocv_calib3d.hpp} | 0 gocv/gocv_core.i | 274 +++++++++++++++++++++++++++ gocv/gocv_test.go | 10 + 5 files changed, 288 insertions(+), 274 deletions(-) rename gocv/{gocv.cpp => gocv_calib3d.cpp} (97%) rename gocv/{gocv.hpp => gocv_calib3d.hpp} (100%) create mode 100644 gocv/gocv_core.i diff --git a/gocv/gocv.swigcxx b/gocv/gocv.swigcxx index be86413..b56bc86 100644 --- a/gocv/gocv.swigcxx +++ b/gocv/gocv.swigcxx @@ -1,278 +1,8 @@ %module gocv -%include "std_vector.i" %{ -#include "opencv2/core/types_c.h" -#include "opencv2/core/version.hpp" -#include "opencv2/core/core.hpp" -#include "gocv.hpp" +#include "gocv_calib3d.hpp" %} -%include "gocv.hpp" - -/* Classes defined in core.hpp */ -namespace cv { - - template class Size_; - template class Point_; - template class Rect_; - template class Vec; - - //////////////////////////////// Point_ //////////////////////////////// - - /*! - template 2D point class. - - The class defines a point in 2D space. Data type of the point coordinates is specified - as a template parameter. There are a few shorter aliases available for user convenience. - See cv::Point, cv::Point2i, cv::Point2f and cv::Point2d. - */ - template class Point_ - { - public: - typedef _Tp value_type; - - // various constructors - Point_(); - Point_(_Tp _x, _Tp _y); - Point_(const Point_& pt); - Point_(const CvPoint& pt); - Point_(const CvPoint2D32f& pt); - Point_(const Size_<_Tp>& sz); - Point_(const Vec<_Tp, 2>& v); - - Point_& operator = (const Point_& pt); - //! conversion to another data type - template operator Point_<_Tp2>() const; - - //! conversion to the old-style C structures - operator CvPoint() const; - operator CvPoint2D32f() const; - operator Vec<_Tp, 2>() const; - - //! dot product - _Tp dot(const Point_& pt) const; - //! dot product computed in double-precision arithmetics - double ddot(const Point_& pt) const; - //! cross-product - double cross(const Point_& pt) const; - //! checks whether the point is inside the specified rectangle - bool inside(const Rect_<_Tp>& r) const; - - _Tp x, y; //< the point coordinates - }; - - /*! - template 3D point class. - - The class defines a point in 3D space. Data type of the point coordinates is specified - as a template parameter. - - \see cv::Point3i, cv::Point3f and cv::Point3d - */ - template class Point3_ - { - public: - typedef _Tp value_type; - - // various constructors - Point3_(); - Point3_(_Tp _x, _Tp _y, _Tp _z); - Point3_(const Point3_& pt); - explicit Point3_(const Point_<_Tp>& pt); - Point3_(const CvPoint3D32f& pt); - Point3_(const Vec<_Tp, 3>& v); - - Point3_& operator = (const Point3_& pt); - //! conversion to another data type - template operator Point3_<_Tp2>() const; - //! conversion to the old-style CvPoint... - operator CvPoint3D32f() const; - //! conversion to cv::Vec<> - operator Vec<_Tp, 3>() const; - - //! dot product - _Tp dot(const Point3_& pt) const; - //! dot product computed in double-precision arithmetics - double ddot(const Point3_& pt) const; - //! cross product of the 2 3D points - Point3_ cross(const Point3_& pt) const; - - _Tp x, y, z; //< the point coordinates - }; - - //////////////////////////////// Size_ //////////////////////////////// - - /*! - The 2D size class - - The class represents the size of a 2D rectangle, image size, matrix size etc. - Normally, cv::Size ~ cv::Size_ is used. - */ - template class Size_ - { - public: - typedef _Tp value_type; - - //! various constructors - Size_(); - Size_(_Tp _width, _Tp _height); - Size_(const Size_& sz); - Size_(const CvSize& sz); - Size_(const CvSize2D32f& sz); - Size_(const Point_<_Tp>& pt); - - Size_& operator = (const Size_& sz); - //! the area (width*height) - _Tp area() const; - - //! conversion of another data type. - template operator Size_<_Tp2>() const; - - //! conversion to the old-style OpenCV types - operator CvSize() const; - operator CvSize2D32f() const; - - _Tp width, height; // the width and the height - }; - - //////////////////////////////// Rect_ //////////////////////////////// - - /*! - The 2D up-right rectangle class - - The class represents a 2D rectangle with coordinates of the specified data type. - Normally, cv::Rect ~ cv::Rect_ is used. - */ - template class Rect_ - { - public: - typedef _Tp value_type; - - //! various constructors - Rect_(); - Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height); - Rect_(const Rect_& r); - Rect_(const CvRect& r); - Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz); - Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2); - - Rect_& operator = ( const Rect_& r ); - //! the top-left corner - Point_<_Tp> tl() const; - //! the bottom-right corner - Point_<_Tp> br() const; - - //! size (width, height) of the rectangle - Size_<_Tp> size() const; - //! area (width*height) of the rectangle - _Tp area() const; - - //! conversion to another data type - template operator Rect_<_Tp2>() const; - //! conversion to the old-style CvRect - operator CvRect() const; - - //! checks whether the rectangle contains the point - bool contains(const Point_<_Tp>& pt) const; - - _Tp x, y, width, height; //< the top-left corner, as well as width and height of the rectangle - }; - - - %template(GcvSize2i) Size_; - %template(GcvSize2d_) Size_; - %template(GcvSize2f_) Size_; - - %template(GcvRect) Rect_; - - %template(GcvPoint2i) Point_; - %template(GcvPoint2f_) Point_; - %template(GcvPoint2d_) Point_; - - %template(GcvPoint3i) Point3_; - %template(GcvPoint3f_) Point3_; - %template(GcvPoint3d_) Point3_; - - - /* ----------------- Mat ----------------- */ - class Mat - { - public: - //! default constructor - Mat(); - //! constructs 2D matrix of the specified size and type - // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) - Mat(int rows, int cols, int type); - Mat(cv::Size size, int type); - //! constucts 2D matrix and fills it with the specified value _s. - Mat(int rows, int cols, int type, const cv::Scalar& s); - Mat(cv::Size size, int type, const cv::Scalar& s); - - //! copy constructor - Mat(const Mat& m); - - //! builds matrix from std::vector with or without copying the data - template explicit Mat(const vector<_Tp>& vec, bool copyData=false); - //! builds matrix from cv::Vec; the data is copied by default - template explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true); - //! builds matrix from cv::Matx; the data is copied by default - template explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true); - //! builds matrix from a 2D point - template explicit Mat(const Point_<_Tp>& pt, bool copyData=true); - //! builds matrix from a 3D point - template explicit Mat(const Point3_<_Tp>& pt, bool copyData=true); - - //! destructor - calls release() - ~Mat(); - - //! returns a new matrix header for the specified row - Mat row(int y) const; - //! returns a new matrix header for the specified column - Mat col(int x) const; - //! ... for the specified row span - Mat rowRange(int startrow, int endrow) const; - //! ... for the specified column span - Mat colRange(int startcol, int endcol) const; - //! ... for the specified diagonal - // (d=0 - the main diagonal, - // >0 - a diagonal from the lower half, - // <0 - a diagonal from the upper half) - Mat diag(int d=0) const; - //! constructs a square diagonal matrix which main diagonal is vector "d" - static Mat diag(const Mat& d); - - //! returns deep copy of the matrix, i.e. the data is copied - Mat clone() const; - - void assignTo( Mat& m, int type=-1 ) const; - - //! creates alternative matrix header for the same data, with different - // number of channels and/or different number of rows. see cvReshape. - Mat reshape(int cn, int rows=0) const; - Mat reshape(int cn, int newndims, const int* newsz) const; - - //! adds element to the end of 1d matrix (or possibly multiple elements when _Tp=Mat) - template void push_back(const _Tp& elem); - template void push_back(const Mat_<_Tp>& elem); - void push_back(const Mat& m); - //! removes several hyper-planes from bottom of the matrix - void pop_back(size_t nelems=1); - - //! special versions for 2D arrays (especially convenient for referencing image pixels) - template _Tp& at(cv::Point pt); - template const _Tp& at(cv::Point pt) const; - %template(gcvAtd) at; - %template(gcvAtf) at; - }; - -} - -/* Additional STL types */ -namespace std { - %template(GcvPoint3fVector) vector; - %template(GcvPoint2fVector) vector; - - %template(GcvIntVector) vector; - %template(GcvFloatVector) vector; -}; +%include "gocv_core.i" +%include "gocv_calib3d.hpp" diff --git a/gocv/gocv.cpp b/gocv/gocv_calib3d.cpp similarity index 97% rename from gocv/gocv.cpp rename to gocv/gocv_calib3d.cpp index 3458147..5732e28 100644 --- a/gocv/gocv.cpp +++ b/gocv/gocv_calib3d.cpp @@ -3,7 +3,7 @@ #include #include -#include "gocv.hpp" +#include "gocv_calib3d.hpp" cv::Mat GcvInitCameraMatrix2D(VecPoint3f objPts, VecPoint2f imgPts) { cv::Mat cameraMatrix; diff --git a/gocv/gocv.hpp b/gocv/gocv_calib3d.hpp similarity index 100% rename from gocv/gocv.hpp rename to gocv/gocv_calib3d.hpp diff --git a/gocv/gocv_core.i b/gocv/gocv_core.i new file mode 100644 index 0000000..924c98b --- /dev/null +++ b/gocv/gocv_core.i @@ -0,0 +1,274 @@ +%include "std_vector.i" + +%{ +#include "opencv2/core/types_c.h" +#include "opencv2/core/version.hpp" +#include "opencv2/core/core.hpp" +%} + +/* Classes defined in core.hpp */ +namespace cv { + + template class Size_; + template class Point_; + template class Rect_; + template class Vec; + + //////////////////////////////// Point_ //////////////////////////////// + + /*! + template 2D point class. + + The class defines a point in 2D space. Data type of the point coordinates is specified + as a template parameter. There are a few shorter aliases available for user convenience. + See cv::Point, cv::Point2i, cv::Point2f and cv::Point2d. + */ + template class Point_ + { + public: + typedef _Tp value_type; + + // various constructors + Point_(); + Point_(_Tp _x, _Tp _y); + Point_(const Point_& pt); + Point_(const CvPoint& pt); + Point_(const CvPoint2D32f& pt); + Point_(const Size_<_Tp>& sz); + Point_(const Vec<_Tp, 2>& v); + + Point_& operator = (const Point_& pt); + //! conversion to another data type + template operator Point_<_Tp2>() const; + + //! conversion to the old-style C structures + operator CvPoint() const; + operator CvPoint2D32f() const; + operator Vec<_Tp, 2>() const; + + //! dot product + _Tp dot(const Point_& pt) const; + //! dot product computed in double-precision arithmetics + double ddot(const Point_& pt) const; + //! cross-product + double cross(const Point_& pt) const; + //! checks whether the point is inside the specified rectangle + bool inside(const Rect_<_Tp>& r) const; + + _Tp x, y; //< the point coordinates + }; + + /*! + template 3D point class. + + The class defines a point in 3D space. Data type of the point coordinates is specified + as a template parameter. + + \see cv::Point3i, cv::Point3f and cv::Point3d + */ + template class Point3_ + { + public: + typedef _Tp value_type; + + // various constructors + Point3_(); + Point3_(_Tp _x, _Tp _y, _Tp _z); + Point3_(const Point3_& pt); + explicit Point3_(const Point_<_Tp>& pt); + Point3_(const CvPoint3D32f& pt); + Point3_(const Vec<_Tp, 3>& v); + + Point3_& operator = (const Point3_& pt); + //! conversion to another data type + template operator Point3_<_Tp2>() const; + //! conversion to the old-style CvPoint... + operator CvPoint3D32f() const; + //! conversion to cv::Vec<> + operator Vec<_Tp, 3>() const; + + //! dot product + _Tp dot(const Point3_& pt) const; + //! dot product computed in double-precision arithmetics + double ddot(const Point3_& pt) const; + //! cross product of the 2 3D points + Point3_ cross(const Point3_& pt) const; + + _Tp x, y, z; //< the point coordinates + }; + + //////////////////////////////// Size_ //////////////////////////////// + + /*! + The 2D size class + + The class represents the size of a 2D rectangle, image size, matrix size etc. + Normally, cv::Size ~ cv::Size_ is used. + */ + template class Size_ + { + public: + typedef _Tp value_type; + + //! various constructors + Size_(); + Size_(_Tp _width, _Tp _height); + Size_(const Size_& sz); + Size_(const CvSize& sz); + Size_(const CvSize2D32f& sz); + Size_(const Point_<_Tp>& pt); + + Size_& operator = (const Size_& sz); + //! the area (width*height) + _Tp area() const; + + //! conversion of another data type. + template operator Size_<_Tp2>() const; + + //! conversion to the old-style OpenCV types + operator CvSize() const; + operator CvSize2D32f() const; + + _Tp width, height; // the width and the height + }; + + //////////////////////////////// Rect_ //////////////////////////////// + + /*! + The 2D up-right rectangle class + + The class represents a 2D rectangle with coordinates of the specified data type. + Normally, cv::Rect ~ cv::Rect_ is used. + */ + template class Rect_ + { + public: + typedef _Tp value_type; + + //! various constructors + Rect_(); + Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height); + Rect_(const Rect_& r); + Rect_(const CvRect& r); + Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz); + Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2); + + Rect_& operator = ( const Rect_& r ); + //! the top-left corner + Point_<_Tp> tl() const; + //! the bottom-right corner + Point_<_Tp> br() const; + + //! size (width, height) of the rectangle + Size_<_Tp> size() const; + //! area (width*height) of the rectangle + _Tp area() const; + + //! conversion to another data type + template operator Rect_<_Tp2>() const; + //! conversion to the old-style CvRect + operator CvRect() const; + + //! checks whether the rectangle contains the point + bool contains(const Point_<_Tp>& pt) const; + + _Tp x, y, width, height; //< the top-left corner, as well as width and height of the rectangle + }; + + + %template(GcvSize2i) Size_; + %template(GcvSize2d_) Size_; + %template(GcvSize2f_) Size_; + + %template(GcvRect) Rect_; + + %template(GcvPoint2i) Point_; + %template(GcvPoint2f_) Point_; + %template(GcvPoint2d_) Point_; + + %template(GcvPoint3i) Point3_; + %template(GcvPoint3f_) Point3_; + %template(GcvPoint3d_) Point3_; + + + /* ----------------- Mat ----------------- */ + class Mat + { + public: + //! default constructor + Mat(); + //! constructs 2D matrix of the specified size and type + // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.) + Mat(int rows, int cols, int type); + Mat(cv::Size size, int type); + //! constucts 2D matrix and fills it with the specified value _s. + Mat(int rows, int cols, int type, const cv::Scalar& s); + Mat(cv::Size size, int type, const cv::Scalar& s); + + //! copy constructor + Mat(const Mat& m); + + //! builds matrix from std::vector with or without copying the data + template explicit Mat(const vector<_Tp>& vec, bool copyData=false); + //! builds matrix from cv::Vec; the data is copied by default + template explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true); + //! builds matrix from cv::Matx; the data is copied by default + template explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true); + //! builds matrix from a 2D point + template explicit Mat(const Point_<_Tp>& pt, bool copyData=true); + //! builds matrix from a 3D point + template explicit Mat(const Point3_<_Tp>& pt, bool copyData=true); + + //! destructor - calls release() + ~Mat(); + + //! returns a new matrix header for the specified row + Mat row(int y) const; + //! returns a new matrix header for the specified column + Mat col(int x) const; + //! ... for the specified row span + Mat rowRange(int startrow, int endrow) const; + //! ... for the specified column span + Mat colRange(int startcol, int endcol) const; + //! ... for the specified diagonal + // (d=0 - the main diagonal, + // >0 - a diagonal from the lower half, + // <0 - a diagonal from the upper half) + Mat diag(int d=0) const; + //! constructs a square diagonal matrix which main diagonal is vector "d" + static Mat diag(const Mat& d); + + //! returns deep copy of the matrix, i.e. the data is copied + Mat clone() const; + + void assignTo( Mat& m, int type=-1 ) const; + + //! creates alternative matrix header for the same data, with different + // number of channels and/or different number of rows. see cvReshape. + Mat reshape(int cn, int rows=0) const; + Mat reshape(int cn, int newndims, const int* newsz) const; + + //! adds element to the end of 1d matrix (or possibly multiple elements when _Tp=Mat) + template void push_back(const _Tp& elem); + template void push_back(const Mat_<_Tp>& elem); + void push_back(const Mat& m); + //! removes several hyper-planes from bottom of the matrix + void pop_back(size_t nelems=1); + + //! special versions for 2D arrays (especially convenient for referencing image pixels) + template _Tp& at(cv::Point pt); + template const _Tp& at(cv::Point pt) const; + %template(gcvAtd) at; + %template(gcvAtf) at; + }; + +} + +/* Additional STL types */ +namespace std { + %template(GcvPoint3fVector) vector; + %template(GcvPoint2fVector) vector; + + %template(GcvIntVector) vector; + %template(GcvFloatVector) vector; +}; diff --git a/gocv/gocv_test.go b/gocv/gocv_test.go index f1a52e8..5b1dbd1 100644 --- a/gocv/gocv_test.go +++ b/gocv/gocv_test.go @@ -64,6 +64,16 @@ func TestGcvCalibrateCamera(t *testing.T) { imgSize := NewGcvSize2i(1920, 1080) camMat := GcvInitCameraMatrix2D(objPts, imgPts) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) GcvCalibrateCamera(objPts, imgPts, imgSize, camMat) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) + spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) } From fb125388820933f377444466731503fa38a9c624 Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Mon, 16 Feb 2015 16:48:18 +0800 Subject: [PATCH 02/10] Wrap initCameraMatrix2D with mat64. --- gocv/gocv.go | 31 +++++++++++++++-- gocv/gocv_calib3d.cpp | 19 +++++------ gocv/gocv_calib3d.go | 66 +++++++++++++++++++++++++++++++++++++ gocv/gocv_calib3d.hpp | 7 ++-- gocv/gocv_core.i | 35 +++++++++++++++++--- gocv/gocv_test.go | 77 +++++++++++++++++++++---------------------- 6 files changed, 173 insertions(+), 62 deletions(-) create mode 100644 gocv/gocv_calib3d.go diff --git a/gocv/gocv.go b/gocv/gocv.go index 4f2e5f9..bfb12f9 100644 --- a/gocv/gocv.go +++ b/gocv/gocv.go @@ -3,8 +3,9 @@ package gocv // #cgo CXXFLAGS: -std=c++11 // #cgo darwin pkg-config: opencv import "C" +import "github.com/gonum/matrix/mat64" -func NewGcvPoint3f(x, y, z float32) GcvPoint3f_ { +func NewGcvPoint3f(x, y, z float64) GcvPoint3f_ { return NewGcvPoint3f_(float32(x), float32(y), float32(z)) } @@ -12,7 +13,7 @@ func NewGcvPoint3d(x, y, z float64) GcvPoint3d_ { return NewGcvPoint3d_(float64(x), float64(y), float64(z)) } -func NewGcvPoint2f(x, y float32) GcvPoint2f_ { +func NewGcvPoint2f(x, y float64) GcvPoint2f_ { return NewGcvPoint2f_(float32(x), float32(y)) } @@ -20,10 +21,34 @@ func NewGcvPoint2d(x, y float64) GcvPoint2d_ { return NewGcvPoint2d_(float64(x), float64(y)) } -func NewGcvSize2f(x, y float32) GcvSize2f_ { +func NewGcvSize2f(x, y float64) GcvSize2f_ { return NewGcvSize2f_(float32(x), float32(y)) } func NewGcvSize2d(x, y float64) GcvSize2d_ { return NewGcvSize2d_(float64(x), float64(y)) } + +// Convert Mat, which defined by SWIG, to mat64.Dense. +// The reason is the latter is much easier to handle +// in Go. +// GcvMat is assumed to be 2-dimensional matrix. +func MatToMat64(mat Mat) *mat64.Dense { + col := mat.GetCols() + row := mat.GetRows() + + data := []float64{} + + for i := 0; i < row; i++ { + for j := 0; j < col; j++ { + if fltPtr, ok := mat.GcvAtd(i, j).(*float64); ok { + data = append(data, *fltPtr) + } else { + panic("Non *float64 passed to MatToMat64") + } + + } + } + + return mat64.NewDense(row, col, data) +} diff --git a/gocv/gocv_calib3d.cpp b/gocv/gocv_calib3d.cpp index 5732e28..b636cef 100644 --- a/gocv/gocv_calib3d.cpp +++ b/gocv/gocv_calib3d.cpp @@ -5,7 +5,7 @@ #include "gocv_calib3d.hpp" -cv::Mat GcvInitCameraMatrix2D(VecPoint3f objPts, VecPoint2f imgPts) { +cv::Mat GcvInitCameraMatrix2D_(VecPoint3f objPts, VecPoint2f imgPts) { cv::Mat cameraMatrix; std::vector objPtsArr; @@ -15,30 +15,27 @@ cv::Mat GcvInitCameraMatrix2D(VecPoint3f objPts, VecPoint2f imgPts) { imgPtsArr.push_back(imgPts); cameraMatrix = cv::initCameraMatrix2D(objPtsArr, imgPtsArr, cv::Size(1920, 1080), 1); - std::cout << cameraMatrix.type() << std::endl; return cameraMatrix; } -double GcvCalibrateCamera(VecPoint3f objPts, VecPoint2f imgPts, - cv::Size imgSize, cv::Mat cameraMatrix) { +double GcvCalibrateCamera_(VecPoint3f objPts, VecPoint2f imgPts, + cv::Size imgSize, cv::Mat& cameraMatrix, + cv::Mat& rvec, cv::Mat& tvec) { std::vector objPtsArr; std::vector imgPtsArr; std::vector rvecs, tvecs; cv::Mat distCoeffs; - double rtn; objPtsArr.push_back(objPts); imgPtsArr.push_back(imgPts); - std::cout << "init Camera" << cameraMatrix << std::endl; - rtn = cv::calibrateCamera(objPtsArr, imgPtsArr, imgSize, - cameraMatrix, distCoeffs, rvecs, tvecs); + cameraMatrix, distCoeffs, + rvecs, tvecs); - std::cout << "final Camera" << cameraMatrix << std::endl; - std::cout << "final rvecs" << rvecs[0] << std::endl; - std::cout << "final tvecs" << tvecs[0] << std::endl; + rvec = rvecs[0]; + tvec = tvecs[0]; return rtn; } diff --git a/gocv/gocv_calib3d.go b/gocv/gocv_calib3d.go new file mode 100644 index 0000000..624b79a --- /dev/null +++ b/gocv/gocv_calib3d.go @@ -0,0 +1,66 @@ +package gocv + +// #cgo CXXFLAGS: -std=c++11 +// #cgo darwin pkg-config: opencv +import "C" +import "github.com/gonum/matrix/mat64" + +// GcvInitCameraMatrix2D takes one N-by-3 matrix and one +// N-by-2 Matrix as input. +// Each row in the input matrix represents a point in real +// world (objPts) or in image (imgPts). +// Return: the camera matrix. +func GcvInitCameraMatrix2D(objPts, imgPts *mat64.Dense) (camMat *mat64.Dense) { + nObjPts, objCol := objPts.Dims() + nImgPts, imgCol := imgPts.Dims() + + if objCol != 3 || imgCol != 2 || nObjPts != nImgPts { + panic("Invalid dimensions for objPts and imgPts") + } + + objPtsVec := NewGcvPoint3fVector(int64(nObjPts)) + imgPtsVec := NewGcvPoint2fVector(int64(nObjPts)) + + for i := 0; i < nObjPts; i++ { + objPtsVec.Set(i, NewGcvPoint3f( + objPts.At(i, 0), objPts.At(i, 1), objPts.At(i, 2))) + } + + for i := 0; i < nObjPts; i++ { + imgPtsVec.Set(i, NewGcvPoint2f( + imgPts.At(i, 0), imgPts.At(i, 1))) + } + + camMat = MatToMat64(GcvInitCameraMatrix2D_(objPtsVec, imgPtsVec)) + return camMat +} + +// func TestGcvCalibrateCamera(t *testing.T) { +// objPts := NewGcvPoint3fVector(int64(4)) +// objPts.Set(0, NewGcvPoint3f(0, 25, 0)) +// objPts.Set(1, NewGcvPoint3f(0, -25, 0)) +// objPts.Set(2, NewGcvPoint3f(-47, 25, 0)) +// objPts.Set(3, NewGcvPoint3f(-47, -25, 0)) + +// imgPts := NewGcvPoint2fVector(int64(4)) +// imgPts.Set(0, NewGcvPoint2f(1136.4140625, 1041.89208984)) +// imgPts.Set(1, NewGcvPoint2f(1845.33190918, 671.39581299)) +// imgPts.Set(2, NewGcvPoint2f(302.73373413, 634.79998779)) +// imgPts.Set(3, NewGcvPoint2f(1051.46154785, 352.76107788)) + +// imgSize := NewGcvSize2i(1920, 1080) + +// camMat := GcvInitCameraMatrix2D(objPts, imgPts) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) + +// rvec := NewMat() +// tvec := NewMat() + +// GcvCalibrateCamera(objPts, imgPts, imgSize, camMat, rvec, tvec) + +// MatToMat64(camMat) +// } diff --git a/gocv/gocv_calib3d.hpp b/gocv/gocv_calib3d.hpp index 3710c3c..09195d2 100644 --- a/gocv/gocv_calib3d.hpp +++ b/gocv/gocv_calib3d.hpp @@ -5,7 +5,8 @@ typedef std::vector VecPoint3f; typedef std::vector VecPoint2f; -cv::Mat GcvInitCameraMatrix2D(VecPoint3f objPts, VecPoint2f imgPts); +cv::Mat GcvInitCameraMatrix2D_(VecPoint3f objPts, VecPoint2f imgPts); -double GcvCalibrateCamera(VecPoint3f objPts, VecPoint2f imgPts, - cv::Size2i imgSize, cv::Mat cameraMatrix); +double GcvCalibrateCamera_(VecPoint3f objPts, VecPoint2f imgPts, + cv::Size2i imgSize, cv::Mat& cameraMatrix, + cv::Mat& rvec, cv::Mat& tvec); diff --git a/gocv/gocv_core.i b/gocv/gocv_core.i index 924c98b..ee63dc6 100644 --- a/gocv/gocv_core.i +++ b/gocv/gocv_core.i @@ -1,8 +1,6 @@ %include "std_vector.i" %{ -#include "opencv2/core/types_c.h" -#include "opencv2/core/version.hpp" #include "opencv2/core/core.hpp" %} @@ -256,12 +254,39 @@ namespace cv { void pop_back(size_t nelems=1); //! special versions for 2D arrays (especially convenient for referencing image pixels) + + template _Tp& at(int i0=0); + template const _Tp& at(int i0=0) const; + + template _Tp& at(int i0, int i1); + template const _Tp& at(int i0, int i1) const; + + template _Tp& at(int i0, int i1, int i2); + template const _Tp& at(int i0, int i1, int i2) const; + + template _Tp& at(const int* idx); + template const _Tp& at(const int* idx) const; + + template _Tp& at(const Vec& idx); + template const _Tp& at(const Vec& idx) const; template _Tp& at(cv::Point pt); template const _Tp& at(cv::Point pt) const; - %template(gcvAtd) at; - %template(gcvAtf) at; - }; + %template(gcvAtf) at; + %template(gcvAtd) at; + + /*! includes several bit-fields: + - the magic signature + - continuity flag + - depth + - number of channels + */ + int flags; + //! the matrix dimensionality, >= 2 + int dims; + //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions + int rows, cols; + }; } /* Additional STL types */ diff --git a/gocv/gocv_test.go b/gocv/gocv_test.go index 5b1dbd1..bd0d775 100644 --- a/gocv/gocv_test.go +++ b/gocv/gocv_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/davecgh/go-spew/spew" + "github.com/gonum/matrix/mat64" ) func TestNewGcvPoint3f(t *testing.T) { @@ -28,52 +29,48 @@ func TestMat(t *testing.T) { } func TestGcvInitCameraMatrix2D(t *testing.T) { - objPts := NewGcvPoint3fVector(int64(4)) - objPts.Set(0, NewGcvPoint3f(0, 25, 0)) - objPts.Set(1, NewGcvPoint3f(0, -25, 0)) - objPts.Set(2, NewGcvPoint3f(-47, 25, 0)) - objPts.Set(3, NewGcvPoint3f(-47, -25, 0)) + objPts := mat64.NewDense(4, 3, []float64{ + 0, 25, 0, + 0, -25, 0, + -47, 25, 0, + -47, -25, 0}) - imgPts := NewGcvPoint2fVector(int64(4)) - imgPts.Set(0, NewGcvPoint2f(1136.4140625, 1041.89208984)) - imgPts.Set(1, NewGcvPoint2f(1845.33190918, 671.39581299)) - imgPts.Set(2, NewGcvPoint2f(302.73373413, 634.79998779)) - imgPts.Set(3, NewGcvPoint2f(1051.46154785, 352.76107788)) + imgPts := mat64.NewDense(4, 2, []float64{ + 1136.4140625, 1041.89208984, + 1845.33190918, 671.39581299, + 302.73373413, 634.79998779, + 1051.46154785, 352.76107788}) camMat := GcvInitCameraMatrix2D(objPts, imgPts) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) + spew.Dump(camMat) } -func TestGcvCalibrateCamera(t *testing.T) { - objPts := NewGcvPoint3fVector(int64(4)) - objPts.Set(0, NewGcvPoint3f(0, 25, 0)) - objPts.Set(1, NewGcvPoint3f(0, -25, 0)) - objPts.Set(2, NewGcvPoint3f(-47, 25, 0)) - objPts.Set(3, NewGcvPoint3f(-47, -25, 0)) +// func TestGcvCalibrateCamera(t *testing.T) { +// objPts := NewGcvPoint3fVector(int64(4)) +// objPts.Set(0, NewGcvPoint3f(0, 25, 0)) +// objPts.Set(1, NewGcvPoint3f(0, -25, 0)) +// objPts.Set(2, NewGcvPoint3f(-47, 25, 0)) +// objPts.Set(3, NewGcvPoint3f(-47, -25, 0)) - imgPts := NewGcvPoint2fVector(int64(4)) - imgPts.Set(0, NewGcvPoint2f(1136.4140625, 1041.89208984)) - imgPts.Set(1, NewGcvPoint2f(1845.33190918, 671.39581299)) - imgPts.Set(2, NewGcvPoint2f(302.73373413, 634.79998779)) - imgPts.Set(3, NewGcvPoint2f(1051.46154785, 352.76107788)) +// imgPts := NewGcvPoint2fVector(int64(4)) +// imgPts.Set(0, NewGcvPoint2f(1136.4140625, 1041.89208984)) +// imgPts.Set(1, NewGcvPoint2f(1845.33190918, 671.39581299)) +// imgPts.Set(2, NewGcvPoint2f(302.73373413, 634.79998779)) +// imgPts.Set(3, NewGcvPoint2f(1051.46154785, 352.76107788)) - imgSize := NewGcvSize2i(1920, 1080) +// imgSize := NewGcvSize2i(1920, 1080) - camMat := GcvInitCameraMatrix2D(objPts, imgPts) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) +// camMat := GcvInitCameraMatrix2D(objPts, imgPts) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) - GcvCalibrateCamera(objPts, imgPts, imgSize, camMat) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) - spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) -} +// rvec := NewMat() +// tvec := NewMat() + +// GcvCalibrateCamera(objPts, imgPts, imgSize, camMat, rvec, tvec) + +// MatToMat64(camMat) +// } From c4a0fdeeab0759007ab941f77adab09baf09adf0 Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Mon, 16 Feb 2015 17:00:57 +0800 Subject: [PATCH 03/10] Rename type names to be more go-like. --- gocv/README.md | 24 ++++++++++++------------ gocv/gocv.go | 26 +++++++++++++------------- gocv/gocv_calib3d.go | 8 ++++---- gocv/gocv_core.i | 20 ++++++++++---------- gocv/gocv_test.go | 12 ++++++------ 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/gocv/README.md b/gocv/README.md index 898e4d5..a8cac6b 100644 --- a/gocv/README.md +++ b/gocv/README.md @@ -5,23 +5,23 @@ Wrap the core types in OpenCV. ## Supporting Types and Examples -| OpenCV C++ | Go OpenCV | Constructor | -|---------------|---------------|-------------------------------| -| `cv::Point2i` | `GcvPoint2i` | `NewGcvPoint2i(x, y int)` | -| `cv::Point2f` | `GcvPoint2f_` | `NewGcvPoint2f(x, y float32)` | -| `cv::Point2d` | `GcvPoint2d_` | `NewGcvPoint2d(x, y float64)` | -| `cv::Point3i` | `GcvPoint3i` | `NewGcvPoint3i(x, y, z int)` | -| `cv::Point3f` | `GcvPoint3f_` | `NewGcvPoint3f(x, y, z float32)` | -| `cv::Point3d` | `GcvPoint3d_` | `NewGcvPoint3d(x, y, z float64)` | -| `cv::Size2i` | `GcvSize2i` | `NewGcvSize2i(x, y int)` | -| `cv::Size2f` | `GcvSize2f_` | `NewGcvSize2f(x, y float32)` | -| `cv::Size2d` | `GcvSize2d_` | `NewGcvSize2d(x, y float64)` | +| OpenCV C++ | Go OpenCV | Constructor | +|---------------|-----------------|-------------------------------| +| `cv::Point2i` | `GcvPoint2i` | `NewGcvPoint2i(x, y int)` | +| `cv::Point2f` | `GcvPoint2f32_` | `NewGcvPoint2f32(x, y float64)` | +| `cv::Point2d` | `GcvPoint2f64_` | `NewGcvPoint2f64(x, y float64)` | +| `cv::Point3i` | `GcvPoint3i` | `NewGcvPoint3i(x, y, z int)` | +| `cv::Point3f` | `GcvPoint3f32_` | `NewGcvPoint3f32(x, y, z float64)` | +| `cv::Point3d` | `GcvPoint3f64_` | `NewGcvPoint3f64(x, y, z float64)` | +| `cv::Size2i` | `GcvSize2i` | `NewGcvSize2i(x, y int)` | +| `cv::Size2f` | `GcvSize2f32_` | `NewGcvSize2f64(x, y float64)` | +| `cv::Size2d` | `GcvSize2f64_` | `NewGcvSize2f64(x, y float64)` | ---------- ### Note for Renamed Types Some of the types are renamed to `*_`. The reason is that we'd like to wrap a better interface for them. -For example, the original `NewPoint2f` takes strictly two `float32`, and we are not able to pass `float64` or `int`, which doesn't make too much sense. +For example, the original `NewGcvPoint2f32` takes strictly two `float32`, and we are not able to pass `float64` or `int`, which doesn't make too much sense. After wrapping an extra level, we are now able to pass `int`, `float32`, and `float64` to these methods. Also note that **renaming doesn't affect any usage**, except you are manipulating the types yourself. diff --git a/gocv/gocv.go b/gocv/gocv.go index bfb12f9..82196d6 100644 --- a/gocv/gocv.go +++ b/gocv/gocv.go @@ -5,28 +5,28 @@ package gocv import "C" import "github.com/gonum/matrix/mat64" -func NewGcvPoint3f(x, y, z float64) GcvPoint3f_ { - return NewGcvPoint3f_(float32(x), float32(y), float32(z)) +func NewGcvPoint3f32(x, y, z float64) GcvPoint3f32_ { + return NewGcvPoint3f32_(float32(x), float32(y), float32(z)) } -func NewGcvPoint3d(x, y, z float64) GcvPoint3d_ { - return NewGcvPoint3d_(float64(x), float64(y), float64(z)) +func NewGcvPoint3f64(x, y, z float64) GcvPoint3f64_ { + return NewGcvPoint3f64_(float64(x), float64(y), float64(z)) } -func NewGcvPoint2f(x, y float64) GcvPoint2f_ { - return NewGcvPoint2f_(float32(x), float32(y)) +func NewGcvPoint2f32(x, y float64) GcvPoint2f32_ { + return NewGcvPoint2f32_(float32(x), float32(y)) } -func NewGcvPoint2d(x, y float64) GcvPoint2d_ { - return NewGcvPoint2d_(float64(x), float64(y)) +func NewGcvPoint2f64(x, y float64) GcvPoint2f64_ { + return NewGcvPoint2f64_(float64(x), float64(y)) } -func NewGcvSize2f(x, y float64) GcvSize2f_ { - return NewGcvSize2f_(float32(x), float32(y)) +func NewGcvSize2f32(x, y float64) GcvSize2f32_ { + return NewGcvSize2f32_(float32(x), float32(y)) } -func NewGcvSize2d(x, y float64) GcvSize2d_ { - return NewGcvSize2d_(float64(x), float64(y)) +func NewGcvSize2f64(x, y float64) GcvSize2f64_ { + return NewGcvSize2f64_(float64(x), float64(y)) } // Convert Mat, which defined by SWIG, to mat64.Dense. @@ -41,7 +41,7 @@ func MatToMat64(mat Mat) *mat64.Dense { for i := 0; i < row; i++ { for j := 0; j < col; j++ { - if fltPtr, ok := mat.GcvAtd(i, j).(*float64); ok { + if fltPtr, ok := mat.GcvAtf64(i, j).(*float64); ok { data = append(data, *fltPtr) } else { panic("Non *float64 passed to MatToMat64") diff --git a/gocv/gocv_calib3d.go b/gocv/gocv_calib3d.go index 624b79a..a49ca0e 100644 --- a/gocv/gocv_calib3d.go +++ b/gocv/gocv_calib3d.go @@ -18,16 +18,16 @@ func GcvInitCameraMatrix2D(objPts, imgPts *mat64.Dense) (camMat *mat64.Dense) { panic("Invalid dimensions for objPts and imgPts") } - objPtsVec := NewGcvPoint3fVector(int64(nObjPts)) - imgPtsVec := NewGcvPoint2fVector(int64(nObjPts)) + objPtsVec := NewGcvPoint3f32Vector(int64(nObjPts)) + imgPtsVec := NewGcvPoint2f32Vector(int64(nObjPts)) for i := 0; i < nObjPts; i++ { - objPtsVec.Set(i, NewGcvPoint3f( + objPtsVec.Set(i, NewGcvPoint3f32( objPts.At(i, 0), objPts.At(i, 1), objPts.At(i, 2))) } for i := 0; i < nObjPts; i++ { - imgPtsVec.Set(i, NewGcvPoint2f( + imgPtsVec.Set(i, NewGcvPoint2f32( imgPts.At(i, 0), imgPts.At(i, 1))) } diff --git a/gocv/gocv_core.i b/gocv/gocv_core.i index ee63dc6..f14232c 100644 --- a/gocv/gocv_core.i +++ b/gocv/gocv_core.i @@ -175,18 +175,18 @@ namespace cv { %template(GcvSize2i) Size_; - %template(GcvSize2d_) Size_; - %template(GcvSize2f_) Size_; + %template(GcvSize2f32_) Size_; + %template(GcvSize2f64_) Size_; %template(GcvRect) Rect_; %template(GcvPoint2i) Point_; - %template(GcvPoint2f_) Point_; - %template(GcvPoint2d_) Point_; + %template(GcvPoint2f32_) Point_; + %template(GcvPoint2f64_) Point_; %template(GcvPoint3i) Point3_; - %template(GcvPoint3f_) Point3_; - %template(GcvPoint3d_) Point3_; + %template(GcvPoint3f32_) Point3_; + %template(GcvPoint3f64_) Point3_; /* ----------------- Mat ----------------- */ @@ -272,8 +272,8 @@ namespace cv { template _Tp& at(cv::Point pt); template const _Tp& at(cv::Point pt) const; - %template(gcvAtf) at; - %template(gcvAtd) at; + %template(gcvAtf32) at; + %template(gcvAtf64) at; /*! includes several bit-fields: - the magic signature @@ -291,8 +291,8 @@ namespace cv { /* Additional STL types */ namespace std { - %template(GcvPoint3fVector) vector; - %template(GcvPoint2fVector) vector; + %template(GcvPoint3f32Vector) vector; + %template(GcvPoint2f32Vector) vector; %template(GcvIntVector) vector; %template(GcvFloatVector) vector; diff --git a/gocv/gocv_test.go b/gocv/gocv_test.go index bd0d775..dae57c7 100644 --- a/gocv/gocv_test.go +++ b/gocv/gocv_test.go @@ -7,18 +7,18 @@ import ( "github.com/gonum/matrix/mat64" ) -func TestNewGcvPoint3f(t *testing.T) { - pt := NewGcvPoint3f(3, 1, 2) +func TestNewGcvPoint3f32(t *testing.T) { + pt := NewGcvPoint3f32(3, 1, 2) spew.Dump(pt) } -func TestNewGcvPoint2f(t *testing.T) { - pt := NewGcvPoint2f(3, 1) +func TestNewGcvPoint2f32(t *testing.T) { + pt := NewGcvPoint2f32(3, 1) spew.Dump(pt) } -func TestNewGcvSize2d(t *testing.T) { - size := NewGcvSize2d(3, 1) +func TestNewGcvSize2f64(t *testing.T) { + size := NewGcvSize2f64(3, 1) spew.Dump(size) } From 15a14724257e724611ed1a64937373cccb5646d0 Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Mon, 16 Feb 2015 17:07:14 +0800 Subject: [PATCH 04/10] Update REAME, split tests. --- README.md | 27 ++++++++++--------- gocv/gocv_calib3d_test.go | 55 +++++++++++++++++++++++++++++++++++++++ gocv/gocv_test.go | 48 ---------------------------------- 3 files changed, 70 insertions(+), 60 deletions(-) create mode 100644 gocv/gocv_calib3d_test.go diff --git a/README.md b/README.md index cec9831..3690c01 100644 --- a/README.md +++ b/README.md @@ -49,22 +49,25 @@ Please also note that the basic data structures in OpenCV (e.g., `cv::Mat`, `cv: ```go package main -import "github.com/lazywei/go-opencv/gocv" +import . "github.com/lazywei/go-opencv/gocv" +import "github.com/gonum/matrix/mat64" func main() { - objPts := gocv.NewGcvPoint3fVector(int64(4)) - objPts.Set(0, gocv.NewGcvPoint3f(0, 25, 0)) - objPts.Set(1, gocv.NewGcvPoint3f(0, -25, 0)) - objPts.Set(2, gocv.NewGcvPoint3f(-47, 25, 0)) - objPts.Set(3, gocv.NewGcvPoint3f(-47, -25, 0)) - imgPts := gocv.NewGcvPoint2fVector(int64(4)) - imgPts.Set(0, gocv.NewGcvPoint2f(1136.4140625, 1041.89208984)) - imgPts.Set(1, gocv.NewGcvPoint2f(1845.33190918, 671.39581299)) - imgPts.Set(2, gocv.NewGcvPoint2f(302.73373413, 634.79998779)) - imgPts.Set(3, gocv.NewGcvPoint2f(1051.46154785, 352.76107788)) + objPts := mat64.NewDense(4, 3, []float64{ + 0, 25, 0, + 0, -25, 0, + -47, 25, 0, + -47, -25, 0}) - gocv.GcvInitCameraMatrix2D(objPts, imgPts) + imgPts := mat64.NewDense(4, 2, []float64{ + 1136.4140625, 1041.89208984, + 1845.33190918, 671.39581299, + 302.73373413, 634.79998779, + 1051.46154785, 352.76107788}) + + camMat := GcvInitCameraMatrix2D(objPts, imgPts) + fmt.Println(camMat) } ``` diff --git a/gocv/gocv_calib3d_test.go b/gocv/gocv_calib3d_test.go new file mode 100644 index 0000000..72115ef --- /dev/null +++ b/gocv/gocv_calib3d_test.go @@ -0,0 +1,55 @@ +package gocv + +import ( + "testing" + + "github.com/davecgh/go-spew/spew" + "github.com/gonum/matrix/mat64" +) + +func TestGcvInitCameraMatrix2D(t *testing.T) { + objPts := mat64.NewDense(4, 3, []float64{ + 0, 25, 0, + 0, -25, 0, + -47, 25, 0, + -47, -25, 0}) + + imgPts := mat64.NewDense(4, 2, []float64{ + 1136.4140625, 1041.89208984, + 1845.33190918, 671.39581299, + 302.73373413, 634.79998779, + 1051.46154785, 352.76107788}) + + camMat := GcvInitCameraMatrix2D(objPts, imgPts) + spew.Dump(camMat) +} + +// func TestGcvCalibrateCamera(t *testing.T) { +// objPts := NewGcvPoint3fVector(int64(4)) +// objPts.Set(0, NewGcvPoint3f(0, 25, 0)) +// objPts.Set(1, NewGcvPoint3f(0, -25, 0)) +// objPts.Set(2, NewGcvPoint3f(-47, 25, 0)) +// objPts.Set(3, NewGcvPoint3f(-47, -25, 0)) + +// imgPts := NewGcvPoint2fVector(int64(4)) +// imgPts.Set(0, NewGcvPoint2f(1136.4140625, 1041.89208984)) +// imgPts.Set(1, NewGcvPoint2f(1845.33190918, 671.39581299)) +// imgPts.Set(2, NewGcvPoint2f(302.73373413, 634.79998779)) +// imgPts.Set(3, NewGcvPoint2f(1051.46154785, 352.76107788)) + +// imgSize := NewGcvSize2i(1920, 1080) + +// camMat := GcvInitCameraMatrix2D(objPts, imgPts) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) +// spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) + +// rvec := NewMat() +// tvec := NewMat() + +// GcvCalibrateCamera(objPts, imgPts, imgSize, camMat, rvec, tvec) + +// MatToMat64(camMat) +// } diff --git a/gocv/gocv_test.go b/gocv/gocv_test.go index dae57c7..228cba8 100644 --- a/gocv/gocv_test.go +++ b/gocv/gocv_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/davecgh/go-spew/spew" - "github.com/gonum/matrix/mat64" ) func TestNewGcvPoint3f32(t *testing.T) { @@ -27,50 +26,3 @@ func TestMat(t *testing.T) { mat2 := NewMat(mat) spew.Dump(mat2) } - -func TestGcvInitCameraMatrix2D(t *testing.T) { - objPts := mat64.NewDense(4, 3, []float64{ - 0, 25, 0, - 0, -25, 0, - -47, 25, 0, - -47, -25, 0}) - - imgPts := mat64.NewDense(4, 2, []float64{ - 1136.4140625, 1041.89208984, - 1845.33190918, 671.39581299, - 302.73373413, 634.79998779, - 1051.46154785, 352.76107788}) - - camMat := GcvInitCameraMatrix2D(objPts, imgPts) - spew.Dump(camMat) -} - -// func TestGcvCalibrateCamera(t *testing.T) { -// objPts := NewGcvPoint3fVector(int64(4)) -// objPts.Set(0, NewGcvPoint3f(0, 25, 0)) -// objPts.Set(1, NewGcvPoint3f(0, -25, 0)) -// objPts.Set(2, NewGcvPoint3f(-47, 25, 0)) -// objPts.Set(3, NewGcvPoint3f(-47, -25, 0)) - -// imgPts := NewGcvPoint2fVector(int64(4)) -// imgPts.Set(0, NewGcvPoint2f(1136.4140625, 1041.89208984)) -// imgPts.Set(1, NewGcvPoint2f(1845.33190918, 671.39581299)) -// imgPts.Set(2, NewGcvPoint2f(302.73373413, 634.79998779)) -// imgPts.Set(3, NewGcvPoint2f(1051.46154785, 352.76107788)) - -// imgSize := NewGcvSize2i(1920, 1080) - -// camMat := GcvInitCameraMatrix2D(objPts, imgPts) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) - -// rvec := NewMat() -// tvec := NewMat() - -// GcvCalibrateCamera(objPts, imgPts, imgSize, camMat, rvec, tvec) - -// MatToMat64(camMat) -// } From bdc350f8506b16540a1df390d5329c7625759ad5 Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Mon, 16 Feb 2015 17:10:14 +0800 Subject: [PATCH 05/10] Add README for mat64. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3690c01..c3ac448 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,8 @@ If you want to use CV2's API, please refer to the code under `gocv/` directory. Please also note that the basic data structures in OpenCV (e.g., `cv::Mat`, `cv::Point3f`) are wrapped partially for now. For more detail on how to use these types, please refer to [GoCV's README](gocv/README.md). +*Requirement*: we will build the wrappers based on [mat64](https://godoc.org/github.com/gonum/matrix/mat64), given it is much easier to manipulate the underlaying data. In most case, it is not necessary to access the original CV data, e.g., `cv::Mat` can be converted from/to `*mat64.Dense`. + ## Example ### OpenCV2's initCameraMatrix2D From 27818da2494511435d5f99be343ec280be8cd256 Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Tue, 17 Feb 2015 00:14:10 +0800 Subject: [PATCH 06/10] Add *mat64.Dense to cv::Mat converter. --- gocv/gocv.go | 17 ++++++++++++++++- gocv/gocv_core.cpp | 21 +++++++++++++++++++++ gocv/gocv_core.hpp | 5 +++++ gocv/gocv_core.i | 9 ++++++--- gocv/gocv_test.go | 10 ++++++++++ 5 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 gocv/gocv_core.cpp create mode 100644 gocv/gocv_core.hpp diff --git a/gocv/gocv.go b/gocv/gocv.go index 82196d6..05ab78c 100644 --- a/gocv/gocv.go +++ b/gocv/gocv.go @@ -29,7 +29,7 @@ func NewGcvSize2f64(x, y float64) GcvSize2f64_ { return NewGcvSize2f64_(float64(x), float64(y)) } -// Convert Mat, which defined by SWIG, to mat64.Dense. +// Convert Mat, which defined by SWIG, to *mat64.Dense. // The reason is the latter is much easier to handle // in Go. // GcvMat is assumed to be 2-dimensional matrix. @@ -52,3 +52,18 @@ func MatToMat64(mat Mat) *mat64.Dense { return mat64.NewDense(row, col, data) } + +// Convert *mat64.Dense to Mat +func ToMat(mat *mat64.Dense) Mat { + row, col := mat.Dims() + + rawData := NewGcvFloat64Vector(int64(row * col)) + + for i := 0; i < row; i++ { + for j := 0; j < col; j++ { + rawData.Set(i*col+j, mat.At(i, j)) + } + } + + return ToMat_(row, col, rawData) +} diff --git a/gocv/gocv_core.cpp b/gocv/gocv_core.cpp new file mode 100644 index 0000000..d5b4256 --- /dev/null +++ b/gocv/gocv_core.cpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +#include "gocv_core.hpp" + +cv::Mat ToMat_(int row, int col, std::vector data) { + assert(row * col == data.size()); + + cv::Mat mat = cv::Mat(row, col, CV_64F); + + for (int i = 0; i < row; ++i) { + for (int j = 0; j < col; ++j) { + mat.at(i, j) = data[i*col + j]; + } + + } + + return mat; +} diff --git a/gocv/gocv_core.hpp b/gocv/gocv_core.hpp new file mode 100644 index 0000000..9210e09 --- /dev/null +++ b/gocv/gocv_core.hpp @@ -0,0 +1,5 @@ +#include +#include +#include + +cv::Mat ToMat_(int row, int col, std::vector data); diff --git a/gocv/gocv_core.i b/gocv/gocv_core.i index f14232c..47e782e 100644 --- a/gocv/gocv_core.i +++ b/gocv/gocv_core.i @@ -1,9 +1,11 @@ -%include "std_vector.i" - %{ #include "opencv2/core/core.hpp" +#include "gocv_core.hpp" %} +%include "std_vector.i" +%include "gocv_core.hpp" + /* Classes defined in core.hpp */ namespace cv { @@ -295,5 +297,6 @@ namespace std { %template(GcvPoint2f32Vector) vector; %template(GcvIntVector) vector; - %template(GcvFloatVector) vector; + %template(GcvFloat32Vector) vector; + %template(GcvFloat64Vector) vector; }; diff --git a/gocv/gocv_test.go b/gocv/gocv_test.go index 228cba8..4c082fb 100644 --- a/gocv/gocv_test.go +++ b/gocv/gocv_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/davecgh/go-spew/spew" + "github.com/gonum/matrix/mat64" ) func TestNewGcvPoint3f32(t *testing.T) { @@ -26,3 +27,12 @@ func TestMat(t *testing.T) { mat2 := NewMat(mat) spew.Dump(mat2) } + +func TestToMat(t *testing.T) { + mat := mat64.NewDense(3, 2, []float64{ + 0, 1, + 1.23, 4, + -12.3, -4, + }) + spew.Dump(ToMat(mat)) +} From af3c33e58e961ea006841c2ae83d3d1594a49b7f Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Tue, 17 Feb 2015 00:33:46 +0800 Subject: [PATCH 07/10] Cleanup swig files. --- gocv/gocv.go | 64 ---------------------- gocv/gocv.swigcxx | 6 +-- gocv/gocv_calib3d.i | 5 ++ gocv/gocv_core.go | 69 ++++++++++++++++++++++++ gocv/{gocv_test.go => gocv_core_test.go} | 0 5 files changed, 75 insertions(+), 69 deletions(-) create mode 100644 gocv/gocv_calib3d.i create mode 100644 gocv/gocv_core.go rename gocv/{gocv_test.go => gocv_core_test.go} (100%) diff --git a/gocv/gocv.go b/gocv/gocv.go index 05ab78c..772b236 100644 --- a/gocv/gocv.go +++ b/gocv/gocv.go @@ -3,67 +3,3 @@ package gocv // #cgo CXXFLAGS: -std=c++11 // #cgo darwin pkg-config: opencv import "C" -import "github.com/gonum/matrix/mat64" - -func NewGcvPoint3f32(x, y, z float64) GcvPoint3f32_ { - return NewGcvPoint3f32_(float32(x), float32(y), float32(z)) -} - -func NewGcvPoint3f64(x, y, z float64) GcvPoint3f64_ { - return NewGcvPoint3f64_(float64(x), float64(y), float64(z)) -} - -func NewGcvPoint2f32(x, y float64) GcvPoint2f32_ { - return NewGcvPoint2f32_(float32(x), float32(y)) -} - -func NewGcvPoint2f64(x, y float64) GcvPoint2f64_ { - return NewGcvPoint2f64_(float64(x), float64(y)) -} - -func NewGcvSize2f32(x, y float64) GcvSize2f32_ { - return NewGcvSize2f32_(float32(x), float32(y)) -} - -func NewGcvSize2f64(x, y float64) GcvSize2f64_ { - return NewGcvSize2f64_(float64(x), float64(y)) -} - -// Convert Mat, which defined by SWIG, to *mat64.Dense. -// The reason is the latter is much easier to handle -// in Go. -// GcvMat is assumed to be 2-dimensional matrix. -func MatToMat64(mat Mat) *mat64.Dense { - col := mat.GetCols() - row := mat.GetRows() - - data := []float64{} - - for i := 0; i < row; i++ { - for j := 0; j < col; j++ { - if fltPtr, ok := mat.GcvAtf64(i, j).(*float64); ok { - data = append(data, *fltPtr) - } else { - panic("Non *float64 passed to MatToMat64") - } - - } - } - - return mat64.NewDense(row, col, data) -} - -// Convert *mat64.Dense to Mat -func ToMat(mat *mat64.Dense) Mat { - row, col := mat.Dims() - - rawData := NewGcvFloat64Vector(int64(row * col)) - - for i := 0; i < row; i++ { - for j := 0; j < col; j++ { - rawData.Set(i*col+j, mat.At(i, j)) - } - } - - return ToMat_(row, col, rawData) -} diff --git a/gocv/gocv.swigcxx b/gocv/gocv.swigcxx index b56bc86..4b5151f 100644 --- a/gocv/gocv.swigcxx +++ b/gocv/gocv.swigcxx @@ -1,8 +1,4 @@ %module gocv -%{ -#include "gocv_calib3d.hpp" -%} - %include "gocv_core.i" -%include "gocv_calib3d.hpp" +%include "gocv_calib3d.i" diff --git a/gocv/gocv_calib3d.i b/gocv/gocv_calib3d.i new file mode 100644 index 0000000..9ca1bc3 --- /dev/null +++ b/gocv/gocv_calib3d.i @@ -0,0 +1,5 @@ +%{ +#include "gocv_calib3d.hpp" +%} + +%include "gocv_calib3d.hpp" diff --git a/gocv/gocv_core.go b/gocv/gocv_core.go new file mode 100644 index 0000000..05ab78c --- /dev/null +++ b/gocv/gocv_core.go @@ -0,0 +1,69 @@ +package gocv + +// #cgo CXXFLAGS: -std=c++11 +// #cgo darwin pkg-config: opencv +import "C" +import "github.com/gonum/matrix/mat64" + +func NewGcvPoint3f32(x, y, z float64) GcvPoint3f32_ { + return NewGcvPoint3f32_(float32(x), float32(y), float32(z)) +} + +func NewGcvPoint3f64(x, y, z float64) GcvPoint3f64_ { + return NewGcvPoint3f64_(float64(x), float64(y), float64(z)) +} + +func NewGcvPoint2f32(x, y float64) GcvPoint2f32_ { + return NewGcvPoint2f32_(float32(x), float32(y)) +} + +func NewGcvPoint2f64(x, y float64) GcvPoint2f64_ { + return NewGcvPoint2f64_(float64(x), float64(y)) +} + +func NewGcvSize2f32(x, y float64) GcvSize2f32_ { + return NewGcvSize2f32_(float32(x), float32(y)) +} + +func NewGcvSize2f64(x, y float64) GcvSize2f64_ { + return NewGcvSize2f64_(float64(x), float64(y)) +} + +// Convert Mat, which defined by SWIG, to *mat64.Dense. +// The reason is the latter is much easier to handle +// in Go. +// GcvMat is assumed to be 2-dimensional matrix. +func MatToMat64(mat Mat) *mat64.Dense { + col := mat.GetCols() + row := mat.GetRows() + + data := []float64{} + + for i := 0; i < row; i++ { + for j := 0; j < col; j++ { + if fltPtr, ok := mat.GcvAtf64(i, j).(*float64); ok { + data = append(data, *fltPtr) + } else { + panic("Non *float64 passed to MatToMat64") + } + + } + } + + return mat64.NewDense(row, col, data) +} + +// Convert *mat64.Dense to Mat +func ToMat(mat *mat64.Dense) Mat { + row, col := mat.Dims() + + rawData := NewGcvFloat64Vector(int64(row * col)) + + for i := 0; i < row; i++ { + for j := 0; j < col; j++ { + rawData.Set(i*col+j, mat.At(i, j)) + } + } + + return ToMat_(row, col, rawData) +} diff --git a/gocv/gocv_test.go b/gocv/gocv_core_test.go similarity index 100% rename from gocv/gocv_test.go rename to gocv/gocv_core_test.go From f3ef2ccd9b48baf58fa80c29c76c98237a645e4f Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Tue, 17 Feb 2015 00:44:28 +0800 Subject: [PATCH 08/10] Rename Mat to GcvMat --- gocv/gocv_calib3d.go | 2 +- gocv/gocv_core.cpp | 2 +- gocv/gocv_core.go | 6 +++--- gocv/gocv_core.hpp | 2 +- gocv/gocv_core.i | 2 ++ gocv/gocv_core_test.go | 8 ++++---- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/gocv/gocv_calib3d.go b/gocv/gocv_calib3d.go index a49ca0e..2ced4e3 100644 --- a/gocv/gocv_calib3d.go +++ b/gocv/gocv_calib3d.go @@ -31,7 +31,7 @@ func GcvInitCameraMatrix2D(objPts, imgPts *mat64.Dense) (camMat *mat64.Dense) { imgPts.At(i, 0), imgPts.At(i, 1))) } - camMat = MatToMat64(GcvInitCameraMatrix2D_(objPtsVec, imgPtsVec)) + camMat = GcvMatToMat64(GcvInitCameraMatrix2D_(objPtsVec, imgPtsVec)) return camMat } diff --git a/gocv/gocv_core.cpp b/gocv/gocv_core.cpp index d5b4256..d448255 100644 --- a/gocv/gocv_core.cpp +++ b/gocv/gocv_core.cpp @@ -5,7 +5,7 @@ #include "gocv_core.hpp" -cv::Mat ToMat_(int row, int col, std::vector data) { +cv::Mat Mat64ToGcvMat_(int row, int col, std::vector data) { assert(row * col == data.size()); cv::Mat mat = cv::Mat(row, col, CV_64F); diff --git a/gocv/gocv_core.go b/gocv/gocv_core.go index 05ab78c..279c7f2 100644 --- a/gocv/gocv_core.go +++ b/gocv/gocv_core.go @@ -33,7 +33,7 @@ func NewGcvSize2f64(x, y float64) GcvSize2f64_ { // The reason is the latter is much easier to handle // in Go. // GcvMat is assumed to be 2-dimensional matrix. -func MatToMat64(mat Mat) *mat64.Dense { +func GcvMatToMat64(mat GcvMat) *mat64.Dense { col := mat.GetCols() row := mat.GetRows() @@ -54,7 +54,7 @@ func MatToMat64(mat Mat) *mat64.Dense { } // Convert *mat64.Dense to Mat -func ToMat(mat *mat64.Dense) Mat { +func Mat64ToGcvMat(mat *mat64.Dense) GcvMat { row, col := mat.Dims() rawData := NewGcvFloat64Vector(int64(row * col)) @@ -65,5 +65,5 @@ func ToMat(mat *mat64.Dense) Mat { } } - return ToMat_(row, col, rawData) + return Mat64ToGcvMat_(row, col, rawData) } diff --git a/gocv/gocv_core.hpp b/gocv/gocv_core.hpp index 9210e09..90074d5 100644 --- a/gocv/gocv_core.hpp +++ b/gocv/gocv_core.hpp @@ -2,4 +2,4 @@ #include #include -cv::Mat ToMat_(int row, int col, std::vector data); +cv::Mat Mat64ToGcvMat_(int row, int col, std::vector data); diff --git a/gocv/gocv_core.i b/gocv/gocv_core.i index 47e782e..9f9ed69 100644 --- a/gocv/gocv_core.i +++ b/gocv/gocv_core.i @@ -192,6 +192,8 @@ namespace cv { /* ----------------- Mat ----------------- */ + %rename(GcvMat) Mat; + class Mat { public: diff --git a/gocv/gocv_core_test.go b/gocv/gocv_core_test.go index 4c082fb..c327e3b 100644 --- a/gocv/gocv_core_test.go +++ b/gocv/gocv_core_test.go @@ -23,16 +23,16 @@ func TestNewGcvSize2f64(t *testing.T) { } func TestMat(t *testing.T) { - mat := NewMat() - mat2 := NewMat(mat) + mat := NewGcvMat() + mat2 := NewGcvMat(mat) spew.Dump(mat2) } -func TestToMat(t *testing.T) { +func TestMat64ToGcvMat(t *testing.T) { mat := mat64.NewDense(3, 2, []float64{ 0, 1, 1.23, 4, -12.3, -4, }) - spew.Dump(ToMat(mat)) + spew.Dump(Mat64ToGcvMat(mat)) } From 51f567bae26327220691c5d8095095f879ae8dd0 Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Tue, 17 Feb 2015 01:27:27 +0800 Subject: [PATCH 09/10] Wrap CalibrateCamera with mat64 --- gocv/gocv_calib3d.go | 45 +++++++++++++++++++++++++++++++++++---- gocv/gocv_calib3d_test.go | 43 +++++++++++++++---------------------- gocv/gocv_core.go | 39 ++++++++++++++++++++++----------- gocv/gocv_core_test.go | 2 +- 4 files changed, 86 insertions(+), 43 deletions(-) diff --git a/gocv/gocv_calib3d.go b/gocv/gocv_calib3d.go index 2ced4e3..b16b406 100644 --- a/gocv/gocv_calib3d.go +++ b/gocv/gocv_calib3d.go @@ -22,19 +22,56 @@ func GcvInitCameraMatrix2D(objPts, imgPts *mat64.Dense) (camMat *mat64.Dense) { imgPtsVec := NewGcvPoint2f32Vector(int64(nObjPts)) for i := 0; i < nObjPts; i++ { - objPtsVec.Set(i, NewGcvPoint3f32( - objPts.At(i, 0), objPts.At(i, 1), objPts.At(i, 2))) + objPtsVec.Set(i, NewGcvPoint3f32(objPts.Row(nil, i)...)) } for i := 0; i < nObjPts; i++ { - imgPtsVec.Set(i, NewGcvPoint2f32( - imgPts.At(i, 0), imgPts.At(i, 1))) + imgPtsVec.Set(i, NewGcvPoint2f32(imgPts.Row(nil, i)...)) } camMat = GcvMatToMat64(GcvInitCameraMatrix2D_(objPtsVec, imgPtsVec)) return camMat } +func GcvCalibrateCamera(objPts, imgPts, camMat *mat64.Dense) (calCamMat, rvec, tvec *mat64.Dense) { + nObjPts, objCol := objPts.Dims() + nImgPts, imgCol := imgPts.Dims() + + if objCol != 3 || imgCol != 2 || nObjPts != nImgPts { + panic("Invalid dimensions for objPts and imgPts") + } + + objPtsVec := NewGcvPoint3f32Vector(int64(nObjPts)) + imgPtsVec := NewGcvPoint2f32Vector(int64(nObjPts)) + + for i := 0; i < nObjPts; i++ { + objPtsVec.Set(i, NewGcvPoint3f32(objPts.Row(nil, i)...)) + } + + for i := 0; i < nObjPts; i++ { + imgPtsVec.Set(i, NewGcvPoint2f32(imgPts.Row(nil, i)...)) + } + + _camMat := Mat64ToGcvMat(camMat) + _rvec := NewGcvMat() + _tvec := NewGcvMat() + _imgSize := NewGcvSize2i(1920, 1080) + + GcvCalibrateCamera_( + objPtsVec, imgPtsVec, + _imgSize, _camMat, _rvec, _tvec) + + calCamMat = GcvMatToMat64(_camMat) + rvec = GcvMatToMat64(_rvec) + tvec = GcvMatToMat64(_tvec) + + return camMat, rvec, tvec +} + +// func mat64ToGcvPoint3f32Vector(mat *mat64.Dense) NewGcvPoint3f32Vector { + +// } + // func TestGcvCalibrateCamera(t *testing.T) { // objPts := NewGcvPoint3fVector(int64(4)) // objPts.Set(0, NewGcvPoint3f(0, 25, 0)) diff --git a/gocv/gocv_calib3d_test.go b/gocv/gocv_calib3d_test.go index 72115ef..ed8d65a 100644 --- a/gocv/gocv_calib3d_test.go +++ b/gocv/gocv_calib3d_test.go @@ -24,32 +24,23 @@ func TestGcvInitCameraMatrix2D(t *testing.T) { spew.Dump(camMat) } -// func TestGcvCalibrateCamera(t *testing.T) { -// objPts := NewGcvPoint3fVector(int64(4)) -// objPts.Set(0, NewGcvPoint3f(0, 25, 0)) -// objPts.Set(1, NewGcvPoint3f(0, -25, 0)) -// objPts.Set(2, NewGcvPoint3f(-47, 25, 0)) -// objPts.Set(3, NewGcvPoint3f(-47, -25, 0)) +func TestGcvCalibrateCamera(t *testing.T) { + objPts := mat64.NewDense(4, 3, []float64{ + 0, 25, 0, + 0, -25, 0, + -47, 25, 0, + -47, -25, 0}) -// imgPts := NewGcvPoint2fVector(int64(4)) -// imgPts.Set(0, NewGcvPoint2f(1136.4140625, 1041.89208984)) -// imgPts.Set(1, NewGcvPoint2f(1845.33190918, 671.39581299)) -// imgPts.Set(2, NewGcvPoint2f(302.73373413, 634.79998779)) -// imgPts.Set(3, NewGcvPoint2f(1051.46154785, 352.76107788)) + imgPts := mat64.NewDense(4, 2, []float64{ + 1136.4140625, 1041.89208984, + 1845.33190918, 671.39581299, + 302.73373413, 634.79998779, + 1051.46154785, 352.76107788}) -// imgSize := NewGcvSize2i(1920, 1080) + camMat := GcvInitCameraMatrix2D(objPts, imgPts) -// camMat := GcvInitCameraMatrix2D(objPts, imgPts) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 0))) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(0, 1))) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 1))) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(1, 2))) -// spew.Dump(camMat.GcvAtd(NewGcvSize2i(2, 2))) - -// rvec := NewMat() -// tvec := NewMat() - -// GcvCalibrateCamera(objPts, imgPts, imgSize, camMat, rvec, tvec) - -// MatToMat64(camMat) -// } + camMat, rvec, tvec := GcvCalibrateCamera(objPts, imgPts, camMat) + spew.Dump(camMat) + spew.Dump(rvec) + spew.Dump(tvec) +} diff --git a/gocv/gocv_core.go b/gocv/gocv_core.go index 279c7f2..49b2072 100644 --- a/gocv/gocv_core.go +++ b/gocv/gocv_core.go @@ -5,28 +5,35 @@ package gocv import "C" import "github.com/gonum/matrix/mat64" -func NewGcvPoint3f32(x, y, z float64) GcvPoint3f32_ { - return NewGcvPoint3f32_(float32(x), float32(y), float32(z)) +func NewGcvPoint3f32(pts ...float64) GcvPoint3f32_ { + // This make sure we have default values + safePts := getSafePts(pts, 3) + return NewGcvPoint3f32_(float32(safePts[0]), float32(safePts[1]), float32(safePts[2])) } -func NewGcvPoint3f64(x, y, z float64) GcvPoint3f64_ { - return NewGcvPoint3f64_(float64(x), float64(y), float64(z)) +func NewGcvPoint3f64(pts ...float64) GcvPoint3f64_ { + safePts := getSafePts(pts, 3) + return NewGcvPoint3f64_(safePts[0], safePts[1], safePts[2]) } -func NewGcvPoint2f32(x, y float64) GcvPoint2f32_ { - return NewGcvPoint2f32_(float32(x), float32(y)) +func NewGcvPoint2f32(pts ...float64) GcvPoint2f32_ { + safePts := getSafePts(pts, 2) + return NewGcvPoint2f32_(float32(safePts[0]), float32(safePts[1])) } -func NewGcvPoint2f64(x, y float64) GcvPoint2f64_ { - return NewGcvPoint2f64_(float64(x), float64(y)) +func NewGcvPoint2f64(pts ...float64) GcvPoint2f64_ { + safePts := getSafePts(pts, 2) + return NewGcvPoint2f64_(safePts[0], safePts[1]) } -func NewGcvSize2f32(x, y float64) GcvSize2f32_ { - return NewGcvSize2f32_(float32(x), float32(y)) +func NewGcvSize2f32(pts ...float64) GcvSize2f32_ { + safePts := getSafePts(pts, 2) + return NewGcvSize2f32_(float32(safePts[0]), float32(safePts[1])) } -func NewGcvSize2f64(x, y float64) GcvSize2f64_ { - return NewGcvSize2f64_(float64(x), float64(y)) +func NewGcvSize2f64(pts ...float64) GcvSize2f64_ { + safePts := getSafePts(pts, 2) + return NewGcvSize2f64_(safePts[0], safePts[1]) } // Convert Mat, which defined by SWIG, to *mat64.Dense. @@ -67,3 +74,11 @@ func Mat64ToGcvMat(mat *mat64.Dense) GcvMat { return Mat64ToGcvMat_(row, col, rawData) } + +func getSafePts(pts []float64, size int) []float64 { + // This make sure we have default values + safePts := make([]float64, size, size) + copy(safePts, pts) + + return safePts +} diff --git a/gocv/gocv_core_test.go b/gocv/gocv_core_test.go index c327e3b..2b0be85 100644 --- a/gocv/gocv_core_test.go +++ b/gocv/gocv_core_test.go @@ -8,7 +8,7 @@ import ( ) func TestNewGcvPoint3f32(t *testing.T) { - pt := NewGcvPoint3f32(3, 1, 2) + pt := NewGcvPoint3f32(3, 1) spew.Dump(pt) } From dcfe2940dfb2db11f64877fd0df1bc28a45d86dd Mon Sep 17 00:00:00 2001 From: Chih-Wei Chang Date: Tue, 17 Feb 2015 12:41:39 +0800 Subject: [PATCH 10/10] Use testify to make real assertions. --- gocv/gocv_calib3d.cpp | 17 +++++++++++++- gocv/gocv_calib3d.go | 12 +++++++++- gocv/gocv_calib3d.hpp | 2 ++ gocv/gocv_calib3d_test.go | 49 ++++++++++++++++++++++++++++++++------- 4 files changed, 69 insertions(+), 11 deletions(-) diff --git a/gocv/gocv_calib3d.cpp b/gocv/gocv_calib3d.cpp index b636cef..88ed529 100644 --- a/gocv/gocv_calib3d.cpp +++ b/gocv/gocv_calib3d.cpp @@ -30,12 +30,27 @@ double GcvCalibrateCamera_(VecPoint3f objPts, VecPoint2f imgPts, objPtsArr.push_back(objPts); imgPtsArr.push_back(imgPts); + std::cout << "objPts " << std::endl << objPtsArr[0] << std::endl; + std::cout << "imgPts " << std::endl << imgPtsArr[0] << std::endl; + std::cout << "imgSize " << std::endl << imgSize << std::endl; + std::cout << "Before CamMat " << std::endl << cameraMatrix << std::endl; + rtn = cv::calibrateCamera(objPtsArr, imgPtsArr, imgSize, cameraMatrix, distCoeffs, - rvecs, tvecs); + rvecs, tvecs, 14575); rvec = rvecs[0]; tvec = tvecs[0]; + std::cout << "After CamMat " << std::endl << cameraMatrix << std::endl; + std::cout << "distCoeffs " << std::endl << distCoeffs << std::endl; + std::cout << "rvec " << std::endl << rvec << std::endl; + std::cout << "tvec " << std::endl << tvec << std::endl; + std::cout << "rms " << std::endl << rtn << std::endl; + return rtn; } + +void GcvRodrigues_(cv::Mat src, cv::Mat& dst) { + cv::Rodrigues(src, dst); +} diff --git a/gocv/gocv_calib3d.go b/gocv/gocv_calib3d.go index b16b406..4e52da8 100644 --- a/gocv/gocv_calib3d.go +++ b/gocv/gocv_calib3d.go @@ -65,7 +65,17 @@ func GcvCalibrateCamera(objPts, imgPts, camMat *mat64.Dense) (calCamMat, rvec, t rvec = GcvMatToMat64(_rvec) tvec = GcvMatToMat64(_tvec) - return camMat, rvec, tvec + return calCamMat, rvec, tvec +} + +// Same as cv::Rodrigues +func GcvRodrigues(src *mat64.Dense) (dst *mat64.Dense) { + gcvSrc := Mat64ToGcvMat(src) + gcvDst := NewGcvMat() + GcvRodrigues_(gcvSrc, gcvDst) + dst = GcvMatToMat64(gcvDst) + + return dst } // func mat64ToGcvPoint3f32Vector(mat *mat64.Dense) NewGcvPoint3f32Vector { diff --git a/gocv/gocv_calib3d.hpp b/gocv/gocv_calib3d.hpp index 09195d2..cb9c342 100644 --- a/gocv/gocv_calib3d.hpp +++ b/gocv/gocv_calib3d.hpp @@ -10,3 +10,5 @@ cv::Mat GcvInitCameraMatrix2D_(VecPoint3f objPts, VecPoint2f imgPts); double GcvCalibrateCamera_(VecPoint3f objPts, VecPoint2f imgPts, cv::Size2i imgSize, cv::Mat& cameraMatrix, cv::Mat& rvec, cv::Mat& tvec); + +void GcvRodrigues_(cv::Mat src, cv::Mat& dst); diff --git a/gocv/gocv_calib3d_test.go b/gocv/gocv_calib3d_test.go index ed8d65a..cc527df 100644 --- a/gocv/gocv_calib3d_test.go +++ b/gocv/gocv_calib3d_test.go @@ -3,8 +3,8 @@ package gocv import ( "testing" - "github.com/davecgh/go-spew/spew" "github.com/gonum/matrix/mat64" + "github.com/stretchr/testify/assert" ) func TestGcvInitCameraMatrix2D(t *testing.T) { @@ -12,16 +12,20 @@ func TestGcvInitCameraMatrix2D(t *testing.T) { 0, 25, 0, 0, -25, 0, -47, 25, 0, - -47, -25, 0}) + -47, -25, 0, + }) imgPts := mat64.NewDense(4, 2, []float64{ 1136.4140625, 1041.89208984, 1845.33190918, 671.39581299, 302.73373413, 634.79998779, - 1051.46154785, 352.76107788}) + 1051.46154785, 352.76107788, + }) camMat := GcvInitCameraMatrix2D(objPts, imgPts) - spew.Dump(camMat) + assert.Equal(t, camMat.Row(nil, 0), []float64{4828.129063751587, 0, 959.5}) + assert.Equal(t, camMat.Row(nil, 1), []float64{0, 4828.129063751587, 539.5}) + assert.Equal(t, camMat.Row(nil, 2), []float64{0, 0, 1}) } func TestGcvCalibrateCamera(t *testing.T) { @@ -29,18 +33,45 @@ func TestGcvCalibrateCamera(t *testing.T) { 0, 25, 0, 0, -25, 0, -47, 25, 0, - -47, -25, 0}) + -47, -25, 0, + }) imgPts := mat64.NewDense(4, 2, []float64{ 1136.4140625, 1041.89208984, 1845.33190918, 671.39581299, 302.73373413, 634.79998779, - 1051.46154785, 352.76107788}) + 1051.46154785, 352.76107788, + }) camMat := GcvInitCameraMatrix2D(objPts, imgPts) camMat, rvec, tvec := GcvCalibrateCamera(objPts, imgPts, camMat) - spew.Dump(camMat) - spew.Dump(rvec) - spew.Dump(tvec) + + assert.Equal(t, camMat.Row(nil, 0), []float64{5.47022369e+03, 0.00000000e+00, 9.59500000e+02}) + assert.Equal(t, camMat.Row(nil, 1), []float64{0.00000000e+00, 5.47022369e+03, 5.39500000e+02}) + assert.Equal(t, camMat.Row(nil, 2), []float64{0.00000000e+00, 0.00000000e+00, 1.00000000e+00}) + + assert.Equal(t, rvec.Col(nil, 0), []float64{-0.99458984, 0.54674764, -2.69721055}) + assert.Equal(t, tvec.Col(nil, 0), []float64{-23.25417757, -12.6155423, -227.64212085}) +} + +func TestGcvRodrigues(t *testing.T) { + rvec := mat64.NewDense(3, 1, []float64{ + -0.99458984, + 0.54674764, + -2.69721055, + }) + rmat := GcvRodrigues(rvec) + + assert.InDelta(t, rmat.At(0, 0), -0.74853587, 1e-6) + assert.InDelta(t, rmat.At(0, 1), 0.07139127, 1e-6) + assert.InDelta(t, rmat.At(0, 2), 0.65923997, 1e-6) + + assert.InDelta(t, rmat.At(1, 0), -0.32247419, 1e-6) + assert.InDelta(t, rmat.At(1, 1), -0.90789575, 1e-6) + assert.InDelta(t, rmat.At(1, 2), -0.26783521, 1e-6) + + assert.InDelta(t, rmat.At(2, 0), 0.57940008, 1e-6) + assert.InDelta(t, rmat.At(2, 1), -0.41307214, 1e-6) + assert.InDelta(t, rmat.At(2, 2), 0.70261437, 1e-6) }