Qt使用OpenCV修改GDAL图片各个通道值(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_21078557/article/details/80004162

说明:本文章是通过Qt使用Opencv,利用GDAL加载的图像,对图像的RGB通道值进行修改。

一、博文概要:

1、如果你还不曾成功通过GDAL加载图像通过opencv显示到QImage中,请点击我查看代码实现。

2、本博客是基于上一次GDAL和Opencv的共同使用的基础之上实现的。

3、将读取到的cv::Mat数据通过使用迭代器的方式进行访问,能够快速的处理。目测现在1920*1080的图像处理是比较流畅的。

4、图像的处理是基于父进程,后面会修改为子线程,后续处理。

5、本文的图片加载使用的是GDAL,同样也可以使用OPencv去加载,完全不干扰,只是提供GDAL和OPencv的操作,这样的资料网上真的是太少了。(新手ing)

废话不多说,直接说实现了。

二、实现流程:
1、通过GDAL加载数据;
2、将GDAL加载的波段数据设置到OPencv的Mat中;
3、将Mat数据进行通道分割;
4、使用迭代器修改每个通道的数据值;
5、合并修改好的通道;
6、QImage显示。

三、具体实现
1、GDAL加载数据和将数据设置到OPencvMat中参考我的这篇文章:链接

2、Mat数据的通道分割修改值并合并图像:
2.1 修改某个通道值

bool IMGFORMATCHANGE::SetImageChannelRatio(const Mat &srcImg,Mat &dstImg,int dr,int dg,int db,int dalpha)
{
    // 1、检查改变分量的范围
    if((dr>255||dg>255||db>255||dalpha>255)&&(dr<0||dg<0||db<0||dalpha<0))
    {
        qDebug()<<"IMGFORMATCHANGE::SetImageChannelRatio:"<<"dr,dg,db,dalpha value out of range.";
        return false;
    }

    // 2、判断图像是否是灰度图像,灰度图像不需要进行通道值改变
    unsigned int channels = srcImg.channels();
    if(channels<3)
    {
        qDebug()<<"IMGFORMATCHANGE::SetImageChannelRatio:"<<"Image can not set RGB value.";
        return false;
    }

    unsigned int rows = srcImg.rows;
    unsigned int cols = srcImg.cols;

    // 3、分离通道
    vector<Mat> BGRA(channels,cv::Mat( rows, cols, CV_8UC3,Scalar(0)));//创建一个channels通道容器保存每个通道的值
    split(srcImg,BGRA);//分离通道

    // 4、通道值处理
    if(db!=0)//B channel
    {
        ModifyChannels(BGRA[0],db);
    }

    if(dg!=0)//G channel
    {
        ModifyChannels(BGRA[1],dg);
    }

    if(dr!=0)//R channel
    {
        ModifyChannels(BGRA[2],dr);
    }

    if(dalpha!=0)//Alpha channel
    {
        ModifyChannels(BGRA[3],dalpha);
    }

    // 5、合并新处理好的通道图像
    cv::merge(BGRA,dstImg);

    return true;
}
bool IMGFORMATCHANGE::SetImageChannelRatio(const QImage &srcImg, QImage &dstImg, int dr, int dg, int db, int dalpha)
{
    cv::Mat src,dst;
    if(!QImage2Mat(srcImg,src))
    {
        qDebug()<<"IMGFORMATCHANGE::SetImageChannelRatio(): "<<"QImage2Mat() false.";
        return false;
    }

    if(!SetImageChannelRatio(src,dst,dr,dg,db,dalpha))
    {
        qDebug()<<"IMGFORMATCHANGE::SetImageChannelRatio(): "<<"SetImageChannelRatio() false.";
        return false;
    }

    if(!Mat2QImage(dst,dstImg))
    {
        qDebug()<<"IMGFORMATCHANGE::SetImageChannelRatio(): "<<"Mat2QImage() false.";
        return false;
    }
    return true;
}

note:ModifyChannels函数实现

void IMGFORMATCHANGE::ModifyChannels(cv::Mat &img, int d)
{
    //采用迭代器的方式进行修改数据,效率最高
    MatIterator_<uchar> itr = img.begin<uchar>();
    MatIterator_<uchar> itrend = img.end<uchar>();

    for(;itr!=itrend;itr++)
    {
        *itr = *itr + d;
        if( *itr > 255)
            *itr = 255;
        if( *itr < 0)
            *itr = 0;
    }
}

2.2 重置某个通道的值为一个指定的数据:

bool IMGFORMATCHANGE::ResetImageChannelRatio(const Mat &srcImg, Mat &dstImg, int r, int g, int b, int alpha)
{
    // 1、判断图像是否是灰度图像,灰度图像不需要进行通道值改变
    unsigned int channels = srcImg.channels();
    if(channels<3)
    {
        qDebug()<<"IMGFORMATCHANGE::ResetImageChannelRatio:"<<"Image can not set RGB value.";
        return false;
    }

    unsigned int rows = srcImg.rows;
    unsigned int cols = srcImg.cols;

    // 2、分离通道
    vector<Mat> BGRA(channels,cv::Mat( rows, cols, CV_8UC3,Scalar(0)));//创建一个channels通道容器保存每个通道的值
    split(srcImg,BGRA);//分离通道



    // 3、通道值处理
    if(b>=0&&b<=255)//B channel
    {
        cv::Mat B(rows,cols,CV_8UC1,Scalar(b));//初始化通道值
        BGRA[0]=B;
    }

    if(g>=0&&g<=255)//G channel
    {
        cv::Mat G(rows,cols,CV_8UC1,Scalar(g));//初始化通道值
        BGRA[1]=G;
    }

    if(r>=0&&r<=255)//R channel
    {
        cv::Mat R(rows,cols,CV_8UC1,Scalar(r));//初始化通道值
        BGRA[2]=R;
    }

    if((alpha>=0&&alpha<=255)&&channels==4)//Alpha channel
    {
        cv::Mat Alpha(rows,cols,CV_8UC1,Scalar(alpha));//初始化通道值
        BGRA[3]=Alpha;
    }

    // 4、合并新处理好的通道图像
    cv::merge(BGRA,dstImg);

    return true;
}
bool IMGFORMATCHANGE::ResetImageChannelRatio(const QImage &srcImg, QImage &dstImg, int r, int g, int b, int alpha)
{
    cv::Mat src,dst;
    if(!QImage2Mat(srcImg,src))
    {
        qDebug()<<"IMGFORMATCHANGE::ResetImageChannelRatio(): "<<"QImage2Mat() false.";
        return false;
    }

    if(!ResetImageChannelRatio(src,dst,r,g,b,alpha))
    {
        qDebug()<<"IMGFORMATCHANGE::ResetImageChannelRatio(): "<<"SetImageChannelRatio() false.";
        return false;
    }

    if(!Mat2QImage(dst,dstImg))
    {
        qDebug()<<"IMGFORMATCHANGE::ResetImageChannelRatio(): "<<"Mat2QImage() false.";
        return false;
    }
    return true;
}

备注:其中重载了两个函数,分别是:
1、`设置某个通道的改变值:

bool SetImageChannelRatio(const Mat &srcImg,Mat &dstImg,int dr,int dg,int db,int dalpha);

bool SetImageChannelRatio(const QImage &srcImg,QImage &dstImg,int dr,int dg,int db,int dalpha);`

2、重置某个通道的值:

    bool ResetImageChannelRatio(const Mat &srcImg,Mat &dstImg,int r,int g,int b,int alpha);

    bool ResetImageChannelRatio(const QImage &srcImg,QImage &dstImg,int r,int g,int b,int alpha);

注意:Mat的颜色空间为BGRA,而QImage的颜色空间为RGBA

三、调用,将此函数实例化为对象进行调用即可,后续附上我的工程文件下载地址。

四、运行效果
原图:
这里写图片描述
1、R通道全部设置为原来的一半:
这里写图片描述
2、G通道全部设置为原来的一半:
这里写图片描述
3、B通道全部设置为原来的一半:
这里写图片描述
4、RGB所有调整一半:(看起来就像狗一样,巨丑)
这里写图片描述
5、设置R通道值全部为255
这里写图片描述
6、设置G通道值全部为255
这里写图片描述
7、设置B通道值全部为255
这里写图片描述

ok,到此就结束了。如果你想参考我的代码进行个人的自定义修改,请在这里下载,并且注明出处,严禁抄袭了还不装逼的人,

源代码下载地址

猜你喜欢

转载自blog.csdn.net/qq_21078557/article/details/80004162