图像放缩之临近点插值

简介: 图像放缩之临近点插值

一:数学原理


当一幅二维数字图像从源图像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);



四:程序效果



0_1319611768H4Xb.png



五:程序源代码

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;
  }
 
}
相关文章
|
24天前
|
算法 API 计算机视觉
图像处理之角点检测与亚像素角点定位
图像处理之角点检测与亚像素角点定位
16 1
|
25天前
|
算法 Java
图像放缩之双立方插值
图像放缩之双立方插值
12 0
|
25天前
|
算法 C语言 计算机视觉
图像处理之图像快速插值放缩算法
图像处理之图像快速插值放缩算法
19 0
|
25天前
|
Web App开发 算法 Java
图像放缩之双线性内插值
图像放缩之双线性内插值
11 0
|
24天前
|
算法 计算机视觉
图像处理之Lanczos采样放缩算法
图像处理之Lanczos采样放缩算法
13 0
|
11月前
|
机器学习/深度学习 算法 自动驾驶
基于图像特征检测——使用相位拉伸变换(Matlab代码实现)
基于图像特征检测——使用相位拉伸变换(Matlab代码实现)
计算一幅图像的信噪比
计算一幅图像的信噪比
524 0
失真函数、失真矩阵与平均失真
失真函数、失真矩阵与平均失真
184 0
|
编解码
学习:泰勒级数插值的多光谱马赛克图像复原方法综述
学习:泰勒级数插值的多光谱马赛克图像复原方法综述
279 0
学习:泰勒级数插值的多光谱马赛克图像复原方法综述
|
机器学习/深度学习 资源调度 算法
【图像插值】基于稀疏拉普拉斯滤波器处理红绿蓝三种像素实现插值效果附matlab代码
【图像插值】基于稀疏拉普拉斯滤波器处理红绿蓝三种像素实现插值效果附matlab代码