欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用GDAL构造OpenCV的图像格式

程序员文章站 2022-03-20 13:17:40
...
        OpenCV提供了大量的函数,但是OpenCV支持的图像数据格式太少,同时,对于GDAL可以支持很多的图像格式,但是GDAL又不没有像OpenCV那么多的算法函数。这两者真的是鱼和熊掌不能兼得,为了结束这种纠结的状态,既想支持多种图像格式,又想 用OpenCV丰富的函数,那么请往下看:基本原理就是,使用GDAL打开图像,然后读取图像数据,将图像数据重新构建一个OpenCV的IplImage类型,然后就可以使用了。

//将GDAL读取出来的数据转换为OpenCV的存储格式
void CImageTemplateMatch::CopyDataFromGDALToOpenCV(void* pImage, DT_8U* pData, int iBandCount)
{
	CvMat* image = (CvMat*) pImage;
	
	int index = 0;
	for(int i = 0; i < image->rows; i++ )
	{
		DT_8U* rrow = (DT_8U*)(image->data.ptr + i*image->step);
		for(int j = 0; j < image->cols*iBandCount; j+=iBandCount)
		{
			for(int k=0; k<iBandCount; k++)
				rrow[j+k] = pData[index+k];

			index +=iBandCount;
		}

		for(int k=0; k<iBandCount; k++)
			rrow[image->cols*iBandCount+k] = 205;
	}
}

//注意,只能适用于小图像,大图像肯定不行,而且波段数只能是1个或者3个,对于超过三个的请自己修改代码
void CovertGDAL2OpenCV(const char* pszFile, IplImage** ppSrcImage)
{
	GDALDataset* poSrc	= (GDALDataset*) GDALOpen(pszFile, GA_ReadOnly);
	int iWidth = poSrc->GetRasterXSize();
	int iHeight = poSrc->GetRasterYSize();
	int iBandCount = poSrc->GetRasterCount();
	
	GDALDataType iDataType = poSrc->GetRasterBand(1)->GetDataType();
	int idepth = GDALGetDataTypeSize((GDALDataType)iDataType);

	//将原始转换为OpenCV的图像格式
	CvSize sourceSize = cvSize(iWidth, iHeight);
	*ppSrcImage = cvCreateImage(sourceSize, idepth, iBandCount );
	CvMat stub,  *image = (CvMat*)pSrcImage;
	image = cvGetMat( image, &stub );

	DT_8U *pSrcData = new DT_8U[iWidth*iHeight*iBandCount];
	if(iBandCount == 3)
	{
		int panBandMap [3] = {3,2,1};	//按照BGR BGR BGR ... 来读取数据组织
		poSrc->RasterIO(GF_Read, iStartCol, iStartRow, iWidth, iHeight, pSrcData, iWidth, iHeight,\
			(GDALDataType) iDataType, iBandCount, panBandMap, iDataType*iBandCount, iDataType*iWidth*iBandCount, iDataType);	//全部读取进来
	}
	else if(iBandCount == 1)
	{
		int panBandMap [1] = {1};
		poSrc->RasterIO(GF_Read, iStartCol, iStartRow, iWidth, iHeight, pSrcData, iWidth, iHeight,\
			(GDALDataType) iDataType, iBandCount, panBandMap, iDataType*iBandCount, iDataType*iWidth*iBandCount, iDataType);	//全部读取进来
	}
	else
	{
		RELEASE(pSrcData);
                GDALClose((GDALDatasetH)poSrc);
		*ppSrcImage = NULL;
		return;
	}

	CopyDataFromGDALToOpenCV(image, pSrcData, iBandCount);
	RELEASE(pSrcData);
	GDALClose((GDALDatasetH)poSrc);
}
          对于代码中的几点注意事项和说明,第一,由于OpenCV是将整幅图像全部存在内存中的,所以该函数不能处理大图像,此外,由于OpenCV一般只能处理三波段和单波段图像,所以该函数也只能处理成三波段和单波段,对于超过三个波段的图像,你可以修改程序,挑选三个波段来进行读取。对于OpenCV中数据的组织格式,自己可以参考OpenCV的相关文档。

转载于:https://www.cnblogs.com/xiaowangba/archive/2012/04/06/6314022.html