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() 
)

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

参数说明

参数英文说明笔者翻译及说明
srcinput array.输入矩阵
dstoutput 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_typenormalization 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)
maskoptional 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
OriginalNORM_L1NORM_L2NORM_INFNORM_MINMAX
2.00 0.0606060610.1257389230.20
6.00 0.1818181820.3772167680.60.5
7.00 0.2121212120.4400862290.70.625
8.00 0.2424242420.5029556910.80.75
10.00 0.3030303030.62869461311

 

alpha=3, beta=7
OriginalNORM_L1NORM_L2NORM_INFNORM_MINMAX
2.00 0.1818181820.3772167680.63
6.00 0.5454545451.1316503041.85
7.00 0.6363636361.3202586882.15.5
8.00 0.7272727271.5088670722.46
10.00 0.9090909091.8860838437

 

alpha=5, beta=100
OriginalNORM_L1NORM_L2NORM_INFNORM_MINMAX
2.00 0.303030.62869515
6.00 0.9090911.88608352.5
7.00 1.060612.200433.564.375
8.00 1.212122.51478476.25
10.00 1.515153.143475100

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按需求设定。

  • 14
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值