天天看點

使用gdal和java對TIF格式正射影像進行拉普拉斯銳化

拉普拉斯銳化算法是讀取目标像素上下左右四個像素值,将上下左右四個像素值分别減去目标像素值,再将結果之和加上目标像素值作為目标像素最後的值,也就是說當目标像素與周圍像素內插補點較大,那麼計算後會進一步拉大內插補點,突出圖像上物體邊緣部分,達到銳化效果。

一般jgp或者png格式圖像采用Java ImageIO直接讀取所有像素後進行拉普拉斯銳化即可,為了更友善讀取tif格式影像則需要引入gdal。使用gdal讀取tif影像基本資訊,擷取影像寬、高、通道數。一般彩色影像包含RGB三個通道或者還有一個表示透明度的阿爾法通道。RGB通道一般對應tif圖像1、2、3通道,阿爾法通道一般為第4通道。

讀取影像基本資訊:

gdal.AllRegister();
Dataset srcDataset = gdal.Open(srcImage.toString(), gdalconstConstants.GA_ReadOnly);
int width = srcDataset.getRasterXSize();
int height = srcDataset.getRasterYSize();
Driver driver = srcDataset.GetDriver();
int count = srcDataset.GetRasterCount();
           

對tif影像進行拉普拉斯銳化,首先讀取影像資訊後轉為BufferdImage,使用處理BufferdImage的拉普拉斯算法進行處理,之後再将BufferdImage轉為tif圖像。處理過程需要考慮到BufferdImage最大支援的圖像寬和高為26663,而tif格式正射影像沒有這一限制,那麼處理過程需要考慮tif影像寬高是否超限,可以設定當tif影像寬或高超過26000像素就對影像進行拆分處理,如果沒有超限則直接讀取tif影像并轉換為BufferdImage。

具體實作:

if (count <= 3) {
				Dataset destDataset = driver.Create(destImage.toString(), width, height, count);
				destDataset.SetMetadata(srcDataset.GetMetadata_Dict()); 
				Band srcBandR = srcDataset.GetRasterBand(1);
				Band srcBandG = srcDataset.GetRasterBand(2);
				Band srcBandB = srcDataset.GetRasterBand(3);
				Band destBandR = destDataset.GetRasterBand(1);
				Band destBandG = destDataset.GetRasterBand(2);
				Band destBandB = destDataset.GetRasterBand(3);
				
				int xIndex = (int)(width / 26000);
				int yIndex = (int)(height / 26000);
				int innerWidth = width / (xIndex + 1);
				int innerHeight = height / (yIndex + 1);
				BufferedImage innerImage = new BufferedImage(innerWidth, innerHeight, BufferedImage.TYPE_INT_RGB);
				for(int i = 0; i <= yIndex ; i ++) {
					for(int j = 0; j <= xIndex ;j++) {
						for (int y = 0; y < innerHeight; y++) {
							int[] arrayR = new int[innerWidth];
							int[] arrayG = new int[innerWidth];
							int[] arrayB = new int[innerWidth];
							srcBandR.ReadRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayR);
							srcBandG.ReadRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayG);
							srcBandB.ReadRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayB);
							for (int x = 0; x < innerWidth; x++) {
								int valueR = arrayR[x];
								int valueG = arrayG[x];
								int valueB = arrayB[x];
								int rgb = (clamp((int) valueR) & 0xff) << 16 | (clamp((int) valueG) & 0xff) << 8
										| (clamp((int) valueB) & 0xff);
								innerImage.setRGB(x, y, rgb);
							}
							
						}
						innerImage = new LaplacianSharpen().lapLaceSharp(innerImage);
						for (int y = 0; y < innerHeight; y++) {
							int[] arrayR = new int[innerWidth];
							int[] arrayG = new int[innerWidth];
							int[] arrayB = new int[innerWidth];
							for (int x = 0; x < innerWidth; x++) {
								int rgb = innerImage.getRGB(x, y);
								int valueR = (rgb >> 16) & 0xff;
								int valueG = (rgb >> 8) & 0xff;
								int valueB = rgb & 0xff;
								arrayR[x] = valueR;
								arrayG[x] = valueG;
								arrayB[x] = valueB;
							}
							destBandR.WriteRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayR);
							destBandG.WriteRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayG);
							destBandB.WriteRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayB);
						}
					}
				}
				driver.delete();
				srcDataset.delete();
				destDataset.delete();
			}else {
				Dataset destDataset = driver.Create(destImage.toString(), width, height, 4);
				destDataset.SetMetadata(srcDataset.GetMetadata_Dict()); 
				Band srcBandR = srcDataset.GetRasterBand(1);
				Band srcBandG = srcDataset.GetRasterBand(2);
				Band srcBandB = srcDataset.GetRasterBand(3);
				Band destBandR = destDataset.GetRasterBand(1);
				Band destBandG = destDataset.GetRasterBand(2);
				Band destBandB = destDataset.GetRasterBand(3);
				// 讀取資訊
				int xIndex = (int)(width / 26000);
				int yIndex = (int)(height / 26000);
				int innerWidth = width / (xIndex + 1);
				int innerHeight = height / (yIndex + 1);
				BufferedImage innerImage = new BufferedImage(innerWidth, innerHeight, BufferedImage.TYPE_INT_RGB);
				for(int i = 0; i <= yIndex ; i ++) {
					for(int j = 0; j <= xIndex ;j++) {
						for (int y = 0; y < innerHeight; y++) {
							int[] arrayR = new int[innerWidth];
							int[] arrayG = new int[innerWidth];
							int[] arrayB = new int[innerWidth];
							srcBandR.ReadRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayR);
							srcBandG.ReadRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayG);
							srcBandB.ReadRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayB);
							for (int x = 0; x < innerWidth; x++) {
								int valueR = arrayR[x];
								int valueG = arrayG[x];
								int valueB = arrayB[x];
								int rgb = (clamp((int) valueR) & 0xff) << 16 | (clamp((int) valueG) & 0xff) << 8
										| (clamp((int) valueB) & 0xff);
								innerImage.setRGB(x, y, rgb);
							}
							
						}
						innerImage = new LaplacianSharpen().lapLaceSharp(innerImage);
						for (int y = 0; y < height; y++) {
							int[] arrayR = new int[innerWidth];
							int[] arrayG = new int[innerWidth];
							int[] arrayB = new int[innerWidth];
							for (int x = 0; x < innerWidth; x++) {
								int rgb = innerImage.getRGB(x, y);
								int valueR = (rgb >> 16) & 0xff;
								int valueG = (rgb >> 8) & 0xff;
								int valueB = rgb & 0xff;
								arrayR[x] = valueR;
								arrayG[x] = valueG;
								arrayB[x] = valueB;
							}
							destBandR.WriteRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayR);
							destBandG.WriteRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayG);
							destBandB.WriteRaster(j * innerWidth, i * innerHeight + y, innerWidth, 1, arrayB);
						}
					}
				}
				Band srcBand = srcDataset.GetRasterBand(4);
				Band destBand = destDataset.GetRasterBand(4);
				for (int y = 0; y < height; y++) {
					int[] array = new int[width];
					srcBand.ReadRaster(0, y, width, 1, array);
					destBand.WriteRaster(0, y, width, 1, array);
				}
				driver.delete();
				srcDataset.delete();
				destDataset.delete();
			}
		
           

處理前影像:

使用gdal和java對TIF格式正射影像進行拉普拉斯銳化

處理後影像:

使用gdal和java對TIF格式正射影像進行拉普拉斯銳化