参考:
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
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include
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 " <" x "<//转成灰度
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波段的影像
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
#include
#include
#include
#include
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;
//创建一个存放影像信息的structure
typedef 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 imgMat(St.nbands);
std::vector 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 imgMat;
vector 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 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;
}
先使用GDAL与opencv将影像转成Mat,再直接使用opencv的imwrite保存Mat,只能针对不超过3波段的数据,而且保存的影像没有坐标。如果波段数不超过3,位数为8bit,推荐使用第一种方法加载图像,该方法保存;其他使用第二种方法加载图像和保存
//直接保存mat
std::vector imgMat(St.nbands);
std::vector 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);