java+gdal实现影像重投影

java+gdal实现影像重投影

GDAL功能很强大,用来处理影像数据,今天我要做的是java代码写的影像重投影,网上参考资料大都是c++和python写的,也看了一些大牛写的代码,最后写出了java版的,eclipse写的,直接引用一个gdal.jar包,不过要有一些dll文件,网上有相关的java配置jdal库的博客,不配置jdal会报错:本地库错误。还有对于gdal读取六参数geoTransform的理解,我在这方面没理解好,耗费了一些时间,会在下文讲到。我的源数据与目标数据具有相同的基准面,属于严密转换,实现起来较为简单。实现重投影要需要以下几个步骤:

  • 源影像仿射变换系数及投影获取
  • 目标影像信息写入
  • ReprojectImage重新投影
  • 重采样(本人需求)

参考博文:
1.GDAL库学习笔记(三):GDAL创建数据集
2.GDAL之栅格重投影
3.GDAL影像投影转换

以上博文中,1和3是用C++写的代码,2是用python写的。关于背景知识以上博文讲诉的较为详细,这里只做简单描述:

影像要进行投影转换,首先要自带坐标系,然后看源影像坐标系统和目标坐标系统。本文进行的是严密转换,同一基准面下的地理坐标系转到投影坐标系。

现将java代码中用的GDAl主要函数列出来,做简要说明:

GetProjectionRef() 获取源影像的坐标参考
GetGeoTransform() 读取六参数,具体含义参考以上引用博文
CloneGeogCS() 获取一个投影系中的地理系,投影坐标系是地理坐标投影的结果,
CoordinateTransformation ct = new CoordinateTransformation(src_Crs, oLatLong);两种坐标系统的变换关系
ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int eResampleAlg)实现重投影的函数

先在eclipse中新建工程->包->类,导入gdal.jar包,配置好gdal(实际运行在dll),以下是参考代码,注释较为详细,可以更改:

package readTifftest;

import org.gdal.gdal.Dataset;
import org.gdal.gdal.Driver;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
import org.gdal.osr.CoordinateTransformation;
import org.gdal.osr.SpatialReference;


/**
 * 
 * @author Administrator
 * @ClassName:Resample
 * @Version 版本
 * @ModifiedBy 修改人
 * @date 2018年1月16日 下午2:49:43
 */
