【opencv】二值图像细化


139 lines (115 sloc)    3.3 KB
 /**
 * Code for thinning a binary image using Zhang-Suen algorithm.
 *
 * Author:  Nash (nash [at] opencv-code [dot] com)
 * Website: http://opencv-code.com
 */
 #include <opencv2/opencv.hpp>
  
 /**
 * Perform one thinning iteration.
 * Normally you wouldn't call this function directly from your code.
 *
 * Parameters:
 * im    Binary image with range = [0,1]
 * iter  0=even, 1=odd
 */
 void thinningIteration(cv::Mat& img, int iter)
 {
     CV_Assert(img.channels() == 1);
     CV_Assert(img.depth() != sizeof(uchar));
     CV_Assert(img.rows > 3 && img.cols > 3);
  
     cv::Mat marker = cv::Mat::zeros(img.size(), CV_8UC1);
  
     int nRows = img.rows;
     int nCols = img.cols;
  
     if (img.isContinuous()) {
         nCols *= nRows;
         nRows = 1;
     }
  
     int x, y;
     uchar *pAbove;
     uchar *pCurr;
     uchar *pBelow;
     uchar *nw, *no, *ne;    // north (pAbove)
     uchar *we, *me, *ea;
     uchar *sw, *so, *se;    // south (pBelow)
  
     uchar *pDst;
  
     // initialize row pointers
     pAbove = NULL;
     pCurr  = img.ptr<uchar>(0);
     pBelow = img.ptr<uchar>(1);
  
     for (y = 1; y < img.rows-1; ++y) {
         // shift the rows up by one
         pAbove = pCurr;
         pCurr  = pBelow;
         pBelow = img.ptr<uchar>(y+1);
  
         pDst = marker.ptr<uchar>(y);
  
         // initialize col pointers
         no = &(pAbove[0]);
         ne = &(pAbove[1]);
         me = &(pCurr[0]);
         ea = &(pCurr[1]);
         so = &(pBelow[0]);
         se = &(pBelow[1]);
  
         for (x = 1; x < img.cols-1; ++x) {
             // shift col pointers left by one (scan left to right)
             nw = no;
             no = ne;
             ne = &(pAbove[x+1]);
             we = me;
             me = ea;
             ea = &(pCurr[x+1]);
             sw = so;
             so = se;
             se = &(pBelow[x+1]);
  
             int A  = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) +
                      (*ea == 0 && *se == 1) + (*se == 0 && *so == 1) +
                      (*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) +
                      (*we == 0 && *nw == 1) + (*nw == 0 && *no == 1);
             int B  = *no + *ne + *ea + *se + *so + *sw + *we + *nw;
             int m1 = iter == 0 ? (*no * *ea * *so) : (*no * *ea * *we);
             int m2 = iter == 0 ? (*ea * *so * *we) : (*no * *so * *we);
  
             if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
                 pDst[x] = 1;
         }
     }
  
     img &= ~marker;
 }
  
 /**
 * Function for thinning the given binary image
 *
 * Parameters:
 * src  The source image, binary with range = [0,255]
 * dst  The destination image
 */
 void thinning(const cv::Mat& src, cv::Mat& dst)
 {
     dst = src.clone();
     dst /= 255;         // convert to binary image
  
     cv::Mat prev = cv::Mat::zeros(dst.size(), CV_8UC1);
     cv::Mat diff;
  
     do {
         thinningIteration(dst, 0);
         thinningIteration(dst, 1);
         cv::absdiff(dst, prev, diff);
         dst.copyTo(prev);
     }
     while (cv::countNonZero(diff) > 0);
  
     dst *= 255;
 }
  
 /**
 * This is an example on how to call the thinning funciton above
 */
 int main()
 {
 cv::Mat src = cv::imread("image.png");
 if (!src.data)
 return -1;
  
 cv::Mat bw;
 cv::cvtColor(src, bw, CV_BGR2GRAY);
 cv::threshold(bw, bw, 10, 255, CV_THRESH_BINARY);
  
 thinning(bw, bw);
  
 cv::imshow("src", src);
 cv::imshow("dst", bw);
 cv::waitKey();
 return 0;
 }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值