opencv-图像二值化、阈值获取、直方图、轮廓提取(转)

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