映像二值化演算法 【迭代法和大律法運算元】

來源:互聯網
上載者:User

二值化是一個相當複雜的理論問題,如果不給出具體的應用要求是無法做的.

最簡單的:

for(......)

if(PixelY[i,j]>T)

PixelY[i,j] = 255;

else

PixelY[i,j] = 0;

如果考慮具體問題,二值化演算法不下100種.

/***************************************************************************  
    *   函數名稱  
    *   OSTUThreshold()  
    *   參數  
    *         LPSTR   lpDIBBits           -   指向源DIB映像指標  
    *         LONG     lWidth                 -   源映像寬度(像素數)  
    *         LONG     lHeight               -   源映像高度(像素數)  
    *   傳回值  
    *         BOOL                                 -   運算成功   返回TRUE   ,   否則   返回FALSE。  
    *   說明  
    *         該函數採用大津法進行閾值分割   二值化  
    ***************************************************************************/  
  BOOL   WINAPI   OSTUThreshold(LPSTR   lpDIBBits,   LONG   lWidth,   LONG   lHeight)  
  {  
  //   指向源映像像素指標  
  LPSTR   lpSrc;  
   
  //   指向緩衝映像指標  
  LPSTR   lpDst;  
   
  //   指向緩衝映像像素指標  
  LPSTR   lpNewDIBBits;  
  HLOCAL   hNewDIBBits;  
   
  //   迴圈變數  
  int   i,   j,   t;  
   
  //   用於計算兩個地區的中間變數  
  long   lP1,   lS1,   lP2,   lS2;  
   
  //   像素值  
  unsigned   char   pixel;  
   
  //   灰階長條圖數組  
  long   lHistogram[256];  
   
  //   閾值,   最大灰階值和最小灰階值,   兩個地區的平均灰階值  
  unsigned   char   iThreshold,   iNewThreshold,   iMaxGrayValue,   iMinGrayValue,   iMean1GrayValue,   iMean2GrayValue;  
   
  //     前景點數占映像比例,   背景點數占映像比例  
  double   w0,w1;  
   
  //   方差  
  double   G,   tempG;  
   
  //   映像每行占位元組數  
  LONG   lLineBytes;  
   
  //   暫時分配記憶體,   以儲存新映像  
  hNewDIBBits   =   LocalAlloc(LHND,   lWidth   *   lHeight);  
   
  if   (hNewDIBBits   ==   NULL)    
  {  
  //分配記憶體失敗  
  return   FALSE;  
  }  
   
  //   鎖定記憶體  
  lpNewDIBBits   =   (char   *)   LocalLock(hNewDIBBits);  
   
  //   初始化新分配的記憶體,   設定初始值為255  
  lpDst   =   (char   *)   lpNewDIBBits;  
  memset(lpDst,   (BYTE)255,   lWidth   *   lHeight);  
   
  lLineBytes   =   WIDTHBYTES(lWidth   *   8);  
   
  for(i=   0;   i   <   256;   i++)  
  {  
  lHistogram[i]   =   0;  
  }  
   
  //   獲得灰階長條圖,灰階最大值和灰階最小值  
  iMaxGrayValue   =   0;  
  iMinGrayValue   =   255;  
  for(i   =   0;   i   <   lWidth;   i++)  
  {  
  for(j   =   0;   j   <   lHeight;   j++)  
  {  
  lpSrc   =   (char   *)   lpDIBBits   +   lLineBytes   *   j   +   i;  
  pixel   =   (unsigned   char)   *lpSrc;  
  lHistogram[pixel]++;  
   
  //   修改最大灰階值和最小灰階值  
  if   (iMinGrayValue   >   pixel)  
  {  
  iMinGrayValue   =   pixel;  
  }  
  if   (iMaxGrayValue   <   pixel)  
  {  
  iMaxGrayValue   =   pixel;  
  }  
  }  
  }  
   
  //   遍曆t,   選取最佳閾值  
  for(t   =   iMinGrayValue;   t   <   iMaxGrayValue   ;   t++)  
  {  
  iNewThreshold   =   t;  
  lP1   =   0;  
  lS1   =   0;  
  lP2   =   0;  
  lS2   =   0;  
   
  //     求前景,背景兩個地區的平均灰階值,   點數所佔比例  
  for(i   =   iMinGrayValue;   i   <=   iNewThreshold;   i++)  
  {  
  lP1   +=   lHistogram[i]   *   i;  
  lS1   +=   lHistogram[i];  
  }  
  iMean1GrayValue   =   (unsigned   char)   (lP1/lS1);  
  w0   =   (double)   (lS1)   /   (lWidth   *   lHeight);  
  for(i   =   iNewThreshold   +   1;   i   <=   iMaxGrayValue;   i++)  
  {  
  lP2   +=   lHistogram[i]   *   i;  
  lS2   +=   lHistogram[i];  
  }  
  iMean2GrayValue   =   (unsigned   char)   (lP2/lS2);  
                  w1   =   1   -   w0;  
   
  //   計算類間方差  
  G   =   (double)   w0   *   w1    
      *   (iMean1GrayValue   -   iMean2GrayValue)   *   (iMean1GrayValue   -   iMean2GrayValue);  
  if   (G   >   tempG)    
  {  
  tempG   =   G;  
  iThreshold   =   iNewThreshold;  
  }  
  }  
   
  //   根據閾值將映像二值化  
          for(i   =   0;   i   <   lWidth;   i++)  
  {  
  for(j   =   0;   j   <   lHeight;   j++)  
  {  
  lpSrc   =   (char   *)   lpDIBBits   +   lLineBytes   *   j   +   i;  
  lpDst   =   (char   *)   lpNewDIBBits   +   lLineBytes   *   j   +   i;  
  pixel   =   (unsigned   char)   *lpSrc;  
  if   (pixel   <=   iThreshold)    
  {  
  *lpDst   =   (unsigned   char)0;  
  }  
  else  
  {  
  *lpDst   =   (unsigned   char)   255;  
  }  
  }  
  }  
   
          //   複製映像  
  memcpy(lpDIBBits,   lpNewDIBBits,   lWidth   *   lHeight);  
   
  //   釋放記憶體  
  LocalUnlock(hNewDIBBits);  
  LocalFree(hNewDIBBits);  
   
  //   返回  
  return   TRUE;  
  }

