OpenCV中矩阵归一化函数normalize()的原理讲解及公式 C++/Python代码实例

Table of Contents

函数原型

参数说明

不同norm_type下的计算公式

NORM_L1

NORM_L2

NORM_INF

NORM_MINMAX

参考文章

代码实例

代码输出

Python代码使用normalize

图像输出

笔者备注


函数原型

void cv::normalize    (    InputArray     src,
InputOutputArray     dst,
double     alpha = 1,
double     beta = 0,
int     norm_type = NORM_L2,
int     dtype = -1,
InputArray     mask = noArray() 
)

笔者说明:这个函数的作用就是把需要处理的数据通过某种算法限制在你需要的一定范围内。

参数说明

参数 英文说明 笔者翻译及说明
src input array. 输入矩阵
dst output array of the same size as src . 输出矩阵,与输入矩阵尺寸相同
alpha

norm value to normalize to or the lower 

range boundary in case of the range normalization.

如果norm_type为NORM_MINMAX ,则alpha为最小值或最大值;如果norm_type为其他类型,则为归一化要乘的系数【重点】
beta

upper range boundary in case of the range

 normalization; it is not used for the norm normalization.

如果norm_type为NORM_MINMAX ,则beta为最小值或最大值;如果norm_type为其他类型,beta被忽略,此处不会被用到,一般传入0【重点】
norm_type normalization type (see cv::NormTypes). 归一化类型,常见的有NORM_L1, NORM_L2, NORM_INF, NORM_MINMAX
dtype

when negative, the output array has the same type as src;

 otherwise, it has the same number of channels as src

 and the depth =CV_MAT_DEPTH(dtype).

如果取负值时,dst与src同样的类型;否则,dst和src有同样的通道数,且此时图像深度为CV_MAT_DEPTH(dtype)
mask optional operation mask. 可选操作掩膜

不同norm_type下的计算公式

以数列{ 2.0, 6.0, 7.0, 8.0, 10.0 }为例, alpha=5, beta=100

NORM_L1

1.先求出norm

公式:L1_norm = ∥src1∥L1=∑I|src1(I)|,即各数的绝对值之和

norm = |2.0| + |6.0| + |7.0| + |8.0| + |10.0| = 33

2. 再求dst

公式:dst = alpha*src/L1_norm

dst[0] = 5 * 2.0/ 33 = 0.303

剩下的以此类推,具体结果请参考最后的代码输出表格。

NORM_L2

1.先求出norm

公式:L2_norm = 矩阵中各元素的平方和的开方(欧几里德)(L2-范数)

2. 再求dst

公式:dst = alpha*src/L2_norm

dst[0] = 5 * 2.0/ 15.906 = 0.629

剩下的以此类推,具体结果请参考最后的代码输出表格。


NORM_INF

1.先求出norm

INF_norm = 矩阵中所有元素的最大值max

以上数列中 max = 10
PS: 图片处理时可以使用函数 void minMaxLoc(...);求出
2. 再求dst

公式:dst = alpha*src/INF_norm

dst[0] = 5 * 2.0/ 10 = 1

剩下的以此类推,具体结果请参考最后的代码输出表格。


NORM_MINMAX

1. alpha、beta分别为归一化后的最小值、最大值
    函数会自动判断哪个为最大值,最小值

2. 再求dst

公式如下:

b = max(alpha, beta)
a = min(alpha, beta)

alpha=5, beta=100

b = max(alpha, beta) = 100

a = min(alpha, beta) = 5

dst[0] = (100-5) * (2-2)/ (10-2) +5 = 2

dst[1] = (100-5) * (6-2)/ (10-2) +5 = 52.5

剩下的以此类推,具体结果请参考最后的代码输出表格。

参考文章

https://docs.opencv.org/3.2.0/d2/de8/group__core__array.html#ga87eef7ee3970f86906d69a92cbf064bd

代码实例

#include <opencv2/opencv.hpp>  //头文件
#include <iostream>
using namespace cv;  //包含cv命名空间
using namespace std;

