Simple matrix multiplication for Mat in iOS/Android
authorGiles Payne <gilespayne@gmail.com>
Tue, 5 Oct 2021 11:16:06 +0000 (20:16 +0900)
committerGiles Payne <gilespayne@gmail.com>
Tue, 5 Oct 2021 11:16:06 +0000 (20:16 +0900)
modules/core/misc/java/src/java/core+Mat.java
modules/core/misc/java/src/java/core+MatMatMul.kt [new file with mode: 0644]
modules/core/misc/java/test/MatTest.java
modules/core/misc/objc/common/Mat.h
modules/core/misc/objc/common/Mat.mm
modules/core/misc/objc/common/MatExt.swift
modules/core/misc/objc/test/MatTest.swift
modules/java/generator/src/cpp/Mat.cpp

index 5fcc727..2d9ee31 100644 (file)
@@ -466,16 +466,32 @@ public class Mat {
     // C++: Mat Mat::mul(Mat m, double scale = 1)
     //
 
-    // javadoc: Mat::mul(m, scale)
+    /**
+     * Element-wise multiplication with scale factor
+     * @param m operand with with which to perform element-wise multiplication
+     * @param scale scale factor
+     */
     public Mat mul(Mat m, double scale) {
         return new Mat(n_mul(nativeObj, m.nativeObj, scale));
     }
 
-    // javadoc: Mat::mul(m)
+    /**
+    * Element-wise multiplication
+    * @param m operand with with which to perform element-wise multiplication
+    */
     public Mat mul(Mat m) {
         return new Mat(n_mul(nativeObj, m.nativeObj));
     }
 
+    /**
+    * Matrix multiplication
+    * @param m operand with with which to perform matrix multiplication
+    * @see Core#gemm(Mat, Mat, double, Mat, double, Mat, int)
+    */
+    public Mat matMul(Mat m) {
+        return new Mat(n_matMul(nativeObj, m.nativeObj));
+    }
+
     //
     // C++: static Mat Mat::ones(int rows, int cols, int type)
     //
@@ -1732,6 +1748,8 @@ public class Mat {
 
     private static native long n_mul(long nativeObj, long m_nativeObj);
 
+    private static native long n_matMul(long nativeObj, long m_nativeObj);
+
     // C++: static Mat Mat::ones(int rows, int cols, int type)
     private static native long n_ones(int rows, int cols, int type);
 
diff --git a/modules/core/misc/java/src/java/core+MatMatMul.kt b/modules/core/misc/java/src/java/core+MatMatMul.kt
new file mode 100644 (file)
index 0000000..3dcb6bd
--- /dev/null
@@ -0,0 +1,3 @@
+package org.opencv.core
+
+operator fun Mat.times(other: Mat): Mat = this.matMul(other)
index 3075dba..323440b 100644 (file)
@@ -686,6 +686,16 @@ public class MatTest extends OpenCVTestCase {
         assertMatEqual(truth, dst, EPS);
     }
 
+    public void testMatMulMat() {
+        Mat m1 = new Mat(2, 2, CvType.CV_32F, new Scalar(2));
+        Mat m2 = new Mat(2, 2, CvType.CV_32F, new Scalar(3));
+
+        dst = m1.matMul(m2);
+
+        truth = new Mat(2, 2, CvType.CV_32F, new Scalar(12));
+        assertMatEqual(truth, dst, EPS);
+    }
+
     public void testOnesIntIntInt() {
         dst = Mat.ones(matSize, matSize, CvType.CV_32F);
 
index fd1dce2..b5e8683 100644 (file)
@@ -114,7 +114,17 @@ CV_EXPORTS @interface Mat : NSObject
 - (BOOL)isSubmatrix;
 - (void)locateROI:(Size2i*)wholeSize ofs:(Point2i*)offset NS_SWIFT_NAME(locateROI(wholeSize:offset:));
 - (Mat*)mul:(Mat*)mat scale:(double)scale;
+/**
+ Performs element-wise multiplication
+ @param mat operand with with which to perform element-wise multiplication
+*/
 - (Mat*)mul:(Mat*)mat;
+/**
+ Performs matrix multiplication
+ @param mat operand with with which to perform matrix multiplication
+ @see `Core.gemm(...)`
+*/
+- (Mat*)matMul:(Mat*)mat;
 + (Mat*)ones:(int)rows cols:(int)cols type:(int)type NS_SWIFT_NAME(ones(rows:cols:type:));
 + (Mat*)ones:(Size2i*)size type:(int)type NS_SWIFT_NAME(ones(size:type:));
 + (Mat*)onesEx:(NSArray<NSNumber*>*)sizes type:(int)type NS_SWIFT_NAME(ones(sizes:type:));
index dc2316c..ab5e1de 100644 (file)
@@ -372,6 +372,11 @@ static bool updateIdx(cv::Mat* mat, std::vector<int>& indices, size_t inc) {
     return [[Mat alloc] initWithNativeMat:new cv::Mat(_nativePtr->mul(*(cv::Mat*)mat.nativePtr))];
 }
 
+- (Mat*)matMul:(Mat*)mat {
+    cv::Mat temp = self.nativeRef * mat.nativeRef;
+    return [Mat fromNative:temp];
+}
+
 + (Mat*)ones:(int)rows cols:(int)cols type:(int)type {
     return [[Mat alloc] initWithNativeMat:new cv::Mat(cv::Mat::ones(rows, cols, type))];
 }
index a6ba548..f0f4446 100644 (file)
@@ -715,3 +715,9 @@ public extension Mat {
         return MatAt(mat: self, indices: indices)
     }
 }
+
+public extension Mat {
+    static func *(lhs:Mat, rhs: Mat) -> Mat {
+        return lhs.matMul(rhs)
+    }
+}
index 2dcfedf..87f99fb 100644 (file)
@@ -683,6 +683,16 @@ class MatTests: OpenCVTestCase {
         try assertMatEqual(truth!, dst, OpenCVTestCase.EPS)
     }
 
+    func testMatMulMat() throws {
+        let m1 = Mat(rows: 2, cols: 2, type: CvType.CV_32F, scalar: Scalar(2))
+        let m2 = Mat(rows: 2, cols: 2, type: CvType.CV_32F, scalar: Scalar(3))
+
+        dst = m1.matMul(m2)
+
+        truth = Mat(rows: 2, cols: 2, type: CvType.CV_32F, scalar: Scalar(12))
+        try assertMatEqual(truth!, dst, OpenCVTestCase.EPS)
+    }
+
     func testOnesIntIntInt() throws {
         dst = Mat.ones(rows: OpenCVTestCase.matSize, cols: OpenCVTestCase.matSize, type: CvType.CV_32F)
 
index d59fe4a..f43a4c6 100644 (file)
@@ -1372,6 +1372,32 @@ JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1mul__JJ
 }
 
 
+//
+// Mat Mat Mat::matMul(Mat m)
+//
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1matMul__JJ
+  (JNIEnv* env, jclass, jlong self, jlong m_nativeObj);
+
+JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1matMul__JJ
+  (JNIEnv* env, jclass, jlong self, jlong m_nativeObj)
+{
+    static const char method_name[] = "Mat::n_1matMul__JJ()";
+    try {
+        LOGD("%s", method_name);
+        Mat* me = (Mat*) self; //TODO: check for NULL
+        Mat& m = *((Mat*)m_nativeObj);
+        Mat _retval_ = (*me) * m;
+        return (jlong) new Mat(_retval_);
+    } catch(const std::exception &e) {
+        throwJavaException(env, &e, method_name);
+    } catch (...) {
+        throwJavaException(env, 0, method_name);
+    }
+
+    return 0;
+}
+
 
 //
 // static Mat Mat::ones(int rows, int cols, int type)