图像放缩之临近点插值

简介: 一:数学原理 当一幅二维数字图像从源图像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;
	}

}


目录
相关文章
|
5月前
|
算法 API 计算机视觉
图像处理之角点检测与亚像素角点定位
图像处理之角点检测与亚像素角点定位
64 1
|
5月前
|
算法 计算机视觉
扭曲
【6月更文挑战第29天】
58 0
|
5月前
|
算法 Python
扭曲图像 鼻子拉伸
【6月更文挑战第28天】
26 0
|
5月前
|
算法 Shell
图像放缩之临近点插值
图像放缩之临近点插值
31 0
|
5月前
|
算法 Java
图像放缩之双立方插值
图像放缩之双立方插值
38 0
|
5月前
|
算法 C语言 计算机视觉
图像处理之图像快速插值放缩算法
图像处理之图像快速插值放缩算法
34 0
|
5月前
|
Web App开发 算法 Java
图像放缩之双线性内插值
图像放缩之双线性内插值
25 0
|
6月前
|
计算机视觉
图像直方图
以下是内容摘要: 本文介绍了直方图在图像处理中的应用,包括图像增强和图像分割。直方图均衡化用于改善图像的亮度分布,而根据直方图可获取分割阈值以实现图像分割。此外,直方图对比有助于图像分类。直方图是表示图像亮度分布的图表,通过分析直方图的峰值可判断图像属于低调、中间调还是高调。直方图均衡化则能将图像转换为灰度分布更均匀的新图像。
59 0
|
机器学习/深度学习 传感器 数据采集
基于Zernike矩实现亚像素边缘检测附matlab代码
基于Zernike矩实现亚像素边缘检测附matlab代码
计算一幅图像的信噪比
计算一幅图像的信噪比
778 0