GDAL载入QImage

GDAL载入到Qt项目中,通过QImage显示到UI

说明:此文是通过本人不断摸索,查阅相关的知识实验成功的,如有不妥之处,望告知:[email protected]

一、开发环境:
1、opencv 3.4.1 msvc
2、GDAL 2.1 msvc
3、Qt 5.10.1
备注:opencv和gdal均是使用的是msvc的编译器,mingw编译环境也可以,需要自己去配置。

二、开发流程:
1、首先通过GDAL载入一张图片;
2、通过读取图片的波段信息存入缓冲区;
3、将缓冲区赋值到OpenCV中的Mat;(此步骤的好处是使用opencv作为中间交换层,能够将图片转换为QImage)
4、将获取的每个波段的信息进行重新混合;
5、将opencv的Mat转换为QImage;
6、显示QImage。

三、备注:
此代码需要你自己首先配置好你的opencv和GDAL环境,如果没有配置请自己百度配置。

四、代码:
按照第二步的流程,代码如下所示:

bool Dataset2QImage(const QString filePath,QImage &img)
{
    //1、check the file format
    QStringList formatStr;
    formatStr.append(".png");
    formatStr.append(".jpg");
    formatStr.append(".tif");
    formatStr.append(".spe");//myself define format
    formatStr.append(".bmp");

    bool format_flag=FALSE;
    for(int i=0;i<formatStr.size();i++)
    {
        if(filePath.endsWith(formatStr[i]))
        {
            format_flag=TRUE;
           break;
        }
    }

    if(!format_flag)
        return FALSE;

    // 2、Initialize GDAL
    GDALAllRegister();

    // 3、Load image
    GDALDataset* dataset = (GDALDataset *)GDALOpen(filePath.toStdString().c_str(), GA_ReadOnly);

    // 4、Get raster image size
    int rows = dataset->GetRasterYSize();
    int cols = dataset->GetRasterXSize();
    int channels = dataset->GetRasterCount();

    Mat R(rows, cols, CV_8UC1, Scalar(0));//to save R img
    Mat G(rows, cols, CV_8UC1, Scalar(0));//to save G img
    Mat B(rows, cols, CV_8UC1, Scalar(0));//to save B img
    vector<Mat> RGB(channels,cv::Mat( rows, cols, CV_8UC3,Scalar(0)));//create RGB channels

    //to init default channel
    //Mat hideChannel(rows, cols, CV_8UC1, Scalar(0));//set need hide channel color is black

    cv::Mat output_image;
    // 6、get data
    // Fetch the band 1
    GDALRasterBand* band = dataset->GetRasterBand(1);
    // Read the band 1 data
    band->RasterIO( GF_Read, 0, 0, cols, rows, B.data,
            cols, rows,GDT_Byte, 0, 0);

    // Fetch the band 2
    band = dataset->GetRasterBand(2);
    // Read the band 2 data
    band->RasterIO( GF_Read, 0, 0, cols, rows, G.data,
            cols, rows,GDT_Byte, 0, 0);

    // Fetch the band 3
    band = dataset->GetRasterBand(3);
    // Read the band 3 data
    band->RasterIO( GF_Read, 0, 0, cols, rows, R.data,
            cols, rows,GDT_Byte, 0, 0);

    // 7、set R G B value to vector mat
    RGB[0]=R;
    RGB[1]=G;
    RGB[2]=B;

    // 8、Merge images,合并通道数据
    cv::merge( RGB, output_image );

    //opencv window show the merge channels image
    //imshow("RGB",output_image);

    // 9、Create the QImage
    return Mat2QImage(output_image,img);
}

以上代码注意事项:
1、上述代码中,第一步是检查文件的格式,其中有我自己定义的图片格式,这个看每个人的发挥,不严谨,严禁的写法应该是采用过滤器的方式;
2、在通过GDAL获取每一个波段的数据的时候,采用指定的波段进行获取,按照优化来说,本应该是采用一个for循环来写,但是,经过本人无数次实验,使用for循环混合后的图片是灰白色的,不能还原原图像,不知道为啥,尝试很久,此处优化留在后期思考。
3、在本代码中最后还使用了将Mat转换为QImage,具体的代码如下所示:

bool Mat2QImage(const Mat &mat,QImage &img)
{
    // 8-bits unsigned, NO. OF CHANNELS = 1
    if(mat.type() == CV_8UC1)
    {
        //qDebug() << "CV_8UC1";
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        // Set the color table (used to translate colour indexes to qRgb values)
        image.setColorCount(256);
        for(int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        // Copy input Mat
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        img=image;
        return TRUE;
    }
    // 8-bits unsigned, NO. OF CHANNELS = 3
    else if(mat.type() == CV_8UC3)
    {
        //qDebug() << "CV_8UC3";
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        img = image.rgbSwapped();
        return TRUE;
    }
    else if(mat.type() == CV_8UC4)
    {
        //qDebug() << "CV_8UC4";
        // Copy input Mat
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        img = image.copy();
        return TRUE;
    }
    else
    {
        qDebug() << "ERROR: Mat could not be converted to QImage.";
        return FALSE;
    }
}

此处提供我的源文件,下载导入你的工程,然后调用对应的函数即可。

猜你喜欢

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