0
点赞
收藏
分享

微信扫一扫

opencv之三种不限原位深、通道的灰度变换法详解

崭新的韭菜 2022-04-20 阅读 87
c++opencv

一直以来对图像的通道变换,位深变换的本质不理解,今天花时间终于算是搞懂了(纯干货)


1、首先要懂得像素的数据类型

位深度数据类型取值范围
8Uunsigned char0-255
8Schar-128-127
16Uunsigned short int0-65535
16Sshort int-32768-32767
32Slong0-65535
32Ffloat0-1.0
64Fdouble0-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);

 

 

 

 


个人理解,若有错误欢迎纠正! 

举报

相关推荐

0 条评论