基于GDAL的多波段图像压缩及二值分割

5 篇文章 0 订阅
4 篇文章 0 订阅

多波段图像压缩及二值分割

内容概述

将多波段各个像素灰度值加和,并且在保留仿射参数和投影信息情况下生成单波段图像,用于经典算法(otsu,em等)本文将以otsu为例,生成简单二值图像
原基于pie二次开发,摘取部分函数算法成文,记录学习过程,有需求的话后续会分享pie二次开发学习过程

环境

语言:C++【100%】
vs版本:【2015】
GDAL版本:【2.3.X】
OPENCV版本:【3.x】

多波段图像压缩

将多波段各个像素灰度值加和,并且在保留仿射参数和投影信息情况下生成单波段图像,用于经典算法(otsu,em等)本文将以otsu为例

代码部分

注释标注的还算全面

头文件

#pragma once
#define BYTE unsigned char

class Arr
{
public:
	int imgX = 0;
	int imgY = 0;
	GDALDataType datatype;
	
	double* EndArr = new double[imgX * imgY];
	BYTE *EndImg = (BYTE *)CPLMalloc(sizeof(double)*imgX*imgY);

};


void GdalAlgo(const char* filepath1, const char* filepath2, Arr &arr);

源文件

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

using namespace std;


void toGeoCoord(int x, int y, double* coords, double* transform)
{
	coords[0] = transform[0] + x * transform[1] + y * transform[2];
	coords[1] = transform[3] + x * transform[4] + y * transform[5];
}

void GdalAlgo(const char* filepath1, const char* filepath2, Arr &arr)
{
	GDALAllRegister(); //注册驱动

	GDALDataset* PD1;//建立数据集读第一张图片
	PD1 = (GDALDataset*)GDALOpen(filepath1, GA_ReadOnly);//指针指向文件路径
	if (PD1 == NULL)
	{
		//openfail
		return;
	}
	int iXSize1 = PD1->GetRasterXSize();//获取图像的宽
	int iYSize1 = PD1->GetRasterYSize();//获取图像的高
	int iBandCount1 = PD1->GetRasterCount();//获取图像的波段数
	GDALDataType datatype1 = PD1->GetRasterBand(1)->GetRasterDataType();//获取影像数据类型
	//######################################################
	double adfGeoTransform[6];//获取仿射变换六参数信息
	PD1->GetGeoTransform(adfGeoTransform);
	const char* pszProj = PD1->GetProjectionRef(); // 获得WKT形式的投影信息
	//通过仿射变换将影像左上角和右下角行列号坐标转化为地理坐标
	double adfULCoord[2];
	double adfLRCoord[2];
	toGeoCoord(0, 0, adfULCoord, adfGeoTransform);
	toGeoCoord(iYSize1 - 1, iYSize1 - 1, adfLRCoord, adfGeoTransform);
	//########################################################

	GDALDataset* PD2;//建立数据集读第二张图片 
	PD2 = (GDALDataset*)GDALOpen(filepath2, GA_ReadOnly);//指针指向文件路径
	if (PD2 == NULL)
	{
		//openfail
		return;
	}
	int iXSize2 = PD2->GetRasterXSize();//获取图像的宽
	int iYSize2 = PD2->GetRasterYSize();//获取图像的高
	int iBandCount2 = PD2->GetRasterCount();//获取图像的波段数
	GDALDataType datatype2 = PD2->GetRasterBand(1)->GetRasterDataType();//获取影像数据类型


	if (iXSize1 == iXSize2 && iYSize1 == iYSize2 && iBandCount1 == iBandCount2 && datatype1 == datatype2)//鲁棒
	{
		int imgX = iXSize1; int imgY = iYSize1; GDALDataType datatype = datatype1;
		arr.imgX = imgX; arr.imgY = imgY; arr.datatype = datatype;//对象获得长宽及数据类型
		
		int size_m1 = sizeof(double)*imgX*imgY;
		BYTE *pData1 = (BYTE *)CPLMalloc(size_m1); // 分配内存1

		int size_m2 = sizeof(double)*imgX*imgY;
		BYTE *pData2 = (BYTE *)CPLMalloc(size_m2); // 分配内存2

		int size_m3 = sizeof(double)*imgX*imgY;
		BYTE *pData3 = (BYTE *)CPLMalloc(size_m3); // 分配内存3

		double *tempp1 = new double[imgX * imgY];// 分配临时内存
		double *tempp2 = new double[imgX * imgY];// 分配临时内存
		double *tempp3 = new double[imgX * imgY];// 分配临时内存
		for (int i = 0; i < imgX; i++)//初始化(也可置于下方循环中)
		{
			for (int j = 0; j < imgY; j++)
			{
				tempp1[i * imgX + j] = 0;
				tempp2[i * imgX + j] = 0;
				tempp3[i * imgX + j] = 0;
			}
		}

		for (int ibands = 1; ibands <= iBandCount1; ibands++)//将多波段图像压缩为单波段图像(一维数组),为传入otsu算法做准备
		{
			GDALRasterBand *poBand1 = PD1->GetRasterBand(ibands);
			GDALRasterBand *poBand2 = PD2->GetRasterBand(ibands);

			poBand1->RasterIO(GF_Read, 0, 0, imgX, imgY, pData1, imgX, imgY, GDT_Byte, 0, 0);
			poBand2->RasterIO(GF_Read, 0, 0, imgX, imgY, pData2, imgX, imgY, GDT_Byte, 0, 0);

			for (int i = 0; i < imgY; i++)//循环获得整图所有波段累计灰度值
			{
				for (int j = 0; j < imgX; j++)
				{
					tempp1[i * imgY + j] += pData1[i * imgY + j];
					tempp2[i * imgY + j] += pData2[i * imgY + j];

					//pData3[i * imgX + j] += pData4[i * imgX + j];
					//pData4[i * imgX + j] = pData1[i * imgX + j] - pData2[i * imgX + j];
				}
			}
		}
		for (int i = 0; i < imgY; i++)//做差获得2时相的一维灰度差
		{
			for (int j = 0; j < imgX; j++)
			{
			
				pData3[i * imgY + j] = fabs(tempp1[i * imgY + j] - tempp2[i * imgY + j]);
				tempp3[i * imgY + j] = fabs(tempp1[i * imgY + j] - tempp2[i * imgY + j]);
		
				//此段数据转换留于自行试写
				//BYTE tempa;
				//tempa = static_cast<BYTE>(a3);
			}
		}
		arr.EndArr = tempp3;//对象获得最终 double 类型一维数组
		arr.EndImg = pData3;//对象获得最终 无数据 类型一维数组
	}


	GDALDriver* tempDriver;//写图像驱动
	GDALDataset* tempData;
	const char* pszFormat = "GTiff";
	const char* pszDstFile = "NewPic.tif";
	tempDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
	tempData = tempDriver->Create(pszDstFile, arr.imgX, arr.imgY, 1, GDT_Byte, NULL);//创建文件用来写入计算后的数据

	GDALRasterBand* temptif = tempData->GetRasterBand(1);
	tempData->SetGeoTransform(adfGeoTransform);
	tempData->SetProjection(pszProj);
	temptif->RasterIO(GF_Write, 0, 0, arr.imgX, arr.imgY, arr.EndImg, arr.imgX, arr.imgY, GDT_Byte, 0, 0);//写temp图像完成
	
    //release space
    GDALClose(tempData);
	delete PD1;
	delete PD2;

	
}

