圖像處理

/*************************************************************************
  *
  * 函數名稱:
  *   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;
}
相關文章
相關標籤/搜索