OpenCV像素值归一化

匆匆过客 提交于 2019-12-08 02:29:11

像素值归一化就是要把图片像素值数据经过某种算法限制在需要的一定范围内。归一化可以使没有可比性的数据变得具有可比性,同时保持相比较的数据之间的相对关系。OpenCV提供了四种图片像素归一化的方法:

  • L1归一化 : NORM_L1
  • L2归一化 : NORM_L2
  • INF归一化 : NORM_INF
  • MINMAX归一化 : NORM_MINMAX(最常用)

使用的API是normalize():

void normalize( InputArray src, //输入图片
				InputOutputArray dst, //输出图片
				double alpha = 1, //norm_type = NORM_MINMAX时下限
				double beta = 0,//norm_type = NORM_MINMAX时上限,norm_type = NORM_INF时最大值
                int norm_type = NORM_L2,
                int dtype = -1, //输出type与输入type相同
                InputArray mask = noArray()
                );

下面以20,80,100三个像素值为例解释OpenCV中四种归一化的计算方法,由于归一化后为小数,因此将20,80,100转换成浮点型20.0,80.0,100.0以减小精度丢失。

1.L1归一化:NORM_L1

L1归一化依据所有像素值之和,用原始像素值除以所有像素值之和即为原始像素值归一化后的值。
例如对于20.0,80.0,100.0三个像素值,它们的和为
20.0+80.0+100.0=200.020.0+80.0+100.0=200.0
20.0/200.0=0.120.0/200.0 = 0.1
80.0/200.0=0.480.0/200.0 = 0.4
100.0/200.0=0.5100.0/200.0 = 0.5
所以20.0,80.0,100.0经过L1归一化后的值分别为0.1,0.4,0.5


2.L2归一化:NORM_L2

L2归一化依据于原始像素值组成的单位向量,用原始像素值除以所有原始像素值平方值之和的平方根即为原始像素值归一化后的值。
例如对于20.0,80.0,100.0三个像素值,它们的平方和为:
20.020.0+80.080.0+100.0100.0=16800.020.0*20.0+80.0*80.0+100.0*100.0=16800.0
开平方得129.61。

20.0/129.61=0.15420.0/129.61=0.154
80.0/129.61=0.61780.0/129.61=0.617
100.0/129.61=0.772100.0/129.61=0.772
所以20.0,80.0,100.0经过L2归一化后的值分别为0.154,0.617,0.772


3.INF归一化:NORM_INF

INF归一化依据于最大值,用原始像素值除以所有原始像素值中的最大值即为原始像素值归一化后的值。
例如对于20.0,80.0,100.0三个像素值,它们的最大值为100.0,则
20.0/100.0=0.220.0/100.0=0.2
80.0/100.0=0.880.0/100.0=0.8
100.0/100.0=1.0100.0/100.0=1.0
所以20.0,80.0,100.0经过INF归一化后的值分别为0.2,0.8,1.0


4.MINMAX归一化:NORM_MINMAX

INF归一化依据于最大值与最小值的差值(记为delta),用原始像素值除以所有原始像素值中的最大值即为原始像素值归一化后的值。
例如对于20.0,80.0,100.0三个像素值,它们的最小值minmin20.0,最大值maxmax100.0,则
delta=maxmin=100.020.0=80.0delta=max-min=100.0-20.0=80.0

所以
(20.0min)/delta=(20.020.0)/80.0=0.0(20.0-min)/delta=(20.0-20.0)/80.0=0.0
(80.0min)/delta=(80.020.0)/80.0=0.75(80.0-min)/delta=(80.0-20.0)/80.0=0.75
(100.0min)/delta=(100.020.0)/80.0=1.0(100.0-min)/delta=(100.0-20.0)/80.0=1.0
所以20.0,80.0,100.0经过MINMAX归一化后的值分别为0.0,0.75,1.0


代码实现:

	vector<double>a = {20,80,100};
	vector<double>a1(3);
	vector<double>a2(3);
	vector<double>a3(3);
	vector<double>a4(3);
	cv::normalize(a, a1, 1, 0, NORM_L1);
	cv::normalize(a, a2, 1, 0, NORM_L2);
	cv::normalize(a, a3, 1, 0, NORM_INF);
	cv::normalize(a, a4, 1, 0, NORM_MINMAX);

结果:
result

5.完整代码

#include<opencv2/opencv.hpp>
#include<iostream>
#include<Windows.h>

using namespace cv;
using namespace std;

int main(int argc, char**argv)
{
#if 0
	//get gray input image
	Mat gray_input_image = imread("./whisper.jpg", 0);
	if (gray_input_image.empty())
	{
		cout << "read input error!" << endl;
		return -1;
	}
	imshow("gary_input", gray_input_image);

	//转为32位浮点型
	gray_input_image.convertTo(gray_input_image, CV_32F);

	Mat result = Mat::zeros(gray_input_image.size(), CV_32FC1);
	normalize(gray_input_image, result, 1.0, 0.0, NORM_MINMAX);
	result = result * 255;
	result.convertTo(result, CV_8UC1);
	imshow("result", result);

	waitKey(0);
	destroyAllWindows();
#endif 

	vector<double>a = {20,80,100};
	vector<double>a1(3);
	vector<double>a2(3);
	vector<double>a3(3);
	vector<double>a4(3);
	cv::normalize(a, a1, 1, 0, NORM_L1);
	cv::normalize(a, a2, 1, 0, NORM_L2);
	cv::normalize(a, a3, 1, 0, NORM_INF);
	cv::normalize(a, a4, 1, 0, NORM_MINMAX);

	cout << "L1 normal:" << endl;
	for (int i = 0; i < a.size(); i++){
		cout << a1[i]<<" ";
	}
	cout << endl;

	cout << "L2 normal:" << endl;
	for (int i = 0; i < a.size(); i++){
		cout << a2[i] << " ";
	}
	cout << endl;

	cout << "INF normal:" << endl;
	for (int i = 0; i < a.size(); i++){
		cout << a3[i] << " ";
	}
	cout << endl;

	cout << "MINMAX normal:" << endl;
	for (int i = 0; i < a.size(); i++){
		cout << a4[i] << " ";
	}
	cout << endl;

	system("pause");
	return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!