原代码有调用qt部分,已做更改,打包即用。
突然懒得写了,后续代码心情好了再补上XD

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于 GDAL 库的像显示系统是一种用于读取、处理和显示地理空间数据的软件系统。GDAL(Geospatial Data Abstraction Library)是一个开源的地理空间数据抽象库,可以支持多种格式的地理空间数据,如栅格像、矢量数据和地理数据库。 通过 GDAL 库,可以实现对各种格式的栅格像数据的读取和显示。系统可以读取并解析栅格像文件,提取其中的地理空间信息,然后将像数据以像形式显示出来。同时,系统还可以进行一些像处理操作,如像的裁剪、缩放、旋转等。 在基于 GDAL 库的像显示系统中,用户可以通过简单的操作界面进行地理空间数据的导入和操作。用户可以直接选择要显示的像文件,系统会自动识别像格式并读取像数据。用户还可以选择要显示的地理范围,系统会根据用户选择进行像的裁剪和放大缩小。 基于 GDAL 库的像显示系统还具备与其他地理信息系统(GIS)软件的互操作能力。通过 GDAL 库提供的接口,可以方便地将像数据与其他 GIS 数据进行集成和分析。系统还支持地理坐标系的转换和投影,使用户可以在不同的地理坐标系之间进行数据的转换和比较分析。 综上所述,基于 GDAL 库的像显示系统是一种功能强大、易于使用的地理空间数据处理和显示工具。它可以读取、处理和显示各种格式的栅格像数据,并支持与其他 GIS 软件的互操作。这种系统在地理信息领域的应用广泛,可以满足用户对地理空间数据的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值