IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 如何实现对不同数据类型的多/单波段Tiff图像的归一化 -> 正文阅读

[数据结构与算法]如何实现对不同数据类型的多/单波段Tiff图像的归一化

归一化是图像数据预处理的常用手段,然而Tiff图像存在多/单波段类型,且数据格式多样化,这为数据处理带来了不少的麻烦。为了便于后期的工作,笔者使用C++语言基于GDAL外部库处理Tiff图像,实现Tiff图像的归一化功能。

直接上代码:

#include "gdal_priv.h"
#include "ogrsf_frmts.h"
#include <iostream>

using namespace alglib;
using namespace std;

//多类型多/单波段归一化
//initialTiff:原始数据存放路径  newTiff:处理后数据存放路径
void normalizedTiff(std::string initialTiff, std::string newTiff)
{
	GDALAllRegister();
	//设置支持中文路径
	CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");

	const char * pszFile = initialTiff.c_str();
	GDALDataset *poDataset = (GDALDataset*)GDALOpen(pszFile, GA_ReadOnly);//使用只读方式打开图像 
	if (!poDataset)
	{
		printf("File: %s不能打开!\n", pszFile);
	}


	//仿射参数
	double padfTransform0[6];
	if (poDataset->GetGeoTransform(padfTransform0) == CE_Failure)
	{
		printf("获取仿射变换参数失败");
	}
	int iImgSizeX0 = poDataset->GetRasterXSize();
	int iImgSizeY0 = poDataset->GetRasterYSize();
	int nCount = poDataset->GetRasterCount(); 	//影像的波段数
	GDALDataType gdal_data_type = poDataset->GetRasterBand(1)->GetRasterDataType();//获取栅格类型
	double dnodata = poDataset->GetRasterBand(1)->GetNoDataValue();//获取空值对应大小
	int *panBandMap = new int[nCount];
	for (int i = 0; i < nCount; i++)
	{
		panBandMap[i] = i + 1;
	}
	switch (gdal_data_type)
	{
	case GDT_Byte:
	{
		unsigned char *pUC_afScanblock1 = new unsigned char[iImgSizeX0*iImgSizeY0 * nCount];
		poDataset->RasterIO(GF_Read, 0, 0, iImgSizeX0, iImgSizeY0, pUC_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);
		
		vector<double>vMax;
		for (int i = 0; i < nCount; i++)
		{
			//获取每个波段最大值
			double dMax = -999999999999999;
			for (int j=0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (dMax < (double)pUC_afScanblock1[i*iImgSizeX0*iImgSizeY0+j] && abs((double)pUC_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata)>0.000001)
				{
					dMax = (double)pUC_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j];
				}
			}
			vMax.push_back(dMax);
		}

		for (int i = 0; i < nCount; i++)
		{
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (abs((double)pUC_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata) > 0.000001)
				{
					pUC_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] = pUC_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] / vMax[i];
				}
			}
		}

		vMax.clear();

		//写入新的tif
		const char* pszDstFilename = newTiff.c_str();
		GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
		GDALDataset* poDstDS = poDriver->Create(pszDstFilename, iImgSizeX0, iImgSizeY0, nCount, gdal_data_type, NULL);
		poDstDS->SetProjection(poDataset->GetProjectionRef());//给它设置投影
		poDstDS->SetGeoTransform(padfTransform0);//给设置空间转换的六参数
		for (int i = 0; i < nCount; i++)
		{
			poDstDS->GetRasterBand(i+1)->SetNoDataValue(dnodata);//将空值设置为“无数据值”
		}
		//保存全波段影像
		poDstDS->RasterIO(GF_Write, 0, 0, iImgSizeX0, iImgSizeY0, pUC_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);

		//释放内存
		GDALClose(poDstDS);
		GDALClose(poDataset);
		delete[]pUC_afScanblock1;
		break;
	}

	case GDT_UInt16:
	{
		//unsigned short *pafScanblock1;
		unsigned short *pUS_afScanblock1 = new unsigned short[iImgSizeX0*iImgSizeY0 * nCount];
		poDataset->RasterIO(GF_Read, 0, 0, iImgSizeX0, iImgSizeY0, pUS_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);
		vector<double>vMax;
		for (int i = 0; i < nCount; i++)
		{
			//获取每个波段最大值
			double dMax = -999999999999999;
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (dMax < (double)pUS_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] && abs((double)pUS_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata)>0.000001)
				{
					dMax = (double)pUS_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j];
				}
			}
			vMax.push_back(dMax);
		}

		for (int i = 0; i < nCount; i++)
		{
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (abs((double)pUS_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata) > 0.000001)
				{
					pUS_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] = pUS_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] / vMax[i];
				}
			}
		}
		vMax.clear();

		//写入新的tif
		const char* pszDstFilename = newTiff.c_str();
		GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
		GDALDataset* poDstDS = poDriver->Create(pszDstFilename, iImgSizeX0, iImgSizeY0, nCount, gdal_data_type, NULL);
		poDstDS->SetProjection(poDataset->GetProjectionRef());//给它设置投影
		poDstDS->SetGeoTransform(padfTransform0);//给设置空间转换的六参数
		for (int i = 0; i < nCount; i++)
		{
			poDstDS->GetRasterBand(i + 1)->SetNoDataValue(dnodata);//将空值设置为“无数据值”
		}
		//保存全波段影像
		poDstDS->RasterIO(GF_Write, 0, 0, iImgSizeX0, iImgSizeY0, pUS_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);

		//释放内存
		GDALClose(poDstDS);
		GDALClose(poDataset);
		delete[]pUS_afScanblock1;
		break;
	}

	case GDT_Int16:
	{
		//	short int *pafScanblock1;
		short int*pSI_afScanblock1 = new short int[iImgSizeX0*iImgSizeY0 * nCount];
		poDataset->RasterIO(GF_Read, 0, 0, iImgSizeX0, iImgSizeY0, pSI_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);
		vector<double>vMax;
		for (int i = 0; i < nCount; i++)
		{
			//获取每个波段最大值
			double dMax = -999999999999999;
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (dMax < (double)pSI_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] && abs((double)pSI_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata)>0.000001)
				{
					dMax = (double)pSI_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j];
				}
			}
			vMax.push_back(dMax);
		}

		for (int i = 0; i < nCount; i++)
		{
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (abs((double)pSI_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata) > 0.000001)
				{
					pSI_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] = pSI_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] / vMax[i];
				}
			}
		}
		vMax.clear();

		//写入新的tif
		const char* pszDstFilename = newTiff.c_str();
		GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
		GDALDataset* poDstDS = poDriver->Create(pszDstFilename, iImgSizeX0, iImgSizeY0, nCount, gdal_data_type, NULL);
		poDstDS->SetProjection(poDataset->GetProjectionRef());//给它设置投影
		poDstDS->SetGeoTransform(padfTransform0);//给设置空间转换的六参数
		for (int i = 0; i < nCount; i++)
		{
			poDstDS->GetRasterBand(i + 1)->SetNoDataValue(dnodata);//将空值设置为“无数据值”
		}
		//保存全波段影像
		poDstDS->RasterIO(GF_Write, 0, 0, iImgSizeX0, iImgSizeY0, pSI_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);

		//释放内存
		GDALClose(poDstDS);
		GDALClose(poDataset);
		delete[]pSI_afScanblock1;
		break;
	}

	case GDT_UInt32:
	{
		//	unsigned long *pafScanblock1;
		unsigned long*pUL_afScanblock1 = new unsigned long[iImgSizeX0*iImgSizeY0 * nCount];
		poDataset->RasterIO(GF_Read, 0, 0, iImgSizeX0, iImgSizeY0, pUL_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);
		vector<double>vMax;
		for (int i = 0; i < nCount; i++)
		{
			//获取每个波段最大值
			double dMax = -999999999999999;
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (dMax < (double)pUL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] && abs((double)pUL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata)>0.000001)
				{
					dMax = (double)pUL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j];
				}
			}
			vMax.push_back(dMax);
		}

		for (int i = 0; i < nCount; i++)
		{
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (abs((double)pUL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata) > 0.000001)
				{
					pUL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] = pUL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] / vMax[i];
				}
			}
		}
		vMax.clear();

		//写入新的tif
		const char* pszDstFilename = newTiff.c_str();
		GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
		GDALDataset* poDstDS = poDriver->Create(pszDstFilename, iImgSizeX0, iImgSizeY0, nCount, gdal_data_type, NULL);
		poDstDS->SetProjection(poDataset->GetProjectionRef());//给它设置投影
		poDstDS->SetGeoTransform(padfTransform0);//给设置空间转换的六参数
		for (int i = 0; i < nCount; i++)
		{
			poDstDS->GetRasterBand(i + 1)->SetNoDataValue(dnodata);//将空值设置为“无数据值”
		}
		//保存全波段影像
		poDstDS->RasterIO(GF_Write, 0, 0, iImgSizeX0, iImgSizeY0, pUL_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);

		//释放内存
		GDALClose(poDstDS);
		GDALClose(poDataset);
		delete[]pUL_afScanblock1;
		break;
	}

	case GDT_Int32:
	{
		//	long *pafScanblock1;
		long *pL_afScanblock1 = new long[iImgSizeX0*iImgSizeY0 * nCount];
		poDataset->RasterIO(GF_Read, 0, 0, iImgSizeX0, iImgSizeY0, pL_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);
		vector<double>vMax;
		for (int i = 0; i < nCount; i++)
		{
			//获取每个波段最大值
			double dMax = -999999999999999;
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (dMax < (double)pL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] && abs((double)pL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata)>0.000001)
				{
					dMax = (double)pL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j];
				}
			}
			vMax.push_back(dMax);
		}

		for (int i = 0; i < nCount; i++)
		{
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (abs((double)pL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata) > 0.000001)
				{
					pL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] = pL_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] / vMax[i];
				}
			}
		}
		vMax.clear();

		//写入新的tif
		const char* pszDstFilename = newTiff.c_str();
		GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
		GDALDataset* poDstDS = poDriver->Create(pszDstFilename, iImgSizeX0, iImgSizeY0, nCount, gdal_data_type, NULL);
		poDstDS->SetProjection(poDataset->GetProjectionRef());//给它设置投影
		poDstDS->SetGeoTransform(padfTransform0);//给设置空间转换的六参数
		for (int i = 0; i < nCount; i++)
		{
			poDstDS->GetRasterBand(i + 1)->SetNoDataValue(dnodata);//将空值设置为“无数据值”
		}
		//保存全波段影像
		poDstDS->RasterIO(GF_Write, 0, 0, iImgSizeX0, iImgSizeY0, pL_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);

		//释放内存
		GDALClose(poDstDS);
		GDALClose(poDataset);
		delete[]pL_afScanblock1;
		break;
	}
	case GDT_Float32:
	{
		float *pF_afScanblock1 = new float[iImgSizeX0*iImgSizeY0 * nCount];
		poDataset->RasterIO(GF_Read, 0, 0, iImgSizeX0, iImgSizeY0, pF_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);
		vector<double>vMax;
		for (int i = 0; i < nCount; i++)
		{
			//获取每个波段最大值
			double dMax = -999999999999999;
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (dMax < (double)pF_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] && abs((double)pF_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata)>0.000001)
				{
					dMax = (double)pF_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j];
				}
			}
			vMax.push_back(dMax);
		}

		for (int i = 0; i < nCount; i++)
		{
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (abs((double)pF_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata) > 0.000001)
				{
					pF_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] = pF_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] / vMax[i];
				}
			}
		}
		vMax.clear();

		//写入新的tif
		const char* pszDstFilename = newTiff.c_str();
		GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
		GDALDataset* poDstDS = poDriver->Create(pszDstFilename, iImgSizeX0, iImgSizeY0, nCount, gdal_data_type, NULL);
		poDstDS->SetProjection(poDataset->GetProjectionRef());//给它设置投影
		poDstDS->SetGeoTransform(padfTransform0);//给设置空间转换的六参数
		for (int i = 0; i < nCount; i++)
		{
			poDstDS->GetRasterBand(i + 1)->SetNoDataValue(dnodata);//将空值设置为“无数据值”
		}
		//保存全波段影像
		poDstDS->RasterIO(GF_Write, 0, 0, iImgSizeX0, iImgSizeY0, pF_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);

		//释放内存
		GDALClose(poDstDS);
		GDALClose(poDataset);
		delete[]pF_afScanblock1;
		break;
	}
	case GDT_Float64:
	{
		//	double *pafScanblock1;
		double *pD_afScanblock1 = new double[iImgSizeX0*iImgSizeY0 *nCount];
		poDataset->RasterIO(GF_Read, 0, 0, iImgSizeX0, iImgSizeY0, pD_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);
		vector<double>vMax;
		for (int i = 0; i < nCount; i++)
		{
			//获取每个波段最大值
			double dMax = -999999999999999;
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (dMax < (double)pD_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] && abs((double)pD_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata)>0.000001)
				{
					dMax = (double)pD_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j];
				}
			}
			vMax.push_back(dMax);
		}

		for (int i = 0; i < nCount; i++)
		{
			for (int j = 0; j < iImgSizeX0*iImgSizeY0; j++)
			{
				if (abs((double)pD_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] - dnodata) > 0.000001)
				{
					pD_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] = pD_afScanblock1[i*iImgSizeX0*iImgSizeY0 + j] / vMax[i];
				}
			}
		}
		vMax.clear();

		//写入新的tif
		const char* pszDstFilename = newTiff.c_str();
		GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
		GDALDataset* poDstDS = poDriver->Create(pszDstFilename, iImgSizeX0, iImgSizeY0, nCount, gdal_data_type, NULL);
		poDstDS->SetProjection(poDataset->GetProjectionRef());//给它设置投影
		poDstDS->SetGeoTransform(padfTransform0);//给设置空间转换的六参数
		for (int i = 0; i < nCount; i++)
		{
			poDstDS->GetRasterBand(i + 1)->SetNoDataValue(dnodata);//将空值设置为“无数据值”
		}
		//保存全波段影像
		poDstDS->RasterIO(GF_Write, 0, 0, iImgSizeX0, iImgSizeY0, pD_afScanblock1, iImgSizeX0, iImgSizeY0, gdal_data_type, nCount, panBandMap, 0, 0, 0);

		//释放内存
		GDALClose(poDstDS);
		GDALClose(poDataset);
		delete[]pD_afScanblock1;
		break;
	}
	default: break;
	}
	delete[]panBandMap;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-05 12:17:23  更:2021-12-05 12:17:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:41:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码