图像放缩之临近点插值

简介: 一:数学原理 当一幅二维数字图像从源图像N*M被放为(j*N) * (k*M)目标图像是,参照数学斜率计算公式 必然有: (X1 – Xmin)/(Xmax - Xmin) = (Y1 - Ymin)/(Ymax-Ymin)   当Xmin 和 Ymin均为从零开始的像素点时,公式...

一:数学原理

当一幅二维数字图像从源图像N*M被放为(j*N) * (k*M)目标图像是,参照数学斜率计算公式

必然有:

(X1 – Xmin)/(Xmax - Xmin) = (Y1 - Ymin)/(Ymax-Ymin)

 

当Xmin 和 Ymin均为从零开始的像素点时,公式可以简化为:

         X=Y1 (Xmax/Ymax)

 

对于任意一幅源图像来说,假设放大后目标图像的宽为Dw高为Dh,任意目标像素点(Dx, Dy)

在源图像上的位置为:

         Sx= Dx * (Sh/Dh) // row

         Sy= Dy * (Sw/Dw) // column

 

其中,(Sx,Sy)为对于的源图像上的像素点,Sw和Sh分别为源图像的宽度和高度。最终有

         Dpixel(Dx,Dy) = Spixel(Sx, Sy);

 

二:临近点插值算法的缺点

临近点插值算法会产生锯齿效果, 不是一个很好的图像放缩算法,临近点插值算法不改变源

像素点到目标像素点的值,只是最简单的位置匹配而已,相比之下,双线性内插值算法和双

立方插值算法效果更好,但是计算量更大,临近点插值是计算量最小的防缩算法。

 

三:关键程序代码解释

从BufferedImage对象中获取像素数组的代码如下:

int type = img.getType();

if ( type == BufferedImage.TYPE_INT_ARGB ||

type == BufferedImage.TYPE_INT_RGB ) {

    img.getRaster().setDataElements(x, y,width,height, pixelsData);

}

else {

    img.setRGB(x, y, width, height, pixelsData, 0, width);

}

 

从源图像对象一维像素数组转换为三维对象数组,代码如下:

int[][][] tempData = new int[imgRows][imgCols][4];

tempData[row][col][0] =(aRow[col] >> 24) & 0xFF; // alpha

tempData[row][col][1] =(aRow[col] >> 16) & 0xFF; // red

tempData[row][col][2] =(aRow[col] >> 8) & 0xFF;  // green

tempData[row][col][3] = (aRow[col]) &0xFF;       // blue

 

首先要计算行与列的缩放比例,计算代码如下:

float rowRatio = ((float)srcH)/((float)destH);

float colRatio = ((float)srcW)/((float)destW);

 

计算源像素点的行位置:

int srcRow = Math.round(((float)row)*rowRatio);

 

计算源像素点的列位置:

int srcCol = Math.round(((float)col)*colRatio);

 

四:程序效果



五:程序源代码

public class NearNaighborZoom implements ImageScale {
	
	public NearNaighborZoom() {
		
	}

	/**
	 * (X-Xmin)/(Xmax-Xmin) = (Y-Ymin)/(Ymax-Ymin)
	 * assume Xmin and Ymin are zero, then the formula will be f(x) = kx (k - coefficent, slope)
	 * 
	 */
	@Override
	public int[] imgScale(int[] inPixelsData, int srcW, int srcH, int destW, int destH) {
		int[][][] inputThreeDeminsionData = processOneToThreeDeminsion(inPixelsData, srcH, srcW);
		int[][][] outputThreeDeminsionData = new int[destH][destW][4];
		float rowRatio = ((float)srcH)/((float)destH);
		float colRatio = ((float)srcW)/((float)destW);
		for(int row=0; row<destH; row++) {
			// convert to three dimension data
			int srcRow = Math.round(((float)row)*rowRatio);
			if(srcRow >=srcH) {
				srcRow = srcH - 1;
			}
			for(int col=0; col<destW; col++) {
				int srcCol = Math.round(((float)col)*colRatio);
				if(srcCol >= srcW) {
					srcCol = srcW - 1;
				}
				outputThreeDeminsionData[row][col][0] = inputThreeDeminsionData[srcRow][srcCol][0]; // alpha
				outputThreeDeminsionData[row][col][1] = inputThreeDeminsionData[srcRow][srcCol][1]; // red
				outputThreeDeminsionData[row][col][2] = inputThreeDeminsionData[srcRow][srcCol][2]; // green
				outputThreeDeminsionData[row][col][3] = inputThreeDeminsionData[srcRow][srcCol][3]; // blue
			}
		}
		return convertToOneDim(outputThreeDeminsionData, destW, destH);
	}
	
