opencv(c++)遥感影像加载与保存

来源:互联网 发布:查看守望先锋数据 编辑:程序博客网 时间:2024/05/24 05:47

参考:
1、https://docs.opencv.org/3.2.0/d7/d73/tutorial_raster_io_gdal.html
2、http://www.cnblogs.com/zyore2013/p/4657702.html
3、http://www.cnblogs.com/zyore2013/p/5815941.html
4、http://blog.csdn.net/liminlu0314/article/details/7433936


1、使用imread加载

#include "opencv2/core.hpp"#include "opencv2/imgproc.hpp"#include "opencv2/highgui.hpp"#include <iostream>using namespace std;using namespace cv;int main(){    char* img_path = "D:/14.tif";    //加载图像,这样加载没有投影信息    Mat image = imread(img_path, IMREAD_LOAD_GDAL | IMREAD_COLOR | IMREAD_ANYDEPTH);    //判断是否加载成功    if (!image.data) //或者image.empty()    {        cout << img_path << "  cannot open!" << endl;        return -1;    }    // 输出图像大小信息 C x W x H    cout << image.channels()<<" x " <<image.rows<<" x "<<image.cols<< endl;     //转成灰度    Mat dst;    cvtColor(image, dst, COLOR_BGR2GRAY);    //显示图像    namedWindow("src", 1);    namedWindow("dst", 1);    imshow("src", image);    imshow("dst", dst);    waitKey(0);    destroyAllWindows();    //保存转换的图像    imwrite("D:/14_2.tif", dst);    return 0;}

注:直接使用imread加载遥感影像不会有投影信息,且只能加载不超过3波段的影像


2、结合GDAL

GDAL读取遥感图像在转成Mat,再保存
参考:
1、http://www.cnblogs.com/zyore2013/p/4657702.html
2、http://www.cnblogs.com/zyore2013/p/5815941.html
3、http://blog.csdn.net/liminlu0314/article/details/7433936

