一直以来对图像的通道变换,位深变换的本质不理解,今天花时间终于算是搞懂了(纯干货)
1、首先要懂得像素的数据类型
位深度 | 数据类型 | 取值范围 |
---|---|---|
8U | unsigned char | 0-255 |
8S | char | -128-127 |
16U | unsigned short int | 0-65535 |
16S | short int | -32768-32767 |
32S | long | 0-65535 |
32F | float | 0-1.0 |
64F | double | 0-1.0 |
数据类型与通道数没关系,8代表8位,16代表16位。
2、其次要懂得通道变换
3通道->1通道:就是将rgb三个通道的像素数据通过某种方式进行合并,然后写入单通道即可
3、就是映射关系
例:0-1要线性映射到0-100是不是就是将0-1每一个数据线性增大100倍?
那么无符号8位数据要映射到无符号16位数据,是不是就是将0-255线性映射到0-65535?即将0-255中每个数据乘以65535.0/255。
这里介绍一种24位3通道彩色图像转16位灰度图的三种灰度变换法
首先:得明白24位3通道图像每通道的数据类型为unsigned char(24/3=8),16位单通道数据类型为unsigned short int
其次:先创建空白16位单通道图像,再通过灰度算法处理像素数据,但是这时候处理的像素数据的数据类型与原图一致,即uchar。
最后:将处理过的像素数据乘以线性映射系数(计算方式如步骤3)写入空白16位单通道图像中即可以得到16位灰度图。
代码:
Mat img = imread("./1.jpg",2|4);
cout<<"原channels=="<<img.channels()<<endl;
cout<<"原type=="<<data.Type2String(img.type())<<endl;
double alpha = 65535.0/255;//映射系数:8位->16位
Mat src16bit = Mat::zeros(Size(img.cols, img.rows), CV_16UC1);
Mat src16bit1 = Mat::zeros(Size(img.cols, img.rows), CV_16UC1);
Mat src16bit2 = Mat::zeros(Size(img.cols, img.rows), CV_16UC1);
for (int i = 0; i < img.rows; i++)
{
uchar* data_pix = img.ptr<uchar>(i);
for (int j = 0; j < img.cols * 3; j = j + 3)
{
uchar r, g, b,d,e;
double val,val1,val2;
r = data_pix[j];
g = data_pix[j + 1];
b = data_pix[j + 2];
//取rgb三通道像素最大值(此时还是8位数据类型uchar)
d = r > g ? r : g;
d = d > b ? d : b;
//平均值法
val1 = alpha*((r+g+b)/3.0);
val = alpha*d;//映射到16位需要把8位数据线性映射到16位数据类型
//加权平均值法
val2 = alpha*(0.299*r+0.578*g+0.114*b);
src16bit.at<unsigned short int>(i, j/3) = (unsigned short int)val;
src16bit1.at<unsigned short int>(i, j/3) = (unsigned short int)val1;
src16bit2.at<unsigned short int>(i, j/3) = (unsigned short int)val2;
}
}
cout<<"最值法channels=="<<src16bit.channels()<<endl;
cout<<"最值法type=="<<data.Type2String(src16bit.type())<<endl;
cout<<"平均值法channels=="<<src16bit1.channels()<<endl;
cout<<"平均值法type=="<<data.Type2String(src16bit1.type())<<endl;
cout<<"加权平均值法channels=="<<src16bit2.channels()<<endl;
cout<<"加权平均值法type=="<<data.Type2String(src16bit2.type())<<endl;
imshow("max_dst",src16bit);
imshow("average_dst",src16bit1);
imshow("weighted_mean_dst",src16bit2);
imshow("img",img);
waitKey(0);
个人理解,若有错误欢迎纠正!