數字圖像縮放之最近鄰插值與雙線性插值處理效果對比

基本原理

1、最近鄰插值:變換後的目標圖像某點像素值等於源圖像中與變換前相應點最近的點的像素值。具體操作爲,設水平方向和垂直方向縮放的比例分別爲w和h,那麼目標圖像中的點des(x,y)對應的源圖像中的點src的座標爲(x0,y0)=(x/w,y/h)。其中,x0,y0可能爲小數,故對其四捨五入,即(x0,y0)=int(x0+0.5,y0+0.5),因此點des(x,y)的像素值就是點src(x0,y0)的像素值。

2、雙線性插值:由1中最近鄰插值中的四捨五入前的點src(x0,y0)得到它的2*2區域4個鄰域像素點的座標,即(x1,y1)=(int(x0),int(y0))(x1,y2)=int(x1,y1+1),(x2,y1)=(x1+1,y1),(x2,y2)=(x1+1,y1+1),然後計算權重q1=(x0-x1)*(y0-y1),q2=(1.0-(x0-x1))*(y0-y1),q4=(x0-x1)*(1.0-(y0-y1)),q3=(1.0-(x0-x1))*(1.0-(y0-y1),用value(x,y)表示點(x,y)處的像素值,則目標圖像中的點des(x,y)對應像素值value(x,y)=value(x2,y2)*q1+value(x1,y2)*q2+value(x1,y1)*q3+value(x2,y1)*q4,


c/c++實現及處理效果:

1、最近鄰插值

void GeometryTrans::Zoom(float ratioX, float ratioY)
{
	
	//釋放舊的輸出圖像緩衝區
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}
    
	//輸出圖像的寬和高
	m_imgWidthOut=int(m_imgWidth*ratioX+0.5) ;
	m_imgHeightOut=int(m_imgHeight*ratioY+0.5); 

	//輸入圖像每行像素字節數
	int lineByteIn=(m_imgWidth*m_nBitCount/8+3)/4*4;
	
	//輸出圖像每行像素字節數
    int	lineByteOut=(m_imgWidthOut*m_nBitCount/8+3)/4*4;

	//申請緩衝區,存放輸出結果
	m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeightOut];

	//每像素字節數,輸入圖像與輸出圖像相同
	int pixelByte=m_nBitCount/8;
	
	//輸出圖像在輸入圖像中待插值的位置座標
	int coordinateX, coordinateY;
	
	//循環變量,輸出圖像的座標
	int i, j;
	
	//循環變量,像素的每個通道
	int k;
	
	//近鄰插值
	for(i=0; i< m_imgHeightOut; i++){
		for(j=0; j<m_imgWidthOut; j++){  
			//輸出圖像座標爲(j,i)的像素映射到原圖中的座標值,即插值位置
			coordinateX=j/ratioX+0.5;
			coordinateY=i/ratioY+0.5;
			
			//若插值位置在輸入圖像範圍內,則近鄰插值
			if(0<=coordinateX&&coordinateX<m_imgWidth
				&& coordinateY>=0&&coordinateY<m_imgHeight){
				for(k=0;k<pixelByte;k++)
					*(m_pImgDataOut + i * lineByteOut + j*pixelByte + k) 
					=*(m_pImgData+ coordinateY*lineByteIn+ coordinateX*pixelByte + k) ;
			}
			else //若不在輸入圖像範圍內,則置255  
			{
				for(k=0;k<pixelByte;k++)
					*(m_pImgDataOut + i * lineByteOut + j*pixelByte+k) = 255;
			}			
		}
	}
}

wKioL1gQxZnzPc5LAAkEOFuNwLo384.bmp-wh_50

2、雙線性插值

void GeometryTrans::Zoom(float ratioX, float ratioY)
{
	
	//釋放舊的輸出圖像緩衝區
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
    	m_pImgDataOut=NULL;
	}
    
	//輸出圖像的寬和高
	m_imgWidthOut=int(m_imgWidth*ratioX+0.5) ;
	m_imgHeightOut=int(m_imgHeight*ratioY+0.5); 

	//輸入圖像每行像素字節數
	int lineByteIn=(m_imgWidth*m_nBitCount/8+3)/4*4;
	
	//輸出圖像每行像素字節數
    int	lineByteOut=(m_imgWidthOut*m_nBitCount/8+3)/4*4;

	//申請緩衝區,存放輸出結果
	m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeightOut];

	//每像素字節數,輸入圖像與輸出圖像相同
	int pixelByte=m_nBitCount/8;
	
	//輸出圖像在輸入圖像中待插值的位置座標
	float coordinateX, coordinateY;
	
	//循環變量,輸出圖像的座標
	int i, j;
	
	//循環變量,像素的每個通道
	int k;

	int y1,y2, x1,x2;
    float fx1,fx2, fy1, fy2;
	
	//雙線性插值
	for(i=0; i< m_imgHeightOut; i++)
	{
		coordinateY = i/ratioY;
        y1 = (int)coordinateY;
        if(y1 == m_imgHeightOut-1)    
			y2 = y1;
        else y2 = y1 + 1;

		fy1 = coordinateY-y1; 
        fy2 = (float)1.0 - fy1;

		for(j=0; j<m_imgWidthOut; j++)
		{  
			coordinateX = j/ratioX;
            x1 = (int)coordinateX;
            if(x1 == m_imgWidthOut-1)    
				x2 = x1;
            else x2 = x1+1;

			fx1 = coordinateX-x1;
            fx2 = (float)1.0 - fx1;
			//所求的源圖像中的2*2區域4個鄰近象素點座標爲(x1, y1) (x1, y2) (x2, y1) (x2,y2)
            //計算4個權重
            float s1 = fx1*fy1;
            float s2 = fx2*fy1;
            float s3 = fx2*fy2;
            float s4 = fx1*fy2;
			//輸出圖像座標爲(j,i)的像素映射到原圖中的座標值,即插值位置
			
			//若插值位置在輸入圖像範圍內,則雙線性插值
			if(0<=coordinateX&&coordinateX<m_imgWidth
				&& coordinateY>=0&&coordinateY<m_imgHeight)
			{
				for(k=0;k<pixelByte;k++)
					*(m_pImgDataOut + i * lineByteOut + j*pixelByte + k) 
					=(int)((*(m_pImgData+ y2*lineByteIn+ x2*pixelByte + k))*s1+
					       (*(m_pImgData+ y2*lineByteIn+ x1*pixelByte + k))*s2+
					       (*(m_pImgData+ y1*lineByteIn+ x1*pixelByte + k))*s3+
					       (*(m_pImgData+ y1*lineByteIn+ x2*pixelByte + k))*s4);
			}
			else //若不在輸入圖像範圍內,則置255  
			{
				for(k=0;k<pixelByte;k++)
					*(m_pImgDataOut + i * lineByteOut + j*pixelByte+k) = 255;
			}
			
		}
	}


}

wKioL1gQxgnyMO4QAAkEOCAxju0180.bmp-wh_50


總結:由處理效果可知,最近鄰插值有鋸齒現象,灰度值不連續,而雙線性插值灰度值連續,圖像比較平滑。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章