#include "opencv2/core.hpp"#include "opencv2/imgproc.hpp"#include "opencv2/highgui.hpp"#include <gdal.h>#include <gdal_priv.h>  #include <iostream>#include <string>#include <vector>using namespace std;using namespace cv;/*! byte */typedef unsigned char   byte;/*! 8U */typedef unsigned char   DT_8U;/*! 16U */typedef unsigned short  DT_16U;/*! 16S */typedef short           DT_16S;/*! 32U */typedef unsigned int    DT_32U;/*! 32S */typedef int             DT_32S;/*! 32F */typedef float           DT_32F;/*! 64F */typedef double          DT_64F;//创建一个存放影像信息的structuretypedef struct{    //GDALDataset *poDataset = NULL;    int Xsize=0;    int Ysize=0;    int nbands=0;    double *tmpadfGeoTransform=new double[6]; //存储地理6参数    const char* proj = NULL;//存储投影    GDALDataType iDataType = GDT_Byte;}MyStruct;cv::Mat GDAL2Mat(GDALDataset *poDataset, MyStruct &St);bool Mat2File(cv::Mat img, MyStruct &St, GDALDataset *poDataset);int main(){    //注册驱动      GDALAllRegister();    string  src_path = "D:/14.tif";    string dst_path = "D:/14_2.tif";    MyStruct St;    GDALDataset *poDataset = (GDALDataset *)GDALOpen(src_path.c_str(), GA_ReadOnly);    St.Xsize = poDataset->GetRasterXSize();    St.Ysize = poDataset->GetRasterYSize();    St.nbands = poDataset->GetRasterCount();    poDataset->GetGeoTransform(St.tmpadfGeoTransform);    St.proj = poDataset->GetProjectionRef();    //获取数据类型    St.iDataType = poDataset->GetRasterBand(1)->GetRasterDataType();    Mat img = GDAL2Mat(poDataset, St);    /*    //直接保存mat    std::vector<cv::Mat> imgMat(St.nbands);    std::vector<cv::Mat> tempMat(St.nbands);    cv::split(img, imgMat);    tempMat.at(0) = (imgMat.at(2));//BGR-->RGB    tempMat.at(1) = (imgMat.at(1));    tempMat.at(2) = (imgMat.at(0));    Mat img2;    cv::merge(tempMat, img2);    imgMat.clear();    tempMat.clear();    imwrite("D:/14_3.tif", img2);    */    //判断是否加载成功    if (!img.data) //或者image.empty()    {        cout << src_path << "  cannot open!" << endl;        return -1;    }    //定义输出数据    GDALDataset *poDataset2;   //GDAL数据集    GDALDriver *poDriver;      //驱动,用于创建新的文件    //poDriver = GetGDALDriverManager()->GetDriverByName("ENVI");    poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");    if (poDriver == NULL)        return 0;    poDataset2 = poDriver->Create(dst_path.c_str(), St.Xsize, St.Ysize, St.nbands,        St.iDataType, NULL);//GDT_Float32    //重新设置地理参考和投影系    poDataset2->SetGeoTransform(St.tmpadfGeoTransform);    poDataset2->SetProjection(St.proj);    GDALClose((GDALDatasetH)poDataset);    Mat2File(img, St, poDataset2);    GDALClose((GDALDatasetH)poDataset2);    return 0;}//GDAL数据转opencv的Mat格式cv::Mat GDAL2Mat(GDALDataset *poDataset,MyStruct &St)  //const QString fileName{    //获取数据类型    //GDALDataType iDataType = poDataset->GetRasterBand(1)->GetRasterDataType();    //int idepth = GDALGetDataTypeSize((GDALDataType)iDataType);    //将GDAL的数据类型与Mat的数据类型对应起来    auto MdataType = NULL;    auto MdataTypes = NULL;    if (St.iDataType == GDT_Byte)    {        MdataType = CV_MAKETYPE(CV_8U, 1);        MdataTypes= CV_MAKETYPE(CV_8U, St.nbands);    }    if (St.iDataType == GDT_UInt16)    {        MdataType = CV_MAKETYPE(CV_16U, 1);        MdataTypes = CV_MAKETYPE(CV_16U, St.nbands);    }    //QVector <cv::Mat> imgMat;      vector<Mat> imgMat;// 每个波段    float *pafScan = new float[St.Xsize*St.Ysize];   // 存储数据    for (int i = 0; i< St.nbands; i++)    {        GDALRasterBand *pBand = poDataset->GetRasterBand(i + 1);        //pafScan = new float[tmpCols*tmpRows];        pBand->RasterIO(GF_Read, 0, 0, St.Xsize, St.Ysize, pafScan,            St.Xsize, St.Ysize, St.iDataType, 0, 0); //GDT_Float32        cv::Mat tmpMat = cv::Mat(St.Ysize, St.Xsize, MdataType, pafScan);//CV_32FC1        imgMat.push_back(tmpMat.clone());    }    delete[]pafScan;    pafScan = NULL;    cv::Mat img;    img.create(St.Ysize, St.Xsize, MdataTypes); //CV_32FC(tmpBandSize)    //cv::merge(imgMat.toStdVector(), img);    cv::merge(imgMat, img);    //释放内存    imgMat.clear();    //GDALClose((GDALDatasetH)poDataset);    return img;}//Mat 数据保存bool Mat2File(cv::Mat img,MyStruct &St, GDALDataset *poDataset)//const QString fileName{    if (img.empty())    //    判断是否为空        return 0;    const int nBandCount = St.nbands;    const int nImgSizeX = St.Xsize;    const int nImgSizeY = St.Ysize;    //    将通道分开    //  imgMat每个通道数据连续    std::vector<cv::Mat> imgMat(nBandCount);    cv::split(img, imgMat);    //  分波段写入文件    GDALAllRegister();    //  循环写入文件    GDALRasterBand *pBand = NULL;    float *ppafScan = new float[nImgSizeX*nImgSizeY];    cv::Mat tmpMat;// = cv::Mat(nImgSizeY,nImgSizeX,CV_32FC1);    for (int i = 1; i <= nBandCount; i++)    {        pBand = poDataset->GetRasterBand(i);        tmpMat = imgMat.at(i - 1);        if (tmpMat.isContinuous())        {            if(St.iDataType==GDT_Byte)                memmove(ppafScan, (void*)tmpMat.ptr(0), sizeof(unsigned char)*nImgSizeX*nImgSizeY);//GDT_Byte            if(St.iDataType==GDT_UInt16)                memmove(ppafScan, (void*)tmpMat.ptr(0), sizeof(unsigned short)*nImgSizeX*nImgSizeY);//GDT_Uint16            //memmove(ppafScan, (void*)tmpMat.ptr(0),sizeof(float)*nImgSizeX*nImgSizeY);//GDT_Float32        }        else            return false;        CPLErr err = pBand->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, ppafScan,            nImgSizeX, nImgSizeY, St.iDataType, 0, 0);    }    delete[] ppafScan;    ppafScan = NULL;    imgMat.clear();    //GDALClose(poDataset);    return 1;}

3、使用imwrite保存

先使用GDAL与opencv将影像转成Mat,再直接使用opencv的imwrite保存Mat,只能针对不超过3波段的数据,而且保存的影像没有坐标。如果波段数不超过3,位数为8bit,推荐使用第一种方法加载图像,该方法保存;其他使用第二种方法加载图像和保存

//直接保存mat    std::vector<cv::Mat> imgMat(St.nbands);    std::vector<cv::Mat> tempMat(St.nbands);    cv::split(img, imgMat);    tempMat.at(0) = imgMat.at(2);//BGR-->RGB    tempMat.at(1) = imgMat.at(1);    tempMat.at(2) = imgMat.at(0);    Mat img2;    cv::merge(tempMat, img2);    imgMat.clear();    tempMat.clear();    imwrite("D:/14_3.tif", img2);

原创粉丝点击