在opencv 里面 norm 这个函数是求解范数
在我的上一篇的博客中对范数做了一个简单的介绍,如果求解向量的范数和矩阵的范数
https://blog.csdn.net/datouniao1/article/details/109055343
norm(src1,normType )
我们来看opencv 中norm 这个函数,首先我们进行简单的计算
src 为输入的矩阵
normType 为范数的类型 默认的是L2 范数
NORM_INF、NORM_L1、NORM_L2、NORM_L2SQR、NORM_HAMMING、NORM_HAMMING2,其中NORM_L2SQR是2-范数的平方;NORM_HAMMING就是汉明距离,简单的讲就是一个数中非零的位的个数;而NORM_HAMMING2与NORM_HAMMING的区别在于,它使用一个表来映射不同的uchar值表示的汉明距离大小
// Core.NORM_INF 绝对值最大
// Core.NORM_L1 绝对值值和
// Core.NORM_L2 绝对值平方和开方
Mat mat=new Mat(new Size(3,1),CvType.CV_8UC1);
mat.put(0, 0, 1,2,3);
System.out.println(mat.dump());
double d=Core.norm(mat);
System.out.println(d);
创建一个最为简单的矩阵
[1,2,3]
上面使用的是默认的L2的范数,我们看到其实这个是一个向量
利用这个公式: (1^2+2^2+2^3)^(1/2)=sqrt(14)=3.7
3.7416573867739413
我们验证一下:
Math.sqrt(14)=3.7416573867739413
可见norm这个函数就是求解矩阵的范数
NormType为范数的类型,比如我们求上面上相的1范数
Mat mat=new Mat(new Size(3,1),CvType.CV_8UC1);
mat.put(0, 0, 1,2,3);
System.out.println(mat.dump());
double d=Core.norm(mat,Core.NORM_L1);
System.out.println(d);
这个就是求解L1范数,我们来看范数的计算公式:
向量的1-范数: ; 各个元素的绝对值之和;
输出结果:
[ 1, 2, 3]
6.0
上面的矩阵都是1维的,我们创建一个二维的矩阵继续来看norm这个函数
Mat mat=new Mat(new Size(3,2),CvType.CV_8UC1);
mat.put(0, 0, 1,2,3);
mat.put(1, 0, 2,2,3);
System.out.println(mat.dump());
double d=Core.norm(mat,Core.NORM_L1);
但是Core.NORM_L1 所表示的是矩阵所有元素绝对值之和
Mat mat=new Mat(new Size(3,3),CvType.CV_8UC1);
mat.put(0, 0, 1,2,3);
mat.put(1, 0, 2,2,3);
mat.put(2, 0, 2,2,4);
System.out.println(mat.dump());
double d=Core.norm(mat,Core.NORM_L1);
System.out.println("计算结果:"+d);
[ 1, 2, 3;
2, 2, 3;
2, 2, 4]
21.0
[ 1, 2, -3;
2, 2, 3;
2, 2, 4]
计算结果:21.0
Mat mat=new Mat(new Size(3,3),CvType.CV_8SC1);
mat.put(0, 0, 1,2,-3);
mat.put(1, 0, 2,2,3);
mat.put(2, 0, 2,2,4);
System.out.println(mat.dump());
double d=Core.norm(mat,Core.NORM_L2);
System.out.println("计算结果:"+d);
Core.NORM_L2 计算出来的结果是所有元素的平方和然后求平方根
[ 1, 2, -3;
2, 2, 3;
2, 2, 4]
计算结果:7.416198487095663
Core.norm(mat, mat2);
其实是求出 Core.norm(mat,Core.NORM_L1)-Core.norm(mat2,Core.NORM_L1) 得到的结果就绝对值
Mat mat=new Mat(new Size(3,3),CvType.CV_8SC1);
mat.put(0, 0, 1,2,3);
mat.put(1, 0, 2,2,3);
mat.put(2, 0, 2,2,4);
System.out.println(mat.dump());
double d=Core.norm(mat,Core.NORM_L1);
System.out.println("计算结果:"+d);
Mat mat2=new Mat(new Size(3,3),CvType.CV_8SC1);
mat2.put(0, 0, 1,2,8);
mat2.put(1, 0, 2,2,3);
mat2.put(2, 0, 2,2,4);
double d2=Core.norm(mat2,Core.NORM_L1);
System.out.println("计算结果:"+d2);
double ds=Core.norm(mat, mat2);
System.out.println("计算结果:"+ds);
[ 1, 2, 3;
2, 2, 3;
2, 2, 4]
计算结果:21.0
[ 1, 2, 8;
2, 2, 3;
2, 2, 4]
计算结果:26.0
计算结果:5.0
Core.norm(mat, mat2,Core.NORM_L1);
Core.norm(mat, mat2,Core.NORM_L2);
计算出来的结果都是:其实是求出 Core.norm(mat,Core.NORM_L1)-Core.norm(mat2,Core.NORM_L1) 得到的结果就绝对值
Mask
之前的操作一直在回避掩码,
double ss=Core.norm(mat, Core.NORM_L1, mask);
但是这个函数中正好也用到了掩码mask 那么我们不妨简单的研究一下
mask 具有这样的特征,和输入的图像src具有相同的大小,而且是8UC1
掩码是一种选择性的计算
Core.norm(mat, Core.NORM_L1)默认的是计算mat中所有的元素的绝对值之和,此时我们mask可以看成是NULL
[ 1, 2, 3;
2, 2, 3;
2, 2, 4]
比如上面的矩阵,我们计算出的结果是Core.norm(mat, Core.NORM_L1)=21,
引入掩码:
我们先创建一个mask 需要和src具有同样大小,而且为8UC1
Mat mask=new Mat(mat.size(),CvType.CV_8UC1);
mask.put(0, 0, 0,0,0);
mask.put(1, 0, 0,0,0);
mask.put(2, 0, 0,0,0);
mask=
[ 0, 0, 0;
0, 0, 0;
0, 0, 0]
此时我们的计算结果:
double ss=Core.norm(mat, Core.NORM_L1,mask);
mat: [ 1, 2, 3; mask:[ 0, 0, 0;
2, 2, 3; 0, 0, 0;
2, 2, 4] 0, 0, 0]
输出结果为:0.0
mat: [ 1, 2, 3; mask:[ 1, 1, 1;
2, 2, 3; 1, 1, 1;
2, 2, 4] 1, 1, 1]
输出结果为:21
mat: [ 1, 2, 3; mask:[ 1, 1, 1;
2, 2, 3; 0, 0, 1;
2, 2, 4] 1, 0, 1]
在这个地方我们大概可以看出来,当我们进行范数计算的时候,输入对象如果对应掩码中的数值非零的时候参与计算,是0的时候值为0
其实我们最后最后计算的结果为:
[ 1, 2 3;
0, 0, 3;
1, 0, 4]
根据掩码的特征,我们在处理图像的时候可以选择性的计算一些数值,当然这些需要我们队opencv相关的函数很熟悉了之后可以进行的操作
上面就是opencv的norm函数的一个基本用法,
希望对你有所帮助