最近利用OpenCV函数库的时候,常常遇到不同深度的图像的转换、显示和保存问题。在网上查阅了很多文章,发现很多说的不够清楚。在此说下自己的理解。
-
IplImage* inImg =
cvLoadImage(
"1.bmp", CV_LOAD_IMAGE_GRAYSCALE);
-
IplImage* out8u =
cvCreateImage(
cvGetSize(inImg), IPL_DEPTH_8U,
1);
-
IplImage* out8s =
cvCreateImage(
cvGetSize(inImg), IPL_DEPTH_8S,
1);
-
IplImage* out16u =
cvCreateImage(
cvGetSize(inImg), IPL_DEPTH_16U,
1);
-
IplImage* out16s =
cvCreateImage(
cvGetSize(inImg), IPL_DEPTH_16S,
1);
-
IplImage* out32s =
cvCreateImage(
cvGetSize(inImg), IPL_DEPTH_32S,
1);
-
IplImage* out32f =
cvCreateImage(
cvGetSize(inImg), IPL_DEPTH_32F,
1);
-
IplImage* out64f =
cvCreateImage(
cvGetSize(inImg), IPL_DEPTH_64F,
1);
如上代码涵盖了OpenCV中几种不同深度的数据格式,其特性统计如下:
图像类型 | 数据类型 | 字节 | 取值范围 | 显示范围 |
IPL_DEPTH_8U | unsigned char | 1 | 0~255 | 0~255 |
IPL_DEPTH_8S | char | 1 | -128~127 | -128~128 |
IPL_DEPTH_16U | unsigned short | 2 | 0~65535 | 0~65535 |
IPL_DEPTH_16S | short | 2 | -32768~32767 | -32768~32767 |
IPL_DEPTH_32S | long | 4 | long | 0~65535 |
IPL_DEPTH_32F | float | 4 | 单精度 | 0~1 |
IPL_DEPTH_64F | double | 8 | 双精度 | 0~1 |
上表中,显示范围表示调用OpenCV的cvShowImage能够在屏幕上显示的范围。其中对于IPL_DEPTH_32S、IPL_DEPTH_32F和IPL_DEPTH_64F类型图像来说,
其取值范围与显示范围不一致。
而应用cvSaveImage保存图像的时候,需要把其他深度变换到IPL_DEPTH_8U深度上来保存。这时候要用到一个函数。
-
void cvConvertScale(const CvArr* src, CvArr* dst, double scale = 1, double shift = 0)
-
/*
-
Parameters:
-
src – Source array
-
dst – Destination array
-
scale – Scale factor
-
shift – Value added to the scaled source array elements
-
*****
-
The function has several different purposes, and thus has several different names. It copies
-
one array to another with optional scaling, which is performed first, and/or optional type
-
conversion.All the channels of multi-channel arrays are processed independently.
-
*/
该函数可以完成图像数据的尺度变换、平移和数据格式变换。
可以利用此函数完成图像数据尺度变换以便于其显示和保存。方法如下:
-
//显示,需将其转换到0~1之间
-
double m, n;
-
cvMinMaxLoc(out32f, &m, &n,
NULL,
NULL,
NULL);
-
cvConvertScale(out32f, out32f,
1.0/(n-m),
1.0*(-m)/(n-m));
-
cvShowImage(
"out",out32f);
-
-
//保存,需转化为8位图像
-
cvMinMaxLoc(out32f, &m, &n,
NULL,
NULL,
NULL);
-
cvConvertScale(out32f, out8u,
255.0/(n-m),
255.0*(-m)/(n-m));
-
cvSaveImage(
"out.png", out8u);
-
cvWaitKey(
-1);