Skip to content

Commit

Permalink
add functions (singular value decomposition, multiply between matrice…
Browse files Browse the repository at this point in the history
…s, transpose matrix) (hybridgroup#559)

* core: add the following:
   cv::SVD::compute()
   Mat.MultiplyMatrix(): Multiply between matrices 
   Mat.T(): transpose matrix
  • Loading branch information
rudyeeee authored and deadprogram committed Dec 23, 2019
1 parent 93d8d46 commit 453df7c
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 0 deletions.
8 changes: 8 additions & 0 deletions core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,14 @@ void Mat_DivideFloat(Mat m, float val) {
*m /= val;
}

Mat Mat_MultiplyMatrix(Mat x, Mat y) {
return new cv::Mat((*x) * (*y));
}

Mat Mat_T(Mat x) {
return new cv::Mat(x->t());
}

void Mat_AbsDiff(Mat src1, Mat src2, Mat dst) {
cv::absdiff(*src1, *src2, *dst);
}
Expand Down
11 changes: 11 additions & 0 deletions core.go
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,17 @@ func (m *Mat) DivideFloat(val float32) {
C.Mat_DivideFloat(m.p, C.float(val))
}

// MultiplyMatrix multiplies matrix (m*x)
func (m *Mat) MultiplyMatrix(x Mat) Mat {
return newMat(C.Mat_MultiplyMatrix(m.p, x.p))
}

// T transpose matrix
// https://docs.opencv.org/4.1.2/d3/d63/classcv_1_1Mat.html#aaa428c60ccb6d8ea5de18f63dfac8e11
func (m *Mat) T() Mat {
return newMat(C.Mat_T(m.p))
}

// ToImage converts a Mat to a image.Image.
func (m *Mat) ToImage() (image.Image, error) {
t := m.Type()
Expand Down
3 changes: 3 additions & 0 deletions core.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ void Mat_AddFloat(Mat m, float val);
void Mat_SubtractFloat(Mat m, float val);
void Mat_MultiplyFloat(Mat m, float val);
void Mat_DivideFloat(Mat m, float val);
Mat Mat_MultiplyMatrix(Mat x, Mat y);

Mat Mat_T(Mat x);

void LUT(Mat src, Mat lut, Mat dst);

Expand Down
39 changes: 39 additions & 0 deletions core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,21 @@ func TestMatMutators(t *testing.T) {
}
mat.Close()
})
t.Run("MultiplyMatrix", func(t *testing.T) {
mat := NewMatWithSizeFromScalar(NewScalar(30.0, 0, 0, 0), 2, 1, MatTypeCV32F)
mat2 := NewMatWithSizeFromScalar(NewScalar(30.0, 0, 0, 0), 1, 2, MatTypeCV32F)
mat3 := mat.MultiplyMatrix(mat2)
for i := 0; i < mat3.Cols(); i++ {
for j := 0; j < mat3.Rows(); j++ {
if mat3.GetFloatAt(i, j) != 900.0 {
t.Errorf("MultiplyMatrix incorrect value: %v\n", mat3.GetFloatAt(i, j))
}
}
}
mat.Close()
mat2.Close()
mat3.Close()
})
}

func TestMatAbsDiff(t *testing.T) {
Expand Down Expand Up @@ -2150,6 +2165,30 @@ func TestGetTickFrequencyCount(t *testing.T) {
}
}

func TestMatT(t *testing.T) {
var q = []float32{1, 3, 2, 4}
src := NewMatWithSize(2, 2, MatTypeCV32F)
defer src.Close()
src.SetFloatAt(0, 0, 1)
src.SetFloatAt(0, 1, 2)
src.SetFloatAt(1, 0, 3)
src.SetFloatAt(1, 1, 4)

dst := src.T()
defer dst.Close()

ret, err := dst.DataPtrFloat32()
if err != nil {
t.Error(err)
}

for i := 0; i < len(ret); i++ {
if ret[i] != q[i] {
t.Errorf("MatT incorrect value: %v\n", ret[i])
}
}
}

func compareImages(img0, img1 image.Image) bool {
bounds0 := img0.Bounds()
bounds1 := img1.Bounds()
Expand Down
5 changes: 5 additions & 0 deletions svd.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "svd.h"

void SVD_Compute(Mat src, Mat w, Mat u, Mat vt) {
cv::SVD::compute(*src, *w, *u, *vt, 0);
}
14 changes: 14 additions & 0 deletions svd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gocv

/*
#include <stdlib.h>
#include "svd.h"
*/
import "C"

// SVDCompute decomposes matrix and stores the results to user-provided matrices
//
// https://docs.opencv.org/4.1.2/df/df7/classcv_1_1SVD.html#a76f0b2044df458160292045a3d3714c6
func SVDCompute(src Mat, w, u, vt *Mat) {
C.SVD_Compute(src.Ptr(), w.Ptr(), u.Ptr(), vt.Ptr())
}
18 changes: 18 additions & 0 deletions svd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef _OPENCV3_SVD_H_
#define _OPENCV3_SVD_H_

#ifdef __cplusplus
#include <opencv2/opencv.hpp>

extern "C" {
#endif

#include "core.h"

void SVD_Compute(Mat src, Mat w, Mat u, Mat vt);

#ifdef __cplusplus
}
#endif

#endif //_OPENCV3_SVD_H
69 changes: 69 additions & 0 deletions svd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package gocv

import (
"testing"
)

func TestSVDCompute(t *testing.T) {
var resultW = []float32{6.167493, 3.8214223}
var resultU = []float32{-0.1346676, -0.99089086, 0.9908908, -0.1346676}
var resultVt = []float32{0.01964448, 0.999807, -0.999807, 0.01964448}

checkFunc := func(a []float32, b []float32) bool {
if len(a) != len(b) {
return false
}

for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}

src := NewMatWithSize(2, 2, MatTypeCV32F)
src.SetFloatAt(0, 0, 3.76956568)
src.SetFloatAt(0, 1, -0.90478725)
src.SetFloatAt(1, 0, 0.634576)
src.SetFloatAt(1, 1, 6.10002347)
defer src.Close()

w := NewMat()
defer w.Close()

u := NewMat()
defer u.Close()

vt := NewMat()
defer vt.Close()

SVDCompute(src, &w, &u, &vt)

dataW, err := w.DataPtrFloat32()
if err != nil {
t.Error(err)
}

if !checkFunc(resultW, dataW) {
t.Error("w value is incorrect")
}

dataU, err := u.DataPtrFloat32()
if err != nil {
t.Error(err)
}

if !checkFunc(resultU, dataU) {
t.Error("u value is incorrect")
}

dataVt, err := vt.DataPtrFloat32()
if err != nil {
t.Error(err)
}

if !checkFunc(resultVt, dataVt) {
t.Error("vt value is incorrect")
}
}

0 comments on commit 453df7c

Please sign in to comment.