diff --git a/ROADMAP.md b/ROADMAP.md index c2a91be6..c9013ee1 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -15,19 +15,19 @@ Your pull requests will be greatly appreciated! - [ ] **core. Core functionality - WORK STARTED** - [X] **Basic structures** - [ ] **Operations on arrays - WORK STARTED**. The following functions still need implementation: - - [ ] [Mahalanobis](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga4493aee129179459cbfc6064f051aa7d) + - [X] [Mahalanobis](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga4493aee129179459cbfc6064f051aa7d) - [ ] [mulTransposed](https://docs.opencv.org/master/d2/de8/group__core__array.html#gadc4e49f8f7a155044e3be1b9e3b270ab) - [ ] [PCABackProject](https://docs.opencv.org/master/d2/de8/group__core__array.html#gab26049f30ee8e94f7d69d82c124faafc) - [X] [PCACompute](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga4e2073c7311f292a0648f04c37b73781) - [ ] [PCAProject](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6b9fbc7b3a99ebfd441bbec0a6bc4f88) - [ ] [PSNR](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga07aaf34ae31d226b1b847d8bcff3698f) - - [ ] [randn](https://docs.opencv.org/master/d2/de8/group__core__array.html#gaeff1f61e972d133a04ce3a5f81cf6808) - - [ ] [randShuffle](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6a789c8a5cb56c6dd62506179808f763) - - [ ] [randu](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga1ba1026dca0807b27057ba6a49d258c0) - - [ ] [setRNGSeed](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga757e657c037410d9e19e819569e7de0f) + - [X] [randn](https://docs.opencv.org/master/d2/de8/group__core__array.html#gaeff1f61e972d133a04ce3a5f81cf6808) + - [X] [randShuffle](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga6a789c8a5cb56c6dd62506179808f763) + - [X] [randu](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga1ba1026dca0807b27057ba6a49d258c0) + - [X] [setRNGSeed](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga757e657c037410d9e19e819569e7de0f) - [ ] [SVBackSubst](https://docs.opencv.org/master/d2/de8/group__core__array.html#gab4e620e6fc6c8a27bb2be3d50a840c0b) - [ ] [SVDecomp](https://docs.opencv.org/master/d2/de8/group__core__array.html#gab477b5b7b39b370bb03e75b19d2d5109) - - [ ] [theRNG](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga75843061d150ad6564b5447e38e57722) + - [X] [theRNG](https://docs.opencv.org/master/d2/de8/group__core__array.html#ga75843061d150ad6564b5447e38e57722) - [ ] XML/YAML Persistence - [ ] [FileStorage](https://docs.opencv.org/master/da/d56/classcv_1_1FileStorage.html) diff --git a/core.cpp b/core.cpp index fdff80a0..1dd0decb 100644 --- a/core.cpp +++ b/core.cpp @@ -95,6 +95,18 @@ bool Mat_IsContinuous(Mat m) { return m->isContinuous(); } +void Mat_Inv(Mat m) { + m->inv(); +} + +Mat Mat_Col(Mat m, int c) { + return new cv::Mat(m->col(c)); +} + +Mat Mat_Row(Mat m, int r) { + return new cv::Mat(m->row(r)); +} + // Mat_Clone returns a clone of this Mat Mat Mat_Clone(Mat m) { return new cv::Mat(m->clone()); @@ -591,6 +603,10 @@ void Mat_Magnitude(Mat x, Mat y, Mat magnitude) { cv::magnitude(*x, *y, *magnitude); } +double Mat_Mahalanobis(Mat v1, Mat v2, Mat icovar) { + return cv::Mahalanobis(*v1, *v2, *icovar); +} + void Mat_Max(Mat src1, Mat src2, Mat dst) { cv::max(*src1, *src2, *dst); } diff --git a/core.go b/core.go index cea16d9b..026f1eed 100644 --- a/core.go +++ b/core.go @@ -343,6 +343,26 @@ func (m *Mat) IsContinuous() bool { return bool(C.Mat_IsContinuous(m.p)) } +// Inv inverses a matrix. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html#a039eb3c6740a850696a12519a4b8bfc6 +func (m *Mat) Inv() { + C.Mat_Inv(m.p) +} + +// Col creates a matrix header for the specified matrix column. +// The underlying data of the new matrix is shared with the original matrix. +func (m *Mat) Col(col int) Mat { + return newMat(C.Mat_Col(m.p, C.int(col))) +} + +// Row creates a matrix header for the specified matrix row. +// The underlying data of the new matrix is shared with the original matrix. +func (m *Mat) Row(row int) Mat { + return newMat(C.Mat_Row(m.p, C.int(row))) +} + // Clone returns a cloned full copy of the Mat. func (m *Mat) Clone() Mat { return newMat(C.Mat_Clone(m.p)) @@ -1391,6 +1411,14 @@ func Magnitude(x, y Mat, magnitude *Mat) { C.Mat_Magnitude(x.p, y.p, magnitude.p) } +// Mahalanobis calculates the Mahalanobis distance between two vectors. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d2/de8/group__core__array.html#ga4493aee129179459cbfc6064f051aa7d +func Mahalanobis(v1, v2, icovar Mat) float64 { + return float64(C.Mat_Mahalanobis(v1.p, v2.p, icovar.p)) +} + // Max calculates per-element maximum of two arrays or an array and a scalar. // // For further details, please see: diff --git a/core.h b/core.h index e47a108f..60c67c5a 100644 --- a/core.h +++ b/core.h @@ -283,6 +283,9 @@ Mat Mat_FromPtr(Mat m, int rows, int cols, int type, int prows, int pcols); void Mat_Close(Mat m); int Mat_Empty(Mat m); bool Mat_IsContinuous(Mat m); +void Mat_Inv(Mat m); +Mat Mat_Col(Mat m, int c); +Mat Mat_Row(Mat m, int r); Mat Mat_Clone(Mat m); void Mat_CopyTo(Mat m, Mat dst); int Mat_Total(Mat m); @@ -399,6 +402,7 @@ double KMeans(Mat data, int k, Mat bestLabels, TermCriteria criteria, int attemp double KMeansPoints(PointVector pts, int k, Mat bestLabels, TermCriteria criteria, int attempts, int flags, Mat centers); void Mat_Log(Mat src, Mat dst); void Mat_Magnitude(Mat x, Mat y, Mat magnitude); +double Mat_Mahalanobis(Mat v1, Mat v2, Mat icovar); void Mat_Max(Mat src1, Mat src2, Mat dst); void Mat_MeanStdDev(Mat src, Mat dstMean, Mat dstStdDev); void Mat_Merge(struct Mats mats, Mat dst); diff --git a/core_test.go b/core_test.go index 4f4fcca4..3d242551 100644 --- a/core_test.go +++ b/core_test.go @@ -2373,6 +2373,31 @@ func TestMatMagnitude(t *testing.T) { } } +func TestMatMahalanobis(t *testing.T) { + src := NewMatWithSize(10, 10, MatTypeCV32F) + defer src.Close() + + RandU(&src, Scalar{Val1: -128}, Scalar{Val1: 128}) + + icovar := NewMatWithSize(10, 10, MatTypeCV32F) + defer icovar.Close() + mean := NewMatWithSize(1, 10, MatTypeCV32F) + defer mean.Close() + + CalcCovarMatrix(src, &icovar, &mean, CovarRows|CovarNormal, MatTypeCV32F) + icovar.Inv() + + line1 := src.Row(0) + defer line1.Close() + line2 := src.Row(1) + defer line2.Close() + + result := Mahalanobis(line1, line2, icovar) + if result == 0 { + t.Error("Mahalanobis result should not be empty.") + } +} + func TestMatMax(t *testing.T) { src1 := NewMatWithSize(4, 4, MatTypeCV32F) defer src1.Close()