天天看點

opencv-圖像二值化、門檻值擷取、直方圖、輪廓提取(轉)

Code:

  1. #include <cv.h>   
  2. #include <highgui.h>   
  3. #include <windows.h>   
  4. // 擷取直方圖   
  5. // 1. pImageData   圖像資料   
  6. // 2. nWidth       圖像寬度   
  7. // 3. nHeight      圖像高度   
  8. // 4. nWidthStep   圖像行大小   
  9. // 5. pHistogram   直方圖   
  10. BOOL GetHistogram(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep,   
  11.     int *pHistogram)   
  12. {   
  13.     int            i     = 0;   
  14.     int            j     = 0;   
  15.     unsigned char *pLine = NULL;   
  16.     // 清空直方圖   
  17.     memset(pHistogram, 0, sizeof(int) * 256);   
  18.     for (pLine = pImageData, j = 0; j < nHeight; j++, pLine += nWidthStep)   
  19.     {   
  20.         for (i = 0; i < nWidth; i++)   
  21.         {   
  22.             pHistogram[pLine[i]]++;   
  23.         }   
  24.     }   
  25.     return TRUE;   
  26. }   
  27. // 大津法取門檻值   
  28. // 1. pImageData   圖像資料   
  29. // 2. nWidth       圖像寬度   
  30. // 3. nHeight      圖像高度   
  31. // 4. nWidthStep   圖像行大小   
  32. // 函數傳回門檻值   
  33. int Otsu(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep)   
  34. {   
  35.     int    i          = 0;   
  36.     int    j          = 0;   
  37.     int    nTotal     = 0;   
  38.     int    nSum       = 0;   
  39.     int    A          = 0;   
  40.     int    B          = 0;   
  41.     double u          = 0;   
  42.     double v          = 0;   
  43.     double dVariance  = 0;   
  44.     double dMaximum   = 0;   
  45.     int    nThreshold = 0;   
  46.     int    nHistogram[256];   
  47.     // 擷取直方圖   
  48.     GetHistogram(pImageData, nWidth, nHeight, nWidthStep, nHistogram);   
  49.     for (i = 0; i < 256; i++)   
  50.     {   
  51.         nTotal += nHistogram[i];   
  52.         nSum   += (nHistogram[i] * i);   
  53.     }   
  54.     for (j = 0; j < 256; j++)   
  55.     {   
  56.         A = 0;   
  57.         B = 0;   
  58.         for (i = 0; i < j; i++)   
  59.         {   
  60.             A += nHistogram[i];   
  61.             B += (nHistogram[i] * i);   
  62.         }   
  63.         if (A > 0)   
  64.         {   
  65.             u = B / A;   
  66.         }   
  67.         else  
  68.         {   
  69.             u = 0;   
  70.         }   
  71.         if (nTotal - A > 0)    
  72.         {   
  73.             v = (nSum - B) / (nTotal - A);   
  74.         }   
  75.         else  
  76.         {   
  77.             v = 0;   
  78.         }   
  79.         dVariance = A * (nTotal - A) * (u - v) * (u - v);   
  80.         if (dVariance > dMaximum)   
  81.         {   
  82.             dMaximum = dVariance;   
  83.             nThreshold = j;   
  84.         }   
  85.     }   
  86.     return nThreshold;   
  87. }   
  88. // 二值化   
  89. // 1. pImageData   圖像資料   
  90. // 2. nWidth       圖像寬度   
  91. // 3. nHeight      圖像高度   
  92. // 4. nWidthStep   圖像行大小   
  93. // 5. nThreshold   門檻值   
  94. BOOL Threshold(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep,   
  95.     unsigned int nThreshold)   
  96. {   
  97.     int            i     = 0;   
  98.     int            j     = 0;   
  99.     unsigned char *pLine = NULL;   
  100.     for (pLine = pImageData, j = 0; j < nHeight; j++, pLine += nWidthStep)   
  101.     {   
  102.         for (i = 0; i < nWidth; i++)   
  103.         {   
  104.             if (pLine[i] >= nThreshold)   
  105.             {   
  106.                 pLine[i] = 0x00;   
  107.             }   
  108.             else  
  109.             {   
  110.                 pLine[i] = 0xff;   
  111.             }   
  112.         }   
  113.     }   
  114.     return TRUE;   
  115. }   
  116. // 二值化圖像取反   
  117. void Not(IplImage *edge)   
  118. {   
  119.     int i;   
  120.     int j;   
  121.     for(i=0;i<edge->height;i++)   
  122.       for(j=0;j<edge->width;j++)   
  123.       {   
  124.          if(edge->imageData[edge->height*i+j]==0)   
  125.             edge->imageData[edge->height*i+j]=1;   
  126.           else  
  127.             edge->imageData[edge->height*i+j]=0;   
  128.       }   
  129. }   
  130. BOOL FindContours(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep)   
  131. {   
  132.     int            i        = 0;   
  133.     int            j        = 0;   
  134.     unsigned char *pLine[3] = { NULL, NULL, NULL };   
  135.     for (j = 1; j < nHeight - 1; j++)   
  136.     {   
  137.         pLine[0]  = pImageData + nWidthStep * (j - 1);   
  138.         pLine[1]  = pImageData + nWidthStep * j;   
  139.         pLine[2]  = pImageData + nWidthStep * (j + 1);   
  140.         for (i = 1; i < nWidth - 1; i++)   
  141.         {   
  142.             if (pLine[0][i-1] == 0xFF && pLine[0][i] == 0xFF && pLine[0][i+1] == 0xFF &&   
  143.                 pLine[1][i-1] == 0xFF && pLine[1][i] == 0xFF && pLine[1][i+1] == 0xFF &&   
  144.                 pLine[2][i-1] == 0xFF && pLine[2][i] == 0xFF && pLine[2][i+1] == 0xFF)   
  145.             {   
  146.                 pLine[0][i-1] = 0;   
  147.             }   
  148.             else  
  149.             {   
  150.                 pLine[0][i-1] = pLine[1][i];   
  151.             }   
  152.         }   
  153.     }   
  154.     return TRUE;   
  155. }   
  156. int main(int argc, char* argv[])   
  157. {   
  158.     IplImage *src = cvLoadImage("e://five.jpg", CV_LOAD_IMAGE_GRAYSCALE);   
  159.     IplImage *dsc = cvCreateImage(cvSize(src->width*0.5,src->height*0.5), src->depth, src->nChannels);   
  160.     // 轉換圖像大小   
  161.     cvResize(src, dsc, CV_INTER_LINEAR);   
  162.     src->width*=0.5;   
  163.     src->height*=0.5;   
  164.     // 複制圖像    
  165.     // 兩個圖像的大小類型通道數必須相同   
  166.     cvCopy(dsc, src );   
  167.     cvNamedWindow("src", CV_WINDOW_AUTOSIZE);   
  168.     cvShowImage("src", src);   
  169.     // 取圖像閥值   
  170.     unsigned int threshold = Otsu((unsigned char *)src->imageData, src->width, src->height, src->widthStep);   
  171.     // 圖像二值化   
  172.     if (TRUE == Threshold((unsigned char *)src->imageData, src->width, src->height, src->widthStep,   
  173.     threshold))   
  174.     {   
  175.         cvNamedWindow("dsc", CV_WINDOW_AUTOSIZE);   
  176.         cvShowImage("dsc", src);   
  177.         // 圖像取反   
  178.         // cvNot(src, src);   
  179.         FindContours((unsigned char *)src->imageData,src->width , src->height, src->widthStep);   
  180.         cvNamedWindow("not", CV_WINDOW_AUTOSIZE);   
  181.         cvShowImage("not", src);   
  182.         cvWaitKey(0);   
  183.     }   
  184.     cvDestroyAllWindows();   
  185.     cvReleaseImage(&src);   
  186.     cvReleaseImage(&dsc);   
  187.     printf("Hello World!/n");   
  188.     return 0;   
  189. }  

繼續閱讀