	/* <p> The purpose of this method is to convert the data in the 3D array of ints back into </p>
	 * <p> the 1d array of type int. </p>
	 * 
	 */
	public int[] convertToOneDim(int[][][] data, int imgCols, int imgRows) {
		// Create the 1D array of type int to be populated with pixel data
		int[] oneDPix = new int[imgCols * imgRows * 4];

		// Move the data into the 1D array. Note the
		// use of the bitwise OR operator and the
		// bitwise left-shift operators to put the
		// four 8-bit bytes into each int.
		for (int row = 0, cnt = 0; row < imgRows; row++) {
			for (int col = 0; col < imgCols; col++) {
				oneDPix[cnt] = ((data[row][col][0] << 24) & 0xFF000000)
						| ((data[row][col][1] << 16) & 0x00FF0000)
						| ((data[row][col][2] << 8) & 0x0000FF00)
						| ((data[row][col][3]) & 0x000000FF);
				cnt++;
			}// end for loop on col

		}// end for loop on row

		return oneDPix;
	}// end convertToOneDim
	
	private int[][][] processOneToThreeDeminsion(int[] oneDPix2, int imgRows, int imgCols) {
		int[][][] tempData = new int[imgRows][imgCols][4];
		for(int row=0; row<imgRows; row++) {
			
			// per row processing
			int[] aRow = new int[imgCols];
			for (int col = 0; col < imgCols; col++) {
				int element = row * imgCols + col;
				aRow[col] = oneDPix2[element];
			}
			
			// convert to three dimension data
			for(int col=0; col<imgCols; col++) {
				tempData[row][col][0] = (aRow[col] >> 24) & 0xFF; // alpha
				tempData[row][col][1] = (aRow[col] >> 16) & 0xFF; // red
				tempData[row][col][2] = (aRow[col] >> 8) & 0xFF;  // green
				tempData[row][col][3] = (aRow[col]) & 0xFF;       // blue
			}
		}
		return tempData;
	}

}


目录
相关文章
|
4月前
|
文件存储
AvaSpec-ULS2048光谱仪测定地物高光谱曲线的方法
AvaSpec-ULS2048光谱仪测定地物高光谱曲线的方法
|
8月前
|
机器学习/深度学习 算法 自动驾驶
基于图像特征检测——使用相位拉伸变换(Matlab代码实现)
基于图像特征检测——使用相位拉伸变换(Matlab代码实现)
|
9月前
|
存储 数据可视化 索引
校正图像亮度不均匀问题并分析前景对象
校正图像亮度不均匀问题并分析前景对象
62 0
|
9月前
|
机器学习/深度学习 传感器 数据采集
基于Zernike矩实现亚像素边缘检测附matlab代码
基于Zernike矩实现亚像素边缘检测附matlab代码
|
10月前
计算一幅图像的信噪比
计算一幅图像的信噪比
383 0
|
12月前
|
机器学习/深度学习 传感器 编解码
基于二维连续小波变换条纹图相位提取方法附matlab代码
基于二维连续小波变换条纹图相位提取方法附matlab代码
144.绘制布朗运动曲线
144.绘制布朗运动曲线
80 0
|
编解码
学习:泰勒级数插值的多光谱马赛克图像复原方法综述
学习:泰勒级数插值的多光谱马赛克图像复原方法综述
251 0
学习:泰勒级数插值的多光谱马赛克图像复原方法综述
|
机器学习/深度学习 资源调度 算法
【图像插值】基于稀疏拉普拉斯滤波器处理红绿蓝三种像素实现插值效果附matlab代码
【图像插值】基于稀疏拉普拉斯滤波器处理红绿蓝三种像素实现插值效果附matlab代码
|
机器学习/深度学习 编解码 算法
【图像检测-边缘检测】基于插值法实现亚像素边缘检测含Matlab源码
【图像检测-边缘检测】基于插值法实现亚像素边缘检测含Matlab源码