<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    圖像編程學習筆記3――圖像旋轉

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    以下文字內容copy于<<數字圖像處理編程入門>>,code為自己實現,是win32控制臺程序。

     

    旋轉(rotation)有一個繞著什么轉的問題,通常的做法是以圖象的中心為圓心旋轉,舉個例子,圖2.7旋轉30度(順時針方向)后如圖2.8所示:

    RFID設備管理軟件

    可以看出,旋轉后圖象變大了。另一種做法是不讓圖象變大,轉出的部分被裁剪掉。如圖2.9所示。

    我們采用第一種做法,首先給出變換矩陣。在我們熟悉的坐標系中,將一個點順時針旋轉a角后的坐標變換公式,如圖2.10所示,r為該點到原點的距離,在旋轉過程中,r保持不變;b為r與x軸之間的夾角。

                                                                 RFID設備管理軟件

    旋轉前:x0=rcosb;y0=rsinb

    旋轉a角度后:

    x1=rcos(b-a)=rcosbcosa+rsinbsina= x0cosa+y0sina;

    y1=rsin(b-a)=rsinbcosa-rcosbsina= -x0sina+y0cosa;

    以矩陣的形式表示:

                                                                                               RFID設備管理軟件(2.5)

    上面的公式中,坐標系xoy是以圖象的中心為原點,向右為x軸正方向,向上為y軸正方向。它和以圖象左上角點為原點o’,向右為x’軸正方向,向下為y’軸正方向的坐標系x’o’y’之間的轉換關系如何呢?如圖2.11所示。

    RFID設備管理軟件

     

    圖2.11    兩種坐標系間的轉換關系

    設圖象的寬為w,高為h,容易得到:

                                                                                           RFID設備管理軟件(2.6)

    逆變換為:

                                                                                            RFID設備管理軟件(2.7)

    有了上面的公式,我們可以把變換分成三步:

    1.將坐標系o’變成o;

    2.將該點順時針旋轉a角;

    3.將坐標系o變回o’,這樣,我們就得到了變換矩陣,是上面三個矩陣的級聯。

                                                       RFID設備管理軟件(2.8)

    要注意的是,因為新圖變大,所以上面公式中出現了wold,hold,wnew,hnew,它們分別表示原圖(old)和新圖(new)的寬、高。我們從圖2.8中容易看出:wnew=max(|x4-x1|,|x3-x2|);hnew=max(|y4-y1|,|y3-y2|)。

    (2.8)的逆變換為

                                                        RFID設備管理軟件(2.9)

    這樣,對于新圖中的每一點,我們就可以根據公式(2.9)求出對應原圖中的點,得到它的灰度。如果超出原圖范圍,則填成白色。要注意的是,由于有浮點運算,計算出來點的坐標可能不是整數,采用取整處理,即找最接近的點,這樣會帶來一些誤差(圖象可能會出現鋸齒)。更精確的方法是采用插值,將在圖象縮放時介紹。

    源程序如下:

    [cpp] view plaincopy  
      1. /** 
      2. * 程序名: Rotation.cpp 
      3. * 功  能: 實現灰度圖像的旋轉,如果超出原圖范圍,則用白色填充 
      4. *         測試位圖為test.bmp放到工程目錄下 
      5. */  
      6. #include <iostream>  
      7. #include <fstream>  
      8. #include <cstring>  
      9. #include <cmath>  
      10. #include <windows.h>  
      11. using namespace std;  
      12. #define PI 3.1415926535  
      13. #define RADIAN(angle) (((angle)*PI)/180.0)  
      14. BITMAPFILEHEADER bmpFileHeader;   //bmp文件頭  
      15. BITMAPINFOHEADER bmpInfoHeader;   //bmp信息頭  
      16. RGBQUAD *pColorTable;            //bmp顏色表     
      17. unsigned char *pBmpData;        //bmp位圖數據  
      18. unsigned char *pNewBmpData;   //旋轉后bmp位圖數據  
      19. int newImgSize;         //旋轉后圖像大小  
      20.   
      21. /** 
      22. * 函數名: readBmp 
      23. * 參  數: fileName--要讀取文件的文件名 
      24. * 功  能: 讀取bmp位圖數據,成功返回TRUE,否則返回FALSE 
      25. */  
      26. BOOL readBmp(char *fileName)  
      27. {  
      28.     FILE *fp = fopen(fileName,"rb");   //以二進制讀方式打開  
      29.     if (NULL == fp)  
      30.     {  
      31.         cout<<"The file is opened failure!"<<endl;  
      32.         return FALSE;  
      33.     }  
      34.     //讀取信息到相應的變量中  
      35.     fread(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);  
      36.     fread(&bmpInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);  
      37.     pColorTable = new RGBQUAD[256];  
      38.     fread(pColorTable,sizeof(RGBQUAD),256,fp);  
      39.     int imgSize = bmpInfoHeader.biSizeImage;     //文圖數據的大小,4的倍數  
      40.     pBmpData = new  unsigned char[imgSize];  
      41.     fread(pBmpData,sizeof(unsigned char),imgSize,fp);  
      42.     fclose(fp);  
      43.     return TRUE;  
      44. }  
      45. /** 
      46. * 函數名: rotation 
      47. * 參  數: rotAngle--要轉換的角度 
      48. * 功  能: 實現bmp圖像的旋轉 
      49. */  
      50. void rotation(int rotAngle)  
      51. {  
      52.     double cosa,sina,srcX[4],srcY[4],dstX[4],dstY[4],rad;  
      53.     int oldWidth,oldHeight,newWidth,newHeight;  
      54.     rad = (double)RADIAN(rotAngle);  
      55.     cosa = cos(rad);  
      56.     sina = sin(rad);  
      57.     //原圖寬與高  
      58.     oldWidth = bmpInfoHeader.biWidth;  
      59.     oldHeight = bmpInfoHeader.biHeight;  
      60.     //原圖四個角的坐標  
      61.     srcX[0] = -0.5 * oldWidth;  
      62.     srcY[0] = 0.5 * oldHeight;  
      63.     srcX[1] = 0.5 * oldWidth;  
      64.     srcY[1] = 0.5 * oldHeight;  
      65.     srcX[2] = 0.5 * oldWidth;  
      66.     srcY[2] = -0.5 * oldHeight;  
      67.     srcX[3] = -0.5 * oldWidth;  
      68.     srcY[3] = -0.5 * oldHeight;  
      69.     //新圖四個角坐標  
      70.     for(int i = 0; i < 4; i++ )  
      71.     {  
      72.         dstX[i] = cosa * srcX[i] + sina * srcY[i];  
      73.         dstY[i] = -sina * srcX[i] + cosa * srcY[i];  
      74. //      cout<<dstY[i]<<endl;  
      75.     }  
      76.     //新圖的寬與高,向上取整  
      77.     bmpInfoHeader.biWidth = newWidth = (int)(max(fabs(dstX[0] - dstX[2]),fabs(dstX[1] - dstX[3])) + 0.5);  
      78.     bmpInfoHeader.biHeight = newHeight = (int)(max(fabs(dstY[0] - dstY[2]),fabs(dstY[1] - dstY[3])) + 0.5);  
      79. //  cout<<newWidth<<newHeight<<endl;  
      80.     //新圖位圖數據大小  
      81.     bmpInfoHeader.biSizeImage = newImgSize = newHeight * ((newWidth * bmpInfoHeader.biBitCount + 31) / 32 * 4);  
      82.     pNewBmpData = new unsigned char[newImgSize];  
      83.     double temp1,temp2;   //計算矩陣(2.9)中的兩個常數,這樣不用以后每次都計算了  
      84.     temp1 = -0.5 * newWidth * cosa - 0.5 * newHeight * sina + 0.5 * oldWidth;  
      85.     temp2 = 0.5 * newWidth * sina - 0.5 * newHeight * cosa + 0.5 * oldHeight;  
      86.     memset(pNewBmpData,(BYTE)255,newImgSize);   //先全部填充成白色  
      87.     int x0,y0,x1,y1;  
      88.     unsigned char *pOldTemp,*pNewTemp;  
      89.     int oldLineByte,newLineByte;  
      90.     oldLineByte = (oldWidth * bmpInfoHeader.biBitCount + 31) / 32 * 4;  
      91.     newLineByte = (newWidth * bmpInfoHeader.biBitCount + 31) / 32 * 4;  
      92.     //把旋轉后的圖像數據對應存儲到pNewBmpData相應位置  
      93.     for(y1 = 0; y1 < newHeight; y1++)  
      94.     {  
      95.         for(x1 = 0; x1 < newWidth; x1++ )  
      96.         {  
      97.             x0 = (int)(x1 * cosa + y1 * sina + temp1);  
      98.             y0 = (int)(-x1 * sina + y1 * cosa + temp2);  
      99.             if((x0 >= 0 && x0 < oldWidth) && (y0 >= 0 && y0 < oldHeight))    //這里不能為<=oldWidth或oldHeight  
      100.             {  
      101.                 pOldTemp = pBmpData + (oldHeight - 1 - y0) * oldLineByte + x0;  
      102.                 pNewTemp = pNewBmpData + (newHeight - 1 - y1) * newLineByte + x1;  
      103.                 *pNewTemp = *pOldTemp;  
      104.             }  
      105.         }  
      106.     }  
      107. }  
      108. /** 
      109. * 函數名: writeBmp 
      110. * 參  數: bmpName -- 旋轉后的bmp文件名 
      111. * 功  能: 新建一個bmp文件,把旋轉后的圖像信息存入其中 
      112. */  
      113. void writeBmp(char *bmpName)  
      114. {  
      115.     FILE *fp = fopen(bmpName,"wb");  //以二進制寫方式打開  
      116.     if(NULL == fp)  
      117.         cout<<"The file is opened failure"<<endl;  
      118.     //寫入選裝后圖像信息  
      119.     fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);  
      120.     fwrite(&bmpInfoHeader,sizeof(BITMAPINFOHEADER),1,fp);  
      121.     fwrite(pColorTable,sizeof(RGBQUAD),256,fp);  
      122.     fwrite(pNewBmpData,sizeof(unsigned char),newImgSize,fp);  
      123.     fclose(fp);  
      124.         delete []pColorTable;  
      125.         delete []pNewBmpData;  
      126.         delete []pBmpData;  
      127.  }  
      128. /** 
      129. * 函數名: work 
      130. * 參  數: 無 
      131. * 功  能: 實現處理工作 
      132. */  
      133. void work()  
      134. {  
      135.     char readBmpName[] = "test.bmp";  
      136.     if ( !readBmp(readBmpName))  
      137.         cout<<"The file "<<readBmpName<<"is read failure"<<endl;  
      138.     cout<<"please input the angle to rotate(Clockwise):";  
      139.     int rotAngle;  
      140.     cin>>rotAngle;  
      141.     rotation(rotAngle);  
      142.     char writeBmpName[] = "test_new.bmp";  
      143.     writeBmp(writeBmpName);  
      144. }  
      145. int main()  
      146. {  
      147.     work();  
      148.     return 0;  
      149. }  
    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全