Mat Basic Processing2
These codes are included in the OpenCVForUnity Example Unity scenes. (MatBasicProcessingExample)
Merge
Example Code:
// // simple composition: Merge example // // 2x2 matrix Mat m1 = new Mat (2, 2, CvType.CV_64FC1); m1.put (0, 0, 1.0, 2.0, 3.0, 4.0); Mat m2 = new Mat (2, 2, CvType.CV_64FC1); m2.put (0, 0, 1.1, 2.1, 3.1, 4.1); Mat m3 = new Mat (2, 2, CvType.CV_64FC1); m3.put (0, 0, 1.2, 2.2, 3.2, 4.2); List<Mat> mv = new List<Mat>(); mv.Add (m1); mv.Add (m2); mv.Add (m3); // merge Mat m_merged = new Mat(); Core.merge (mv, m_merged); // dump Debug.Log (""m_merged="" + m_merged.dump());
Execution Result:
m_merged=[1, 1.1, 1.2, 2, 2.1, 2.2; 3, 3.1, 3.2, 4, 4.1, 4.2]
MixChannels
Example Code:
// // complex composition: mixChannels example // // 2x2 matrix Mat m1 = new Mat (2, 2, CvType.CV_64FC1); m1.put (0, 0, 1.0, 2.0, 3.0, 4.0); Mat m2 = new Mat (2, 2, CvType.CV_64FC1); m2.put (0, 0, 1.1, 2.1, 3.1, 4.1); Mat m3 = new Mat (2, 2, CvType.CV_64FC1); m3.put (0, 0, 1.2, 2.2, 3.2, 4.2); List<Mat> mv = new List<Mat>(); mv.Add (m1); mv.Add (m2); mv.Add (m3); // mat for output must be allocated. Mat m_mixed1 = new Mat(2, 2, CvType.CV_64FC2); Mat m_mixed2 = new Mat(2, 2, CvType.CV_64FC2); MatOfInt fromTo = new MatOfInt (0,0, 1,1, 1,3, 2,2); List<Mat> mixv = new List<Mat> (); mixv.Add (m_mixed1); mixv.Add (m_mixed2); // mix Core.mixChannels (mv, mixv, fromTo); // dump Debug.Log (""m_mixed1="" + m_mixed1.dump()); Debug.Log (""m_mixed2="" + m_mixed2.dump());
Execution Result:
m_mixed1=[1, 1.1, 2, 2.1; 3, 3.1, 4, 4.1] m_mixed2=[1.2, 1.1, 2.2, 2.1; 3.2, 3.1, 4.2, 4.1]
Split
Example Code:
// // split example // // channels=3, 2x3 matrix Mat m1 = new Mat (2, 3, CvType.CV_64FC3); m1.put (0, 0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18); List<Mat> planes = new List<Mat>(); // split Core.split (m1, planes); // dump foreach (Mat item in planes) { Debug.Log (item.dump()); }
Execution Result:
[1, 4, 7; 10, 13, 16] [2, 5, 8; 11, 14, 17] [3, 6, 9; 12, 15, 18]
Reduce
Example Code:
// // reduce example // // 3x3 matrix Mat m1 = new Mat (3, 3, CvType.CV_64FC1); m1.put (0, 0, 1, 5, 3, 4, 2, 6, 7, 8, 9); Mat v1 = new Mat (); Mat v2 = new Mat (); Mat v3 = new Mat (); Mat v4 = new Mat (); // reduce 3 x 3 matrix to one row Core.reduce (m1, v1, 0, Core.REDUCE_SUM); // total value of each column Core.reduce (m1, v2, 0, Core.REDUCE_AVG); // total average value of each column Core.reduce (m1, v3, 0, Core.REDUCE_MIN); // minimum value of each column Core.reduce (m1, v4, 0, Core.REDUCE_MAX); // maximum value of each column // dump Debug.Log (""m1="" + m1.dump()); Debug.Log (""v1(sum)="" + v1.dump()); Debug.Log (""v2(avg)="" + v2.dump()); Debug.Log (""v3(min)="" + v3.dump()); Debug.Log (""v4(max)="" + v4.dump()); // reduce 3 x 3 matrix to one col Core.reduce (m1, v1, 1, Core.REDUCE_SUM); // total value of each row Core.reduce (m1, v2, 1, Core.REDUCE_AVG); // total average value of row Core.reduce (m1, v3, 1, Core.REDUCE_MIN); // minimum value of each row Core.reduce (m1, v4, 1, Core.REDUCE_MAX); // maximum value of each row // dump Debug.Log (""m1="" + m1.dump()); Debug.Log (""v1(sum)="" + v1.dump()); Debug.Log (""v2(avg)="" + v2.dump()); Debug.Log (""v3(min)="" + v3.dump()); Debug.Log (""v4(max)="" + v4.dump());
Execution Result:
m1=[1, 5, 3; 4, 2, 6; 7, 8, 9] v1(sum)=[12, 15, 18] v2(avg)=[4, 5, 6] v3(min)=[1, 2, 3] v4(max)=[7, 8, 9] m1=[1, 5, 3; 4, 2, 6; 7, 8, 9] v1(sum)=[9; 12; 24] v2(avg)=[3; 4; 8] v3(min)=[1; 2; 7] v4(max)=[5; 6; 9]
Submatrix
Example Code:
// // submatrix (ROI) example // // 3x3 matrix Mat m1 = new Mat (3, 3, CvType.CV_64FC1); m1.put (0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); Debug.Log (""m1="" + m1.dump ()); // get submatrix (ROI) of range (row[0_2] col[0_2]) Mat m2 = new Mat (m1, new OpenCVForUnity.Rect(0,0,2,2)); Debug.Log (""m2="" + m2.dump()); Debug.Log (""m2.submat()="" + m2.submat(0,2,0,2).dump()); // find the parent matrix size of the submatrix (ROI) m2 and its position in it Size wholeSize = new Size (); Point ofs = new Point (); m2.locateROI (wholeSize, ofs); Debug.Log (""wholeSize:"" + wholeSize.width + ""x"" + wholeSize.height); Debug.Log (""offset:"" + ofs.x + "", "" + ofs.y); // expand the range of submatrix (ROI) m2.adjustROI(0, 1, 0, 1); Debug.Log (""rows="" + m2.rows() + "", "" + ""cols="" + m2.cols()); Debug.Log (""m2="" + m2.dump());
Execution Result:
m1=[1, 2, 3; 4, 5, 6; 7, 8, 9] m2=[1, 2; 4, 5] m2.submat()=[1, 2; 4, 5] wholeSize:3x3 offset:0, 0 rows=3, cols=3 m2=[1, 2, 3; 4, 5, 6; 7, 8, 9]
RandShuffle
Example Code:
// // randShuffle example // // 4x5 matrix Mat m1 = new Mat (4, 5, CvType.CV_64FC1); m1.put (0, 0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20); Debug.Log (""m1(original)="" + m1.dump ()); // shuffle Core.randShuffle (m1, UnityEngine.Random.value); Debug.Log (""m1(shuffle)="" + m1.dump ()); // submatrix Mat m2 = new Mat (m1, new OpenCVForUnity.Rect(1,1,3,2)); Debug.Log (""m2(sub-matrix)="" + m2.dump()); Core.randShuffle (m2, UnityEngine.Random.value); Debug.Log (""m2(sub-matrix)="" + m2.dump()); Debug.Log (""m1="" + m1.dump ());
Execution Result:
m1(original)=[1, 2, 3, 4, 5; 6, 7, 8, 9, 10; 11, 12, 13, 14, 15; 16, 17, 18, 19, 20] m1(shuffle)=[7, 5, 20, 3, 2; 11, 1, 13, 17, 4; 12, 19, 14, 6, 16; 10, 8, 9, 18, 15] m2(sub-matrix)=[1, 13, 17; 19, 14, 6] m2(shuffle sub-matrix)=[1, 6, 19; 14, 13, 17] m1=[7, 5, 20, 3, 2; 11, 1, 6, 19, 4; 12, 14, 13, 17, 16; 10, 8, 9, 18, 15]
Sort
Example Code:
// // sort example // // 5x5 matrix Mat m1 = new Mat (5, 5, CvType.CV_8UC1); Core.randu (m1, 0, 25); Debug.Log (""m1="" + m1.dump ()); executionResultText.text = ""m1="" + m1.dump() + ""\n""; Mat dst_mat = new Mat (); // sort ascending Core.sort (m1, dst_mat, Core.SORT_EVERY_ROW|Core.SORT_ASCENDING); Debug.Log (""ROW|ASCENDING:"" + dst_mat.dump ()); // sort descending Core.sort (m1, dst_mat, Core.SORT_EVERY_ROW|Core.SORT_DESCENDING); Debug.Log (""ROW|DESCENDING:"" + dst_mat.dump ()); // sort ascending Core.sort (m1, dst_mat, Core.SORT_EVERY_COLUMN|Core.SORT_ASCENDING); Debug.Log (""COLUMN|ASCENDING:"" + dst_mat.dump ()); // sort descending Core.sort (m1, dst_mat, Core.SORT_EVERY_COLUMN|Core.SORT_DESCENDING); Debug.Log (""COLUMN|DESCENDING:"" + dst_mat.dump ());
Execution Result:
m1=[ 21, 6, 12, 22, 1; 21, 10, 22, 23, 15; 0, 16, 3, 3, 17; 15, 0, 5, 18, 20; 7, 17, 16, 17, 14] ROW|ASCENDING:[ 1, 6, 12, 21, 22; 10, 15, 21, 22, 23; 0, 3, 3, 16, 17; 0, 5, 15, 18, 20; 7, 14, 16, 17, 17] ROW|DESCENDING:[ 22, 21, 12, 6, 1; 23, 22, 21, 15, 10; 17, 16, 3, 3, 0; 20, 18, 15, 5, 0; 17, 17, 16, 14, 7] COLUMN|ASCENDING:[ 0, 0, 3, 3, 1; 7, 6, 5, 17, 14; 15, 10, 12, 18, 15; 21, 16, 16, 22, 17; 21, 17, 22, 23, 20] COLUMN|DESCENDING:[ 21, 17, 22, 23, 20; 21, 16, 16, 22, 17; 15, 10, 12, 18, 15; 7, 6, 5, 17, 14; 0, 0, 3, 3, 1]
Comparison
Example Code:
// // comparison example // // 3x3 matrix Mat m1 = new Mat (3, 3, CvType.CV_64FC1); m1.put (0, 0, 1,2,3,4,5,6,7,8,9); Mat m2 = new Mat (3, 3, CvType.CV_64FC1); m2.put (0, 0, 10,11,12,13,14,15,16,17,18); Debug.Log (""m1="" + m1.dump ()); Debug.Log (""m2="" + m2.dump ()); Mat dst_mat = new Mat (); // GT (M1 > M2) Core.compare (m1, m2, dst_mat, Core.CMP_GT); Debug.Log (""GT (M1 > M2)="" + dst_mat.dump ()); // GE (M1 >= M2) Core.compare (m1, m2, dst_mat, Core.CMP_GE); Debug.Log (""GE (M1 >= M2)="" + dst_mat.dump ()); // EQ (M1 == M2) Core.compare (m1, m2, dst_mat, Core.CMP_EQ); Debug.Log (""EQ (M1 == M2)="" + dst_mat.dump ()); // NE (M1 != M2) Core.compare (m1, m2, dst_mat, Core.CMP_NE); Debug.Log (""NE (M1 != M2)="" + dst_mat.dump ()); // LE (M1 <= M2) Core.compare (m1, m2, dst_mat, Core.CMP_LE); Debug.Log (""LE (M1 <= M2)="" + dst_mat.dump ()); // LT (M1 < M2) Core.compare (m1, m2, dst_mat, Core.CMP_LT); Debug.Log (""LT (M1 < M2)="" + dst_mat.dump ());
Execution Result:
m1=[1, 2, 3; 4, 5, 6; 7, 8, 9] m2=[9, 8, 7; 6, 5, 4; 3, 2, 1] GT (M1 > M2)=[ 0, 0, 0; 0, 0, 255; 255, 255, 255] GE (M1 >= M2)=[ 0, 0, 0; 0, 255, 255; 255, 255, 255] EQ (M1 == M2)=[ 0, 0, 0; 0, 255, 0; 0, 0, 0] NE (M1 != M2)=[255, 255, 255; 255, 0, 255; 255, 255, 255] LE (M1 <= M2)=[255, 255, 255; 255, 255, 0; 0, 0, 0] LT (M1 < M2)=[255, 255, 255; 255, 0, 0; 0, 0, 0]
Operators
Example Code:
// // operators example // // 3x3 matrix Mat m1 = new Mat (3, 3, CvType.CV_64FC1); m1.put (0, 0, 1,2,3,4,5,6,7,8,9); Mat m2 = new Mat (3, 3, CvType.CV_64FC1); m2.put (0, 0, 10,11,12,13,14,15,16,17,18); Scalar s = new Scalar (5); double alpha = 3; Debug.Log (""m1="" + m1.dump ()); Debug.Log (""m2="" + m2.dump ()); Debug.Log (""s="" + s); Debug.Log (""alpha="" + alpha); // Addition, subtraction, negation: A+B, A-B, A+s, A-s, s+A, s-A, -A // (M1 + M2 = Core.add (M1, M2, M_dst)) Debug.Log (""m1+m2="" + (m1 + m2).dump()); // (M1 + s = Core.add (M1, s, M_dst)) Debug.Log (""m1+s="" + (m1 + s).dump()); // (M1 - M2 = Core.subtract (M1, M2, M_dst)) Debug.Log (""m1-m2="" + (m1 - m2).dump()); // (M1 - s = Core.subtract (M1, s, M_dst)) Debug.Log (""m1-s="" + (m1 - s).dump()); // (-M1 = Core.multiply (M1, Scalar.all (-1), M_dst)) Debug.Log (""-m1="" + (-m1).dump()); // Scaling: A*alpha A/alpha // (M1 * 3 = Core.multiply (M1, Scalar.all (3), M_dst)) Debug.Log (""m1*alpha="" + (m1*alpha).dump()); // (M1 / 3 = Core.divide (M1, Scalar.all (3), M_dst)) Debug.Log (""m1/alpha="" + (m1/alpha).dump()); // Per-element multiplication and division: A.mul(B), A/B, alpha/A // (M1.mul(M2) = M1.mul (M2)) Debug.Log (""m1.mul(m2)="" + (m1.mul(m2)).dump()); // (M1 / M2 = Core.divide (M1, M2, M_dst)) Debug.Log (""m1/m2="" + (m1 / m2).dump()); // (3 / M1 = Core.divide (new Mat (M1.size (), M1.type (), Scalar.all (3)), M1, M_dst)) Debug.Log (""alpha/m2="" + (alpha / m2).dump()); // Matrix multiplication: A*B // (M1 * M2 = Core.gemm (M1, M2, 1, new Mat (), 0, M_dst)) Debug.Log (""m1*m2="" + (m1 * m2).dump()); // Bitwise logical operations: A logicop B, A logicop s, s logicop A, ~A, where logicop is one of : &, |, ^. // (M1 & M2 = Core.bitwise_and (M1, M2, M_dst)) Debug.Log (""m1&m2="" + (m1 & m2).dump()); // (M1 | M2 = Core.bitwise_or (M1, M2, M_dst)) Debug.Log (""m1|m2="" + (m1 | m2).dump()); // (M1 ^ M2 = Core.bitwise_xor (M1, M2, M_dst)) Debug.Log (""m1^m2="" + (m1 ^ m2).dump()); // (~M1 = Core.bitwise_not (M1, M_dst)) Debug.Log (""~m1="" + (~m1).dump()); // Note. // The assignment operator behavior is different from OpenCV (c ++). // For example, C = A + B will not be expanded to cv::add(A, B, C). // Also cannot assign a scalar to Mat like C = s. // In c#, it is not possible to explicitly overload compound assignment operators such as “A *= B“. // Instead, binary operator overloading is used implicitly. // Therefore, whenever an operator is used, a new mat is created and assigned.
Execution Result:
m1=[1, 2, 3; 4, 5, 6; 7, 8, 9] m2=[10, 11, 12; 13, 14, 15; 16, 17, 18] s=[5, 0, 0, 0] alpha=3 m1+m2=[11, 13, 15; 17, 19, 21; 23, 25, 27] m1+s=[6, 7, 8; 9, 10, 11; 12, 13, 14] m1-m2=[-9, -9, -9; -9, -9, -9; -9, -9, -9] m1-s=[-4, -3, -2; -1, 0, 1; 2, 3, 4] -m1=[-1, -2, -3; -4, -5, -6; -7, -8, -9] m1*alpha=[3, 6, 9; 12, 15, 18; 21, 24, 27] m1/alpha=[0.3333333333333333, 0.6666666666666666, 1; 1.333333333333333, 1.666666666666667, 2; 2.333333333333333, 2.666666666666667, 3] m1.mul(m2)=[10, 22, 36; 52, 70, 90; 112, 136, 162] m1/m2=[0.1, 0.1818181818181818, 0.25; 0.3076923076923077, 0.3571428571428572, 0.4; 0.4375, 0.4705882352941176, 0.5] alpha/m2=[0.3, 0.2727272727272727, 0.25; 0.2307692307692308, 0.2142857142857143, 0.2; 0.1875, 0.1764705882352941, 0.1666666666666667] m1*m2=[84, 90, 96; 201, 216, 231; 318, 342, 366] m1&m2=[4.450147717014403e-308, 2, 3; 2, 2.5, 3; 4, 8, 9] m1|m2=[nan(snan), 11, 12; 26, 28, 30; 28, 17, 18] m1^m2=[5.617791046444737e+307, 6.118953110894804e-308, 4.450147717014403e-308; 1.446298008029681e-307, 1.335044315104321e-307, 1.223790622178961e-307; 7.787758504775205e-308, 2.364140974663901e-308, 2.225073858507201e-308] ~m1=[-4, -2, -1.5; -0.9999999999999999, -0.8749999999999999, -0.7499999999999999; -0.6249999999999999, -0.4999999999999999, -0.4687499999999999] // Note. // The assignment operator behavior is different from OpenCV (c ++). // For example, C = A + B will not be expanded to cv::add(A, B, C). // Also cannot assign a scalar to Mat like C = s. // In c#, it is not possible to explicitly overload compound assignment operators such as “A *= B“. // Instead, binary operator overloading is used implicitly. // Therefore, whenever an operator is used, a new mat is created and assigned.
Get And Put
Example Code:
// // get and put example // // channels=4 3x3 matrix Mat m1 = new Mat (3, 3, CvType.CV_8UC4 , new Scalar(1,2,3,4)); Debug.Log (""m1="" + m1.dump ()); // get an element value. double[] m1_1_1 = m1.get(1,1); Debug.Log (""m1[1,1]="" + m1_1_1[0] + "", "" + m1_1_1[1] + "", "" + m1_1_1[2] + "", "" + m1_1_1[3]); // get an array of all element values. byte[] m1_array = new byte[m1.total () * m1.channels()]; m1.get (0, 0, m1_array); string dump_str = """"; foreach (var i in m1_array){ dump_str += i + "", ""; } Debug.Log (""m1_array="" + dump_str); // another faster way. (use Utils.copyFromMat()) Utils.copyFromMat (m1, m1_array); dump_str = ""; foreach (var i in m1_array) { dump_str += i + ", "; } Debug.Log ("m1_array (use Utils.copyFromMat())=" + dump_str); // put an element value in a matrix. Mat m2 = m1.clone (); m2.put (1, 1, 5,6,7,8); Debug.Log (""m2="" + m2.dump ()); // put an array of element values in a matrix. byte[] m2_arr = new byte[]{5,6,7,8,5,6,7,8,5,6,7,8,5,6,7,8,5,6,7,8,5,6,7,8,5,6,7,8,5,6,7,8,5,6,7,8}; m2.put (0, 0, m2_arr); Debug.Log (""m2="" + m2.dump ()); // another faster way. (use Utils.copyToMat()) Utils.copyToMat (m2_arr, m2); Debug.Log ("m2 (use Utils.copyToMat())=" + m2.dump ()); // fill element values (setTo method) m2.setTo(new Scalar(100,100,100,100)); Debug.Log (""m2="" + m2.dump ());
Execution Result:
m1=[ 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4; 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4; 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4] m1[1,1]=1, 2, 3, 4 m1_array=1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, m1_array (use Utils.copyFromMat())=1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, m2=[ 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4; 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4; 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4] m2=[ 5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8; 5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8; 5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8] m2 (use Utils.copyToMat())=[ 5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8; 5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8; 5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8] m2=[100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100; 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100; 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
Accessing Pixel Values
Example Code:
// // accessing pixel value example // // How access pixel value in an OpenCV Mat. // channels=4 512x512 matrix (RGBA color image) Mat imgMat = new Mat(512, 512, CvType.CV_8UC4, new Scalar(0, 0, 0, 255)); System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); // // 1. Use get and put method. // imgMat.setTo(new Scalar(0, 0, 0, 255)); watch.Start(); int rows = imgMat.rows(); int cols = imgMat.cols(); for (int i0 = 0; i0 < rows; i0++) { for (int i1 = 0; i1 < cols; i1++) { byte[] p = new byte[4]; imgMat.get(i0, i1, p); p[0] = (byte)(p[0] + 127); // R p[1] = (byte)(p[1] + 127); // G p[2] = (byte)(p[2] + 127); // B imgMat.put(i0, i1, p); } } watch.Stop(); Debug.Log("1. Use get and put method. time: " + watch.ElapsedMilliseconds + " ms"); executionResultText.text = "1. Use get and put method. time: " + watch.ElapsedMilliseconds + " ms" + "\n"; // // 2. Use MatIndexer. // imgMat.setTo(new Scalar(0, 0, 0, 255)); watch.Reset(); watch.Start(); MatIndexer indexer = new MatIndexer(imgMat); rows = imgMat.rows(); cols = imgMat.cols(); for (int i0 = 0; i0 < rows; i0++) { for (int i1 = 0; i1 < cols; i1++) { byte[] p = new byte[4]; indexer.get(i0, i1, p); p[0] = (byte)(p[0] + 127); // R p[1] = (byte)(p[1] + 127); // G p[2] = (byte)(p[2] + 127); // B indexer.put(i0, i1, p); } } watch.Stop(); Debug.Log("2. Use MatIndexer. time: " + watch.ElapsedMilliseconds + " ms"); executionResultText.text += "2. Use MatIndexer. time: " + watch.ElapsedMilliseconds + " ms" + "\n"; // // 3. Use MatUtils.copyFromMat and MatUtils.copyToMat method. // imgMat.setTo(new Scalar(0, 0, 0, 255)); watch.Reset(); watch.Start(); // Copies an OpenCV Mat data to a pixel data Array. byte[] img_array = new byte[imgMat.total() * imgMat.channels()]; MatUtils.copyFromMat(imgMat, img_array); long step0 = imgMat.step1(0); long step1 = imgMat.step1(1); rows = imgMat.rows(); cols = imgMat.cols(); for (int i0 = 0; i0 < rows; i0++) { for (int i1 = 0; i1 < cols; i1++) { long p1 = step0 * i0 + step1 * i1; long p2 = p1 + 1; long p3 = p1 + 2; img_array[p1] = (byte)(img_array[p1] + 127); // R img_array[p2] = (byte)(img_array[p2] + 127); // G img_array[p3] = (byte)(img_array[p3] + 127); // B } } // Copies a pixel data Array to an OpenCV Mat data. MatUtils.copyToMat(img_array, imgMat); watch.Stop(); Debug.Log("3. Use MatUtils.copyFromMat and MatUtils.copyToMat method. time: " + watch.ElapsedMilliseconds + " ms"); executionResultText.text += "3. Use MatUtils.copyFromMat and MatUtils.copyToMat method. time: " + watch.ElapsedMilliseconds + " ms" + "\n"; #if OPENCV_USE_UNSAFE_CODE // // 4. Use pointer access. // imgMat.setTo(new Scalar(0, 0, 0, 255)); watch.Reset(); watch.Start(); step0 = imgMat.step1(0); step1 = imgMat.step1(1); long ptrVal = imgMat.dataAddr(); unsafe { rows = imgMat.rows(); cols = imgMat.cols(); for (int i0 = 0; i0 < rows; i0++) { for (int i1 = 0; i1 < cols; i1++) { byte* p1 = (byte*)(ptrVal + (step0 * i0) + (step1 * i1)); byte* p2 = p1 + 1; byte* p3 = p1 + 2; *p1 = (byte)(*p1 + 127); // R *p2 = (byte)(*p2 + 127); // G *p3 = (byte)(*p3 + 127); // B } } } watch.Stop(); Debug.Log("4. Use pointer access. time: " + watch.ElapsedMilliseconds + " ms"); executionResultText.text += "4. Use pointer access. time: " + watch.ElapsedMilliseconds + " ms" + "\n"; #endif
Execution Result:
1. Use get and put method. time: 107 ms 2. Use MatIndexer. time: 60 ms 3. Use MatUtils.copyFromMat and MatUtils.copyToMat method. time: 4 ms 4. Use pointer access. time: 1 ms