Skip to content

Commit

Permalink
core: allow to construct CvMat from native cv::Mat pointer.
Browse files Browse the repository at this point in the history
This patch solves the use-case when there is a mix of native code that
uses opencv and gocv.
In case that native code that utilizes opencv creates a CvMat and there
is a need to pass it to the golang environment without creating a copy.

The solution is to pass a native pointer to gocv and eventually call
cv::Mat copy constructor that performs shallow copy of the origin CvMat.

(See
https://docs.opencv.org/4.5.2/d3/d63/classcv_1_1Mat.html#a294eaf8a95d2f9c7be19ff594d06278e)
for more details.
  • Loading branch information
solganik committed Jun 27, 2021
1 parent 9d52420 commit 2df2bce
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 0 deletions.
4 changes: 4 additions & 0 deletions core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ Mat Mat_FromPtr(Mat m, int rows, int cols, int type, int prow, int pcol) {
return new cv::Mat(rows, cols, type, m->ptr(prow, pcol));
}

Mat Mat_FromCVMat(Mat m) {
return new cv::Mat(*m);
}

// Mat_Close deletes an existing Mat
void Mat_Close(Mat m) {
delete m;
Expand Down
8 changes: 8 additions & 0 deletions core.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,14 @@ func NewMatFromBytes(rows int, cols int, mt MatType, data []byte) (Mat, error) {
return mat, nil
}

// NewMatFromCVMat returns a new Mat from native CVMat pointer. This can be used in case
// some of the application code uses third party native libraries that return CVMat, so we can
// construct gocv Mat from them. Data is not copied, Copy Constructor of cv::Mat is called.
func NewMatFromCVMat(cvMatPtr unsafe.Pointer) Mat {
newMat := C.Mat_FromCVMat(C.Mat(cvMatPtr))
return Mat{p: newMat}
}

// Returns an identity matrix of the specified size and type.
//
// The method returns a Matlab-style identity matrix initializer, similarly to Mat::zeros. Similarly to Mat::ones.
Expand Down
1 change: 1 addition & 0 deletions core.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ Mat Mat_NewFromScalar(const Scalar ar, int type);
Mat Mat_NewWithSizeFromScalar(const Scalar ar, int rows, int cols, int type);
Mat Mat_NewFromBytes(int rows, int cols, int type, struct ByteArray buf);
Mat Mat_FromPtr(Mat m, int rows, int cols, int type, int prows, int pcols);
Mat Mat_FromCVMat(Mat m);
void Mat_Close(Mat m);
int Mat_Empty(Mat m);
bool Mat_IsContinuous(Mat m);
Expand Down
17 changes: 17 additions & 0 deletions core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"runtime"
"strings"
"testing"
"unsafe"
)

func TestMat(t *testing.T) {
Expand All @@ -19,6 +20,22 @@ func TestMat(t *testing.T) {
}
}

func TestMatNativeCopy(t *testing.T) {
mat := NewMatWithSize(10, 10, MatTypeCV32F)
mat.SetTo(NewScalar(1,2,3, 4))
matData := mat.ToBytes()

mat2 := NewMatFromCVMat(unsafe.Pointer(mat.p))
mat.Close()
runtime.GC()

if !bytes.Equal(matData, mat2.ToBytes()) {
t.Error("TestMatNativeCopy: mats are not equal")
}

mat.Close()
}

func TestMatWithSizes(t *testing.T) {
t.Run("create mat with multidimensional array", func(t *testing.T) {
sizes := []int{100, 100, 100}
Expand Down

0 comments on commit 2df2bce

Please sign in to comment.