public class GDAL_Resample {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Resample("E:\\database\\overview\\J46_弃用\\J46D001010.png","E:\\database\\overview\\J46\\J46D001010.tif");

	}
	/**
	 * 影像投影转换并重采样得到输出影像,同一个椭球体基准面下的转换就是严密的转换
	 * @param input  输入影像路径
	 * @param output 输出影像路径
	 */
	public static void Resample(String input,String output){
		//String agentfile=output.substring(0, output.lastIndexOf("."))+".tif";
		//注册GDAL
		gdal.AllRegister();
		//只读方式读取数据
		Dataset pSrc = gdal.Open(input,gdalconstConstants.GA_ReadOnly);
		if (pSrc == null)
			return;
		//打开的影像像素、波段等信息
		int numBands=pSrc.GetRasterCount(); //读取影像波段数
		int xSize = pSrc.GetRasterXSize();//栅格尺寸
		int ySize = pSrc.GetRasterYSize();//
        int depth=pSrc.GetRasterBand(1).GetRasterDataType();//图像深度
       
		String src_wkt=pSrc.GetProjectionRef();//获取源图像crs
		
		SpatialReference src_Crs=new SpatialReference(src_wkt);//构造投影坐标系统的空间参考(wkt)

	    double[] geoTransform = pSrc.GetGeoTransform();		
	    //图像范围
		double xmin = geoTransform[0];
		double ymax = geoTransform[3];
		double w_src = geoTransform[1];//像素宽度
		double h_src = geoTransform[5];//像素高度
		double xmax = geoTransform[0] + xSize * w_src;
		double ymin = geoTransform[3] + ySize * h_src;

		//设置输出图像的坐标 
		SpatialReference oLatLong; 	
        oLatLong = src_Crs.CloneGeogCS(); //获取该投影坐标系统中的地理坐标系   
        //构造一个从投影坐标系到地理坐标系的转换关系  
        CoordinateTransformation ct = new CoordinateTransformation(src_Crs, oLatLong);
        
        // 此注释为错误计算过程  
//        double dst1[]=ct.TransformPoint(xmin,ymax);
//        double dst2[]=ct.TransformPoint(xmax,ymin);
//		double dstxmin = dst1[0];
//		double dstymax = dst1[1];
//		double dstxmax = dst2[0];
//		double dstymin = dst2[1]; //39.67609572370327

		//计算目标影像的左上和右下坐标,即目标影像的仿射变换参数,投影转换为经纬度
		double a[]= ct.TransformPoint(xmin, ymax);
		double b[]= ct.TransformPoint(xmax, ymax);
		double c[]= ct.TransformPoint(xmax, ymin);
		double d[]= ct.TransformPoint(xmin, ymin);     
		double dbX[]={a[0],b[0],c[0],d[0]};
		double dbY[]={a[1],b[1],c[1],d[1]};

		GDAL_Resample test=new GDAL_Resample();
        test.res(dbX);//按从小到大排列
        double dstxmin=dbX[0];
        double dstxmax=dbX[3];
        test.res(dbY);
        double dstymin=dbY[0];
        double dstymax=a[1];
        double[] adfGeoTransform=new double[6];
        adfGeoTransform[0]=dstxmin;
        adfGeoTransform[3]=dstymin;
        adfGeoTransform[1]=(dbX[3]-dbX[0])/xSize;
        adfGeoTransform[5]=(dbY[3]-dbY[0])/ySize;
        //adfGeoTransform[2]=(dstxmax-adfGeoTransform[0]-xSize*adfGeoTransform[1])/ySize;
       // adfGeoTransform[4]=(dbY[3]-adfGeoTransform[3]-ySize*adfGeoTransform[5])/xSize;
        
        //创建输出图像
		Driver driver = gdal.GetDriverByName("GTiff"); 
		driver.Register();  
		String[] options={"INTERLEAVE=PIXEL"};
		Dataset pDst = driver.Create(output,xSize,ySize,numBands,depth,options);
	
		//写入仿射变换系数及投影 
		String dst_wkt=oLatLong.ExportToWkt();
		pDst.SetGeoTransform(adfGeoTransform);
		pDst.SetProjection(dst_wkt);
		
		/*eResampleAlg采样模式
		 * GRA_NearestNeighbour=0   最近邻法,算法简单并能保持原光谱信息不变;缺点是几何精度差,灰度不连续,边缘会出现锯齿状     
           GRA_Bilinear=1         双线性法,计算简单,图像灰度具有连续性且采样精度比较精确;缺点是会丧失细节; 
           GRA_Cubic=2            三次卷积法,计算量大,图像灰度具有连续性且采样精度高; 
           GRA_CubicSpline=3      三次样条法,灰度连续性和采样精度最佳; 
           GRA_Lanczos=4          分块兰索斯法,由匈牙利数学家、物理学家兰索斯法创立,实验发现效果和双线性接近; 
		 */
		//重新投影
		gdal.ReprojectImage(pSrc, pDst, src_wkt, dst_wkt, 3);
		  
		pDst.delete();
		pSrc.delete();
	}
	/**
	 * 比较大小,得到最大值与最小值
	 * @param arr
	 * @return
	 */
	  public double[] res(double[] arr){
	        for(int i=0;i<arr.length;i++){
	            for(int j=0;j<arr.length-i-1;j++){
	                 
	                if(arr[j]>arr[j+1]){
	                    double temp=arr[j];
	                    arr[j]=arr[j+1];
	                    arr[j+1]=temp;
	                }
	            }
	        }	             
	        return arr;         
	    }
}

以上就是全部代码,还不完整,java新手,代码变量命名没有很注意,不过注释上说的比较详细。
不断更新中,欢迎留言交流。

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值