计算机视觉
图像处理

图像放缩——临近点插值

一:数学原理

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

 

四:程序效果

五:程序源代码

 

    < style="font-weight: normal;">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);  
        }  
          
        /* The purpose of this method is to convert the data in the 3D array of ints back into  
         * the 1d array of type int. 
         *  
         */  
        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;  
        }  
      
    }  
     

转载注明来源:CV视觉网 » 图像放缩——临近点插值

分享到:更多 ()
扫描二维码,给作者 打赏
pay_weixinpay_weixin

请选择你看完该文章的感受:

0不错 0超赞 0无聊 0扯淡 0不解 0路过

评论 抢沙发

评论前必须登录!