int main(int argc, char ** argv)
{
	
	vector<double> positiveData = { 2.0, 6.0, 7.0, 8.0, 10.0 };
	vector<double> normalizedData_l1, normalizedData_l2, normalizedData_inf, normalizedData_minmax;
	// Norm to probability (total count)
	// sum(numbers) = 23.0	
	normalize(positiveData, normalizedData_l1, 5.0, 100.0, NORM_L1);
	cout <<"*normalizedData_l1*:" << endl;
	//method#1 C operatator[] - FASTEST
	//cout << "\n*C operatator[]*:" << endl;
	for (size_t i = 0; i < normalizedData_l1.size(); i++)
	{
		cout << normalizedData_l1[i] << ",\t";
	}

	//method#2 C iterator  - 2nd fast
	//cout << "*iterator*:" << endl;
	//for (vector<double>::iterator pd= normalizedData_l1.begin(); pd != normalizedData_l1.end();pd++)
	//{
	//	cout << *pd << "\t";
	//}	

	//method#3 at -- 3rd fast
	//cout << "\n*at*:" << endl;
	//for (size_t i = 0; i < normalizedData_l1.size(); i++)
	//{
	//	cout << normalizedData_l1.at(i)<< ",\t";
	//}

	// Norm to unit vector: ||positiveData|| = 1.0
	normalize(positiveData, normalizedData_l2, 5.0, 100.0, NORM_L2);
	cout << "\n*normalizedData_l2*:" << endl;
	for (size_t i = 0; i < normalizedData_l2.size(); i++)
	{
		cout << normalizedData_l2[i] << ",\t";
	}

	// Norm to max element
	normalize(positiveData, normalizedData_inf, 5.0, 100.0, NORM_INF);
	cout << "\n*normalizedData_inf*:" << endl;
	for (size_t i = 0; i < normalizedData_inf.size(); i++)
	{
		cout << normalizedData_inf[i] << ",\t";
	}

	// Norm to range [5.0;100.0]
	// 2.0      0.0     (shift to left border)
	// 8.0      0.75    (6.0/8.0)
	// 10.0     1.0     (shift to right border)
	normalize(positiveData, normalizedData_minmax, 5.0, 100.0, NORM_MINMAX);
	cout << "\n*normalizedData_minmax*:" << endl;
	for (size_t i = 0; i < normalizedData_inf.size(); i++)
	{
		cout << normalizedData_minmax[i] << ",\t";
	}
	cout <<  endl;

	// 【3】等待任意按键按下
	waitKey(0);
	return 0;
}

代码输出

我对alpha, beta取了三种情况,输出结果如下:

alpha=1, beta=0
Original NORM_L1 NORM_L2 NORM_INF NORM_MINMAX
2.00  0.060606061 0.125738923 0.2 0
6.00  0.181818182 0.377216768 0.6 0.5
7.00  0.212121212 0.440086229 0.7 0.625
8.00  0.242424242 0.502955691 0.8 0.75
10.00  0.303030303 0.628694613 1 1
alpha=3, beta=7
Original NORM_L1 NORM_L2 NORM_INF NORM_MINMAX
2.00  0.181818182 0.377216768 0.6 3
6.00  0.545454545 1.131650304 1.8 5
7.00  0.636363636 1.320258688 2.1 5.5
8.00  0.727272727 1.508867072 2.4 6
10.00  0.909090909 1.88608384 3 7
alpha=5, beta=100
Original NORM_L1 NORM_L2 NORM_INF NORM_MINMAX
2.00  0.30303 0.628695 1 5
6.00  0.909091 1.88608 3 52.5
7.00  1.06061 2.20043 3.5 64.375
8.00  1.21212 2.51478 4 76.25
10.00  1.51515 3.14347 5 100

Python代码使用normalize

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import cv2
import sys

if __name__ == '__main__':
    if len(sys.argv) > 1:
        src = cv2.imread(sys.argv[1], cv2.IMREAD_ANYCOLOR)
    else:
        print("Usage:python normalize.py imageFile")

    cv2.imshow("src", src)    # 显示图片
    # 直方图归一化/正规化
    # 方法一:
    # dst = cv2.normalize(src, src, 0, 255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
    # 方法二:
    dst = cv2.normalize(src, None, 0, 255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
    cv2.imshow("dst", dst)    # 显示图片
    cv2.waitKey(0)  # 等待用户输入,按任意键即可

图像输出

可以看出输出图像比原来的对比度有增强

笔者备注

如果选择NORM_MINMAX类型,通常将alpha设定为最小值,将beta设定为最大值。

比如,需要将数据范围限定在[0, 400],可以这么使用

normalize(src, dst, 0, 400.0, NORM_MINMAX);

如果选择其他三种类型,beta设定为0,alpha按需求设定。

发布了85 篇原创文章 · 获赞 82 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/yl_best/article/details/89000431