07_OpenCV图像翻转、Resize、像素值归一化
1.图像翻转
图像翻转的本质就是像素值的映射,OpenCV
提供了API flip
来翻转图像,有三种翻转方式:
void flip(InputArray src, //输入
OutputArray dst, //输出
int flipCode);//旋转方式
代码实践:
Mat result_x, result_y, result_xy;
//沿x轴翻转
flip(input_image, result_x, 0);
imshow("result_x", result_x);
//沿y轴翻转
flip(input_image, result_y, 1);
imshow("result_y", result_y);
//沿xy对角线翻转
flip(input_image, result_xy, -1);
imshow("result_xy", result_xy);
结果:
2.图像Resize
图像插值是从图像低分辨率图像生成高分辨率图像的过程中插值以恢复图像中所丢失的信息,即补全图像放缩所丢失的信息。
常见的四种插值方法:
- 近邻插值:
INTER_NEAREST
- 线性插值:
INTER_LINEAR
- 立方插值:
INTER_CUBIC
- 卢卡斯插值:
INTER_LANCZOS
OpenCV
提供了resize()
:
void resize( InputArray src, OutputArray dst,
Size dsize, double fx = 0, double fy = 0,
int interpolation = INTER_LINEAR );
代码实践:
int height = input_image.rows;
int width = input_image.cols;
float fx = 0.0, fy = 0.0;
Mat result = Mat::zeros(input_image.size(), input_image.type());
resize(input_image, result, Size(width * 2, height * 2), fx = 0, fy = 0, INTER_NEAREST);
imshow("INTER_NEAREST", result);
resize(input_image, result, Size(width * 2, height * 2), fx = 0, fy = 0, INTER_LINEAR);
imshow("INTER_LINEAR", result);
resize(input_image, result, Size(width * 2, height * 2), fx = 0, fy = 0, INTER_CUBIC);
imshow("INTER_CUBIC", result);
resize(input_image, result, Size(width * 2, height * 2), fx = 0, fy = 0, INTER_LANCZOS4);
imshow("INTER_LANCZOS4", result);
3.图像像素值归一化
像素值归一化就是要把图片像素值数据经过某种算法限制在需要的一定范围内。归一化可以使没有可比性的数据变得具有可比性,同时保持相比较的数据之间的相对关系。
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以减小精度丢失。
3.1 L1归一化:NORM_L1
L1归一化依据所有像素值之和,用原始像素值除以所有像素值之和即为原始像素值归一化后的值。
例如对于20.0,80.0,100.0三个像素值,它们的和为
20.0
+
80.0
+
100.0
=
200.0
20.0+80.0+100.0=200.0
20.0+80.0+100.0=200.0则
20.0
/
200.0
=
0.1
20.0/200.0 = 0.1
20.0/200.0=0.1
80.0
/
200.0
=
0.4
80.0/200.0 = 0.4
80.0/200.0=0.4
100.0
/
200.0
=
0.5
100.0/200.0 = 0.5
100.0/200.0=0.5
所以20.0,80.0,100.0经过L1归一化后的值分别为0.1,0.4,0.5。
3.2 L2归一化: NORM_L2
L2归一化依据于原始像素值组成的单位向量,用原始像素值除以所有原始像素值平方值之和的平方根即为原始像素值归一化后的值。
例如对于20.0,80.0,100.0三个像素值,它们的平方和为:
20.0
∗
20.0
+
80.0
∗
80.0
+
100.0
∗
100.0
=
16800.0
20.0*20.0+80.0*80.0+100.0*100.0=16800.0
20.0∗20.0+80.0∗80.0+100.0∗100.0=16800.0
开平方得129.61。
则
20.0
/
129.61
=
0.154
20.0/129.61=0.154
20.0/129.61=0.154
80.0
/
129.61
=
0.617
80.0/129.61=0.617
80.0/129.61=0.617
100.0
/
129.61
=
0.772
100.0/129.61=0.772
100.0/129.61=0.772
所以20.0,80.0,100.0经过L2归一化后的值分别为0.154,0.617,0.772。
3.3 INF归一化: NORM_INF
INF归一化依据于最大值,用原始像素值除以所有原始像素值中的最大值即为原始像素值归一化后的值。
例如对于20.0,80.0,100.0三个像素值,它们的最大值为100.0,则
20.0
/
100.0
=
0.2
20.0/100.0=0.2
20.0/100.0=0.2
80.0
/
100.0
=
0.8
80.0/100.0=0.8
80.0/100.0=0.8
100.0
/
100.0
=
1.0
100.0/100.0=1.0
100.0/100.0=1.0
所以20.0,80.0,100.0经过INF归一化后的值分别为0.2,0.8,1.0。
3.4 MINMAX归一化: NORM_MINMAX
INF归一化依据于最大值与最小值的差值(记为delta),用原始像素值除以所有原始像素值中的最大值即为原始像素值归一化后的值。
例如对于20.0,80.0,100.0三个像素值,它们的最小值
m
i
n
min
min为20.0,最大值
m
a
x
max
max为100.0,则
d
e
l
t
a
=
m
a
x
−
m
i
n
=
100.0
−
20.0
=
80.0
delta=max-min=100.0-20.0=80.0
delta=max−min=100.0−20.0=80.0
所以
(
20.0
−
m
i
n
)
/
d
e
l
t
a
=
(
20.0
−
20.0
)
/
80.0
=
0.0
(20.0-min)/delta=(20.0-20.0)/80.0=0.0
(20.0−min)/delta=(20.0−20.0)/80.0=0.0
(
80.0
−
m
i
n
)
/
d
e
l
t
a
=
(
80.0
−
20.0
)
/
80.0
=
0.75
(80.0-min)/delta=(80.0-20.0)/80.0=0.75
(80.0−min)/delta=(80.0−20.0)/80.0=0.75
(
100.0
−
m
i
n
)
/
d
e
l
t
a
=
(
100.0
−
20.0
)
/
80.0
=
1.0
(100.0-min)/delta=(100.0-20.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);
结果:
4.完整代码
#include<opencv2/opencv.hpp>
#include<iostream>
//#include<Windows.h>
using namespace cv;
using namespace std;
int main(int argc, char**argv)
{
//get input image
Mat input_image = imread("./whisper.jpg", 1);
if (input_image.empty())
{
cout << "read input error!" << endl;
return -1;
}
imshow("input", input_image);
#if 0
Mat result_x, result_y, result_xy;
//沿x轴翻转
flip(input_image, result_x, 0);
imshow("result_x", result_x);
//沿y轴翻转
flip(input_image, result_y, 1);
imshow("result_y", result_y);
//沿xy对角线翻转
flip(input_image, result_xy, -1);
imshow("result_xy", result_xy);
#endif
int height = input_image.rows;
int width = input_image.cols;
float fx = 0.0, fy = 0.0;
Mat result = Mat::zeros(input_image.size(), input_image.type());
resize(input_image, result, Size(width * 2, height * 2), fx = 0, fy = 0, INTER_NEAREST);
imshow("INTER_NEAREST", result);
resize(input_image, result, Size(width * 2, height * 2), fx = 0, fy = 0, INTER_LINEAR);
imshow("INTER_LINEAR", result);
resize(input_image, result, Size(width * 2, height * 2), fx = 0, fy = 0, INTER_CUBIC);
imshow("INTER_CUBIC", result);
resize(input_image, result, Size(width * 2, height * 2), fx = 0, fy = 0, INTER_LANCZOS4);
imshow("INTER_LANCZOS4", result);
waitKey(0);
destroyAllWindows();
//system("pause");
return 0;
}
#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;
}