/*************************************************************************
 *
 * 函數名稱:
 *   ThresholdDIB()
 *
 * 參數:
 *   LPSTR lpDIBBits    - 指向源DIB映像指標
 *   LONG  lWidth       - 源映像寬度(象素數)
 *   LONG  lHeight      - 源映像高度(象素數)
 *
 * 傳回值:
 *   BOOL               - 運算成功返回TRUE,否則返回FALSE。
 *
 * 說明:
 * 該函數用 迭代法 對映像進行閾值分割運算。
 *
 ************************************************************************/

BOOL WINAPI ThresholdDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight)
{
 
 // 指向源映像的指標
 LPSTR lpSrc;
 
 // 指向緩衝映像的指標
 LPSTR lpDst;
 
 // 指向緩衝DIB映像的指標
 LPSTR lpNewDIBBits;
 HLOCAL hNewDIBBits;

 //迴圈變數
 long i;
 long j;

 //像素值
 unsigned char pixel;

 //長條圖數組
 long lHistogram[256];

 //閾值,最大灰階值與最小灰階值,兩個地區的平均灰階值
 unsigned char iThreshold,iNewThreshold,iMaxGrayValue,iMinGrayValue,iMean1GrayValue,iMean2GrayValue;

 //用於計算地區灰階平均值的中間變數
 long lP1,lP2,lS1,lS2;

 //迭代次數
 int iIterationTimes;

 // 映像每行的位元組數
 LONG lLineBytes;

 // 暫時分配記憶體,以儲存新映像
 hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);

 if (hNewDIBBits == NULL)
 {
  // 分配記憶體失敗
  return FALSE;
 }
 
 // 鎖定記憶體
 lpNewDIBBits = (char * )LocalLock(hNewDIBBits);

 // 初始化新分配的記憶體,設定初始值為255
 lpDst = (char *)lpNewDIBBits;
 memset(lpDst, (BYTE)255, lWidth * lHeight);

 // 計算映像每行的位元組數
 lLineBytes = WIDTHBYTES(lWidth * 8);

 for (i = 0; i < 256;i++)
 {
  lHistogram[i]=0;
 }

 //獲得長條圖
 iMaxGrayValue = 0;
 iMinGrayValue = 255;
 for (i = 0;i < lWidth ;i++)
 {
  for(j = 0;j < lHeight ;j++)
  {
   // 指向源映像倒數第j行,第i個象素的指標   
   lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
 
   pixel = (unsigned char)*lpSrc;
   
   lHistogram[pixel]++;
   //修改最大,最小灰階值
   if(iMinGrayValue > pixel)
   {
    iMinGrayValue = pixel;
   }
   if(iMaxGrayValue < pixel)
   {
    iMaxGrayValue = pixel;
   }
  }
 }

 //迭代求最佳閾值
 iNewThreshold = (iMinGrayValue + iMaxGrayValue)/2;
 iThreshold = 0;
 
 for(iIterationTimes = 0; iThreshold != iNewThreshold && iIterationTimes < 100;iIterationTimes ++)
 {
  iThreshold = iNewThreshold;
  lP1 =0;
  lP2 =0;
  lS1 = 0;
  lS2 = 0;
  //求兩個地區的灰階平均值
  for (i = iMinGrayValue;i < iThreshold;i++)
  {
   lP1 += lHistogram[i]*i;
   lS1 += lHistogram[i];
  }
  iMean1GrayValue = (unsigned char)(lP1 / lS1);
  for (i = iThreshold+1;i < iMaxGrayValue;i++)
  {
   lP2 += lHistogram[i]*i;
   lS2 += lHistogram[i];
  }
  iMean2GrayValue = (unsigned char)(lP2 / lS2);
  iNewThreshold =  (iMean1GrayValue + iMean2GrayValue)/2;
 }

 //根據閾值將映像二值化
 for (i = 0;i < lWidth ;i++)
 {
  for(j = 0;j < lHeight ;j++)
  {
   // 指向源映像倒數第j行,第i個象素的指標   
   lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
 
   // 指向靶心圖表像倒數第j行,第i個象素的指標   
   lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;

   pixel = (unsigned char)*lpSrc;
   
   if(pixel <= iThreshold)
   {
    *lpDst = (unsigned char)0;
   }
   else
   {
    *lpDst = (unsigned char)255;
   }
  }
 }

 // 複製映像
 memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);

 // 釋放記憶體
 LocalUnlock(hNewDIBBits);
 LocalFree(hNewDIBBits);

 // 返回
 return TRUE;
}

 

 

