平常处理的jpg、png、bmp图片都是Bitmap,是像素点的矩阵。在OpenCV中最常用Mat对其进行操作。Mat即Matrix的缩写。
1.CvType
这个类的一些静态int类型变量用来标识数据的类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
CvType.CV_8U; // 8-每个元素占8位内存 U-元素为无符号unsigned int。默认单通道 CvType.CV_8UC1; // 8位 无符号 C1-单通道。C-Channel CvType.CV_8UC2; // 8位 无符号 双通道,多用来操作黑白灰度图 CvType.CV_8UC3; // 8位 无符号3通道,多操作RGB图 CvType.CV_8UC4; // 4通道,RGBA图 CvType.CV_8S; // 8位 S-short类型。默认单通道 CvType.CV_8SC1; // 8位 short 单通道 CvType.CV_8SC2; CvType.CV_8SC3; CvType.CV_8SC4; CvType.CV_16U; // 16位 无符号 默认单通道 CvType.CV_16UC1; // 16位 无符号 单通道 CvType.CV_16UC2; // 双通道 CvType.CV_16UC3; CvType.CV_16UC4; CvType.CV_16S; // 16位 short 默认单通道 CvType.CV_16SC1; // 16位 short 单通道 CvType.CV_16SC2; // 双通道 CvType.CV_16SC3; CvType.CV_16SC4; CvType.CV_32S; // 32位 short CvType.CV_32SC1; CvType.CV_32SC2; CvType.CV_32SC3; CvType.CV_32SC4; CvType.CV_32F; // 32位 float CvType.CV_32FC1; CvType.CV_32FC2; CvType.CV_32FC3; CvType.CV_32FC4; CvType.CV_64F; // 64位 float CvType.CV_64FC1; CvType.CV_64FC2; CvType.CV_64FC3; CvType.CV_64FC4; CvType.CV_USRTYPE1; // ? |
2.Mat的创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
private static void func4() { System.out.println("/**************** 创建方式4 ****************/"); Mat mat4 = Mat.zeros(1, 3, CvType.CV_8UC1); System.out.println("默认填充0的矩阵:" + mat4.dump()); Mat mat4_2 = Mat.ones(2, 3, CvType.CV_8UC1); System.out.println("默认填充1的矩阵:" + mat4_2.dump()); Mat mat4_3 = Mat.eye(3, 3, CvType.CV_8UC1); mat4_3.put(1, 2, 9); System.out.println("恒等大小和类型的矩阵:" + mat4_3.dump()); // 区别? } private static void func3() { System.out.println("/**************** 创建方式3 ****************/"); Mat mat3 = new Mat(2, 2, CvType.CV_8UC1, new Scalar(99)); // 全部元素都使用一个值 System.out.println(mat3.dump()); } private static void func2() { System.out.println("/**************** 创建方式2 ****************/"); byte[][] data = { {1, 2, 3}, // data[0] {4, 5, 6}, // data[1] {7, 8, 9} // data[2] }; byte[] bd = {11, 12, 13}; Mat mat2 = new Mat(3, 3, CvType.CV_8UC1); mat2.put(0, 0, data[0]); mat2.put(1, 0, new byte[]{6, 6, 6}); mat2.put(2, 0, bd); System.out.println(mat2.dump()); System.out.println("宽/列数:" + mat2.width()); // 同cols() System.out.println("高/行数:" + mat2.height()); // 同rows() } private static void func1() { System.out.println("/**************** 创建方式1 ****************/"); // 新建(3行,3列,CV_8U类型) Mat mat1 = new Mat(3, 3, CvType.CV_8U); mat1.put(0, 0, 1); // 行列索引始于0,在(0,0)第一行第一列放入一个值 mat1.put(0, 1, 2); // 正确的理解是,从(0,0)开始放入一个值,最后参数是个动态double数组 mat1.put(0, 2, 3); mat1.put(1, 0, 4, 5, 6, 11); // 按照行的长度,自动向后填充元素,多余的舍弃。 //mat1.put(1, 1, 5); //mat1.put(1, 2, 6); mat1.put(2, 0, 7); mat1.put(2, 1, 8); // mat1.put(2, 2, 9); // 根据构造方法第三个参数填充默认值0。 System.out.println("矩阵总行数:" + mat1.cols()); System.out.println("矩阵总列数:" + mat1.rows()); System.out.println("矩阵的尺寸:" + mat1.size()); System.out.println("矩阵元素总数:" + mat1.total()); System.out.println("矩阵元素一览:\n" + mat1.dump()); // 按矩阵的内部结构显示。左上角(0,0) System.out.println("矩阵[1][2]:" + Arrays.toString(mat1.get(1, 2))); // get方法返回一个double数组 mat1.create(2, 2, CvType.CV_8U); System.out.println("重构后的矩阵:\n" + mat1.dump()); } |
3.Mat的常用计算方法
1)常用计算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
Size size = new Size(2, 2); // org.opencv.core.Size(w, h) Mat mat5 = new Mat(); mat5.create(size, CvType.CV_32FC1); // 32FC1或64FC1 float[] data = {1f, 2f, 3f, 4f}; mat5.put(0, 0, data); System.out.println("/**************** 常用计算 ****************/"); System.out.println("原矩阵:\n" + mat5.dump()); Mat t = mat5.t(); System.out.println("\n转置矩阵:\n" + t.dump()); // 以左上角和右下角为轴翻转180度。 Mat t2 = new Mat(); Core.transpose(mat5, t2); System.out.println("\n转置矩阵:\n" + t2.dump()); Mat inv = mat5.inv(); // 要计算逆矩阵,则类型必须是CV_32F或CV_64F System.out.println("\n逆矩阵:\n" + inv.dump()); // Mat inv2 = new Mat(); Core.invert(mat5, inv2); System.out.println("\n逆矩阵:\n" + inv2.dump()); Mat reshape = mat5.reshape((int)mat5.total()); // (列)此时行默认为1,乘积与原total相同 System.out.println("\n转型为1行" + mat5.total() + "列:\n" + reshape.dump()); Mat reshape2 = mat5.reshape(1, 4); // (列,行)乘积须为原total System.out.println("\n转型为4行1列:\n" + reshape2.dump()); Mat pushback = new Mat(); pushback.push_back(mat5); System.out.println("\n追加数据后:\n" + pushback.dump()); pushback.push_back(inv); System.out.println("\n追加数据后:\n" + pushback.dump()); Mat clone = mat5.clone(); System.out.println("\n克隆的矩阵:\n" + clone.dump()); |
逆矩阵计算理解图:
2)加减乘除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
System.out.println("\n/**************** 加减乘除 ****************/"); Mat tmp = Mat.ones(2, 2, CvType.CV_32FC1); // 元素都为1 Mat target = new Mat(); Core.add(mat5, tmp, target); // (s1, s2, d)对应元素的加法 d[i] = s1[i] + s2[i] System.out.println("两个mat相加得:\n" + target.dump()); Core.scaleAdd(mat5, 2, tmp, target); // (s1, a, s2, d) d = s1 * a + s2 System.out.println("\n两个mat相加得:\n" + target.dump()); Core.subtract(mat5, tmp, target); // (s1, s2, d) d = s1 - s2 System.out.println("\n两个mat相减得:\n" + target.dump()); Core.subtract(mat5, tmp, target); // (s1, s2, d) d = s1 - s2 System.out.println("\n两个mat相减得:\n" + target.dump()); Core.gemm(mat5, tmp, 1, new Mat(), 0, target); // http://blog.csdn.net/dcrmg/article/details/52404580 System.out.println("\n两个mat点乘得:\n" + target.dump()); // 不是一般的相乘 target = mat5.mul(tmp); // s1[i][j] * s2[i][j] System.out.println("\n两个mat对乘得:\n" + target.dump()); Core.divide(mat5, Scalar.all(2), target); // (src1, scalar, dst) dst[i][j] = src1[i][j] / 2 System.out.println("\nmat除以2得:\n" + target.dump()); Core.divide(mat5, tmp, target); // (src1, src2, dst) dst[i][j] = src1[i][j] / src2[i][j] System.out.println("\n两个mat相除得:\n" + target.dump()); Mat mask = new Mat(2,2,CvType.CV_8UC1); // 遮罩的类型须8UC1或8SC1。注意size mask.put(0, 0, 0); // 只有0和非0的区别 mask.put(0, 1, 0); // 0表示此坐标元素不进行计算 mask.put(1, 0, 1); mask.put(1, 1, 1); target = new Mat(); Core.add(mat5, tmp, target, mask); System.out.println("\n两个mat相加,经过遮罩运算:\n" + target.dump()); |
点乘理解图:
3)线性代数计算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
System.out.println("\n/**************** 线性代数 ****************/"); Scalar trace = Core.trace(mat5); // n×n矩阵的主对角线(从左上角到右下方角)上元素的总和被称为矩阵的迹 System.out.println("trace操作:" + trace.toString()); // trace.val[0] Mat eigenvalues = new Mat(); Mat eigenctors = new Mat(); Core.eigen(mat5, eigenvalues, eigenctors); System.out.println("\n矩阵的特征值:\n" + eigenvalues.dump()); System.out.println("矩阵的特征向量:\n" + eigenctors.dump()); Mat covar = new Mat(2, 2, CvType.CV_32FC1); Mat mean = new Mat(2, 2, CvType.CV_32FC1); Core.calcCovarMatrix(mat5, covar, mean, Core.COVAR_ROWS | Core.COVAR_NORMAL, CvType.CV_32FC1);//(samples, covar, mean, flags, ctype) System.out.println("\n矩阵的协方差矩阵:\n" + covar.dump()); System.out.println("矩阵的均值矩阵:\n" + mean.dump()); // flags: // Core.COVAR_ROWS:以行为主 // Core.COVAR_COLS:以列为主 // Core.COVAR_NORMAL:计算协方差和均值 // Core.COVAR_SCALE:协方差矩阵可以缩放 // Core.COVAR_USE_AVG:需使用平均值 // Core.COVAR_SCRAMBLED:快速计算 Mat dst = new Mat(); Core.compare(mat5, tmp, dst, Core.CMP_GT); // (src1, src2, dst, cmpop) System.out.println("\n两个矩阵比较:s1是否大于s2:\n" + dst.dump()); // int result = s1[i][j] > s2[i][j] ? 255 : 0 ; Core.compare(mat5, tmp, dst, Core.CMP_GE); System.out.println("两个矩阵比较:s1是否大于等于s2:\n" + dst.dump()); // int result = s1[i][j] >= s2[i][j] ? 255 : 0 ; Core.compare(mat5, tmp, dst, Core.CMP_NE); System.out.println("两个矩阵比较:s1是否不等于s2:\n" + dst.dump()); // int result = s1[i][j] <> s2[i][j] ? 255 : 0 ; // compop: // Core.CMP_GT:大于 // Core.CMP_LT:小于 // Core.CMP_GE:大于等于 // Core.CMP_LE:小于等于 // Core.CMP_EQ:相等 // Core.CMP_NE:不相等 |
4)统计相关计算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
System.out.println("\n/**************** 统计计算 ****************/"); Mat v1 = new Mat(); Mat v2 = new Mat(); Mat v3 = new Mat(); Mat v4 = new Mat(); Core.reduce(mat5, v1, 0, Core.REDUCE_SUM, CvType.CV_64FC1); // (src, dst, dim, rtype, dtype) Core.reduce(mat5, v2, 0, Core.REDUCE_AVG); // dtype的类型如果指定,需大于src的类型 Core.reduce(mat5, v3, 0, Core.REDUCE_MAX); // SUM:求列的和,AVG:列的平均值,MAX:列最大值,MIN:列最小值 Core.reduce(mat5, v4, 0, Core.REDUCE_MIN); // System.out.println("矩阵的“列”元素和的总和值:\n" + v1.dump()); System.out.println("矩阵的“列”元素和的平均值:\n" + v2.dump()); System.out.println("矩阵的“列”元素和的最大值:\n" + v3.dump()); System.out.println("矩阵的“列”元素和的最小值:\n" + v4.dump()); Mat sort1 = new Mat(); Mat sort2 = new Mat(); Mat sort3 = new Mat(); Mat sort4 = new Mat(); Core.sort(mat5, sort1, Core.SORT_ASCENDING); // 升序(默认),基于行(默认) //Core.sort(mat5, sort1, Core.SORT_ASCENDING | Core.SORT_EVERY_ROW); // 降序基于行 Core.sort(mat5, sort2, Core.SORT_DESCENDING); // 降序基于行 //Core.sort(mat5, sort2, Core.SORT_DESCENDING | Core.SORT_EVERY_ROW); // 降序基于行 Core.sort(mat5, sort3, Core.SORT_ASCENDING | Core.SORT_EVERY_COLUMN); // 升序,基于列 Core.sort(mat5, sort4, Core.SORT_DESCENDING | Core.SORT_EVERY_COLUMN); // 降序,基于列 System.out.println("\n矩阵基于行升序排序:\n" + sort1.dump()); // 每行左小右大 System.out.println("矩阵基于行降序排序:\n" + sort2.dump()); // 每行左大右小 System.out.println("矩阵基于列降序排序:\n" + sort3.dump()); // 每列上小下大 System.out.println("矩阵基于列降序排序:\n" + sort4.dump()); // 每列上大下小 float[] dataref = {8f, 2f, 1f, 7f}; Mat reference = new Mat(); reference.create(2, 2, CvType.CV_32FC1); reference.put(0, 0, dataref); Mat max = new Mat(); Mat min = new Mat(); Core.max(mat5, reference, max); // (src1, src2, dst),dst[i][j] = src1[i][j] > src2[i][j] ? src1[i][j] : src2[i][j] Core.min(mat5, reference, min); // dst[i][j] = src1[i][j] < src2[i][j] ? src1[i][j] : src2[i][j] System.out.println("\n两矩阵元素的最大元素:\n" + max.dump()); System.out.println("两矩阵元素的最小元素:\n" + min.dump()); MatOfDouble mean2 = new MatOfDouble(); MatOfDouble stddev = new MatOfDouble(); Core.meanStdDev(mat5, mean2, stddev); System.out.println("\n矩阵的均值:\n" + mean2.dump()); // mean2.get(0,0)[0]。全部元素和的平均值 System.out.println("矩阵的标准差:\n" + stddev.dump()); // stddev.get(0,0)[0]。方差是各个数据与平均数之差的平方的平均数。方差的算术平方根叫标准差 Scalar sumElems = Core.sumElems(mat5); System.out.println("矩阵的元素总和:" + sumElems.toString()); // sumElems.val[0] int countNonZero = Core.countNonZero(mat5); System.out.println("矩阵的非零元素个数:" + countNonZero); MinMaxLocResult minMaxLoc = Core.minMaxLoc(mat5); System.out.println("矩阵的中最大元素:" + minMaxLoc.maxVal + ",最小元素:" + minMaxLoc.minVal); double norm = Core.norm(mat5); // ((全部元素的平方)的和)的平方根 System.out.println("矩阵的基本范数:" + norm); Mat randu = new Mat(3, 3, CvType.CV_32FC1); Core.randu(randu, 10, 20); System.out.println("新建3x3(元素随机均匀取值10~20)的矩阵:\n" + randu.dump()); Mat randn = new Mat(3, 3, CvType.CV_32FC1); Core.randn(randn, 11, 3); System.out.println("新建3x3(平均值11,标准差3)的常态分布矩阵:\n" + randn.dump()); |
5)矩阵运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
float[] data = { 1, 2, 3, 4 }; Mat mat6 = new Mat(new Size(2, 2), CvType.CV_32FC1); mat6.put(0, 0, data); float[] refdata = { 8, 8, 8, 8 }; Mat reference = new Mat(new Size(2, 2), CvType.CV_32FC1); reference.put(0, 0, refdata); System.out.println("/**************** 矩阵运算 ****************/"); System.out.println("原矩阵:\n" + mat6.dump()); System.out.println("参照矩阵:\n" + reference.dump()); Mat diff = new Mat(); Core.absdiff(mat6, reference, diff); // Math.abs( src1[i][j] - src2[i][j] ) System.out.println("\n矩阵元素差的绝对值:\n" + diff.dump()); Mat weighted = new Mat(); // (s1, a, s2, b, g, d) Core.addWeighted(mat6, 2, reference, 3, 4, weighted); // d[i][j] = s1[i][j]*a + s2[i][j]*b + g System.out.println("\n两个矩阵有权重相加:\n" + weighted.dump()); Mat wiseand = new Mat(); Core.bitwise_and(mat6, reference, wiseand); // 矩阵的对应元素进行二进制“且”运算 System.out.println("\n两个矩阵且运算:\n" + wiseand.dump()); Mat wiseor = new Mat(); Core.bitwise_or(mat6, reference, wiseor); // 或 System.out.println("两个矩阵或运算:\n" + wiseor.dump()); Mat wisenot = new Mat(); Core.bitwise_not(mat6, reference, wisenot); // 非 System.out.println("两个矩阵非运算:\n" + wisenot.dump()); Mat wisenxor = new Mat(); Core.bitwise_xor(mat6, reference, wisenxor); // 异或 System.out.println("两个矩阵异或运算:\n" + wisenxor.dump()); int root = 64; float cubeRoot = Core.cubeRoot(root); // 立方根 System.out.println("\n" + root + "的立方根是:" + cubeRoot); Mat exp = new Mat(); Core.exp(mat6, exp); System.out.println("\n矩阵元素的指数:\n" + exp.dump()); Mat log = new Mat(); Core.log(mat6, log); System.out.println("\n矩阵元素的自然对数:\n" + log.dump()); Mat isInRange = new Mat(); Scalar lower = new Scalar(2); Scalar up = new Scalar(3); Core.inRange(mat6, lower, up, isInRange); System.out.println("\n矩阵的元素是否存在于2-3区间:\n" + isInRange.dump()); // 255是,0否。 Mat normailized_l1 = new Mat(); Mat normailized_l2 = new Mat(); Mat normailized_inf = new Mat(); Mat normailized_minmax = new Mat(); Core.normalize(mat6, normailized_l1, 1, 1, Core.NORM_L1); // (src, dst, a, b, type) Core.normalize(mat6, normailized_l2, 1, 1, Core.NORM_L2); Core.normalize(mat6, normailized_inf, 1, 1, Core.NORM_INF); Core.normalize(mat6, normailized_minmax, 1, 1, Core.NORM_MINMAX); System.out.println("\n矩阵L1归一化:\n" + normailized_l1.dump()); System.out.println("矩阵L2归一化:\n" + normailized_l2.dump()); System.out.println("矩阵INF归一化:\n" + normailized_inf.dump()); System.out.println("矩阵MM归一化:\n" + normailized_minmax.dump()); Mat sqrt = new Mat(); Core.sqrt(mat6, sqrt); System.out.println("\n矩阵每元素的平方根:\n" + sqrt.dump()); float[] vd1 = {1, 3, 6, 10}; float[] vd2 = {1, 4, 8, 10}; Mat x = new Mat(1, 4, CvType.CV_32FC1); Mat y = new Mat(1, 4, CvType.CV_32FC1); x.put(0, 0, vd1); y.put(0, 0, vd2); Mat m = new Mat(); Mat a = new Mat(); Core.cartToPolar(x, y, m, a); System.out.println("\n2D矩阵向量长度:\n" + m.dump()); System.out.println("2D矩阵向量角度:\n" + a.dump()); Core.polarToCart(m, a, x, y); System.out.println("\n根据向量长度和角度反推原矩阵x:\n" + x.dump()); System.out.println("根据向量长度和角度反推原矩阵y:\n" + y.dump()); |
api参考 http://blog.csdn.net/zwlq1314521/article/details/45038271
声明
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/2222.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设