///////////////////////////////////////////////////////////////

 

 映像的二值化原理和實現 1、 映像的二值化的基本原理映像的二值化處理就是講映像上的 點的灰階置為 0 或255,也就是講整個映像呈現出明顯的黑白效果。即將256個亮度等級的灰階映像通過適當的閥值選取而獲得仍然可以反映映像整體和局部特徵的二值化映像。在數位影像處理中,二值映像佔有非常重要的地位,特別是在實用的影像處理中,以二值影像處理實現而構成的系統是很多的,要進行二值映像的處理與分析,首先要把灰階映像二值化,得到二值化映像,這樣子有利於再對映像做進一步處理時,映像的集合性質只與像素值為0或255的點的位置有關,不再涉及像素的多級值,使處理變得簡單,而且資料的處理和壓縮量小。為了得到理想的二值映像,一般採用封閉、連通的邊界定義不交疊的地區。 所有灰階大於或等於閥值的像素被判定為屬於特定物體,其灰階值為 255 表示,否則這些像素點被排除在物體地區以外,灰階值為0 ,表示背景或者例外的物體地區。如果某特定物體在內部有均勻一致的灰階值,並且其處在一個具有其他等級灰階值的均勻背景下,使用閥值法就可以得到比較的分割效果。如果物體同背景的差別表現不在灰階值上(比如紋理不同),可以將這個差別特徵轉換為灰階的差別,然後利用閥值選取技術來分割該映像。動態調節閥值實現映像的二值化可動態觀察其分割映像的具體結果。2、 映像的二值化的程式實現通過Delphi刻度控制項調整閥值,實現動態控制,程式如下:procedure TForm1.Button1Click(Sender: TObject);var        p:PByteArray;        Gray,x,y:integer;begin        TestBMP:=TBitmap.Create; changedbmp:=tbitmap.Create;        testbmp.Assign(image1.Picture);        for y:=0 to testbmp.Height-1 do        begin                p:=testbmp.ScanLine[y];                for x:=0 to testbmp.Width-1 do                begin                                           // 首先將映像灰階化                        gray:=round(p[x*3+2]*0.3+p[x*3+1]*0.59+p[x*3]*0.11);                        if gray> TrackBar1.Position then // 按閥值進行二值化                        begin                                p[x*3]:=255; p[x*3+1]:=255; p[x*3+2]:=255;                        end                        else                        begin                                p[x*3]:=0;p[x*3+1]:=0;p[x*3+2]:=0;                        end;                end;        end;        ChangedBmp.Assign(TestBMP);        PaintBox1.Canvas.CopyMode:=srccopy;        PaintBox1.Canvas.Draw(0,0,ChangedBmp); end;3、 處理的效果

 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=886749

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.