• 骨架提取


      1 #include <opencv2/opencv.hpp>  
      2 #include <iostream>  
      3 #include <vector>  
      4 #include <limits>  
      5 
      6 using namespace cv;
      7 using namespace std;
      8 
      9 /**
     10 * @brief 对输入图像进行细化
     11 * @param[in] src为输入图像,用cvThreshold函数处理过的8位灰度图像格式,元素中只有0与1,1代表有元素,0代表为空白
     12 * @param[out] dst为对src细化后的输出图像,格式与src格式相同,调用前需要分配空间,元素中只有0与1,1代表有元素,0代表为空白
     13 * @param[in] maxIterations限制迭代次数,如果不进行限制,默认为-1,代表不限制迭代次数,直到获得最终结果
     14 */
     15 void thinImage(IplImage* src, IplImage* dst, int maxIterations = -1)
     16 {
     17     CvSize size = cvGetSize(src);
     18     cvCopy(src, dst);//将src中的内容拷贝到dst中  
     19     int count = 0;  //记录迭代次数  
     20     while (true)
     21     {
     22         count++;
     23         if (maxIterations != -1 && count > maxIterations) //限制次数并且迭代次数到达  
     24             break;
     25         //std::cout << count << ' ';输出迭代次数  
     26         vector<pair<int, int> > mFlag; //用于标记需要删除的点  
     27                                        //对点标记  
     28         for (int i = 0; i<size.height; ++i)
     29         {
     30             for (int j = 0; j<size.width; ++j)
     31             {
     32                 //如果满足四个条件,进行标记  
     33                 //  p9 p2 p3  
     34                 //  p8 p1 p4  
     35                 //  p7 p6 p5  
     36                 int p1 = CV_IMAGE_ELEM(dst, uchar, i, j);
     37                 int p2 = (i == 0) ? 0 : CV_IMAGE_ELEM(dst, uchar, i - 1, j);
     38                 int p3 = (i == 0 || j == size.width - 1) ? 0 : CV_IMAGE_ELEM(dst, uchar, i - 1, j + 1);
     39                 int p4 = (j == size.width - 1) ? 0 : CV_IMAGE_ELEM(dst, uchar, i, j + 1);
     40                 int p5 = (i == size.height - 1 || j == size.width - 1) ? 0 : CV_IMAGE_ELEM(dst, uchar, i + 1, j + 1);
     41                 int p6 = (i == size.height - 1) ? 0 : CV_IMAGE_ELEM(dst, uchar, i + 1, j);
     42                 int p7 = (i == size.height - 1 || j == 0) ? 0 : CV_IMAGE_ELEM(dst, uchar, i + 1, j - 1);
     43                 int p8 = (j == 0) ? 0 : CV_IMAGE_ELEM(dst, uchar, i, j - 1);
     44                 int p9 = (i == 0 || j == 0) ? 0 : CV_IMAGE_ELEM(dst, uchar, i - 1, j - 1);
     45 
     46                 if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6)
     47                 {
     48                     int ap = 0;
     49                     if (p2 == 0 && p3 == 1) ++ap;
     50                     if (p3 == 0 && p4 == 1) ++ap;
     51                     if (p4 == 0 && p5 == 1) ++ap;
     52                     if (p5 == 0 && p6 == 1) ++ap;
     53                     if (p6 == 0 && p7 == 1) ++ap;
     54                     if (p7 == 0 && p8 == 1) ++ap;
     55                     if (p8 == 0 && p9 == 1) ++ap;
     56                     if (p9 == 0 && p2 == 1) ++ap;
     57 
     58                     if (ap == 1)
     59                     {
     60                         if (p2*p4*p6 == 0)
     61                         {
     62                             if (p4*p6*p8 == 0)
     63                             {
     64                                 //标记  
     65                                 mFlag.push_back(make_pair(i, j));
     66                             }
     67                         }
     68                     }
     69                 }
     70             }
     71         }
     72 
     73         //将标记的点删除  
     74         for (vector<pair<int, int> >::iterator i = mFlag.begin(); i != mFlag.end(); ++i)
     75         {
     76             CV_IMAGE_ELEM(dst, uchar, i->first, i->second) = 0;
     77         }
     78 
     79         //直到没有点满足,算法结束  
     80         if (mFlag.size() == 0)
     81         {
     82             break;
     83         }
     84         else
     85         {
     86             mFlag.clear();//将mFlag清空  
     87         }
     88 
     89         //对点标记  
     90         for (int i = 0; i<size.height; ++i)
     91         {
     92             for (int j = 0; j<size.width; ++j)
     93             {
     94                 //如果满足四个条件,进行标记  
     95                 //  p9 p2 p3  
     96                 //  p8 p1 p4  
     97                 //  p7 p6 p5  
     98                 int p1 = CV_IMAGE_ELEM(dst, uchar, i, j);
     99                 if (p1 != 1) continue;
    100                 int p2 = (i == 0) ? 0 : CV_IMAGE_ELEM(dst, uchar, i - 1, j);
    101                 int p3 = (i == 0 || j == size.width - 1) ? 0 : CV_IMAGE_ELEM(dst, uchar, i - 1, j + 1);
    102                 int p4 = (j == size.width - 1) ? 0 : CV_IMAGE_ELEM(dst, uchar, i, j + 1);
    103                 int p5 = (i == size.height - 1 || j == size.width - 1) ? 0 : CV_IMAGE_ELEM(dst, uchar, i + 1, j + 1);
    104                 int p6 = (i == size.height - 1) ? 0 : CV_IMAGE_ELEM(dst, uchar, i + 1, j);
    105                 int p7 = (i == size.height - 1 || j == 0) ? 0 : CV_IMAGE_ELEM(dst, uchar, i + 1, j - 1);
    106                 int p8 = (j == 0) ? 0 : CV_IMAGE_ELEM(dst, uchar, i, j - 1);
    107                 int p9 = (i == 0 || j == 0) ? 0 : CV_IMAGE_ELEM(dst, uchar, i - 1, j - 1);
    108 
    109                 if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6)
    110                 {
    111                     int ap = 0;
    112                     if (p2 == 0 && p3 == 1) ++ap;
    113                     if (p3 == 0 && p4 == 1) ++ap;
    114                     if (p4 == 0 && p5 == 1) ++ap;
    115                     if (p5 == 0 && p6 == 1) ++ap;
    116                     if (p6 == 0 && p7 == 1) ++ap;
    117                     if (p7 == 0 && p8 == 1) ++ap;
    118                     if (p8 == 0 && p9 == 1) ++ap;
    119                     if (p9 == 0 && p2 == 1) ++ap;
    120 
    121                     if (ap == 1)
    122                     {
    123                         if (p2*p4*p8 == 0)
    124                         {
    125                             if (p2*p6*p8 == 0)
    126                             {
    127                                 //标记  
    128                                 mFlag.push_back(make_pair(i, j));
    129                             }
    130                         }
    131                     }
    132                 }
    133             }
    134         }
    135         //删除  
    136         for (vector<pair<int, int> >::iterator i = mFlag.begin(); i != mFlag.end(); ++i)
    137         {
    138             CV_IMAGE_ELEM(dst, uchar, i->first, i->second) = 0;
    139         }
    140 
    141         //直到没有点满足,算法结束  
    142         if (mFlag.size() == 0)
    143         {
    144             break;
    145         }
    146         else
    147         {
    148             mFlag.clear();//将mFlag清空  
    149         }
    150     }
    151 }
    152 
    153 int main(int argc, char*argv[])
    154 {
    155     //获取图像  
    156     if (argc != 2)
    157     {
    158         cout << "参数个数错误!" << endl;
    159         return -1;
    160     }
    161     IplImage *pSrc = cvLoadImage(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
    162     if (!pSrc)
    163     {
    164         cout << "读取文件失败!" << endl;
    165         return -1;
    166     }
    167     IplImage *pTemp = cvCreateImage(cvGetSize(pSrc), pSrc->depth, pSrc->nChannels);
    168     IplImage *pDst = cvCreateImage(cvGetSize(pSrc), pSrc->depth, pSrc->nChannels);
    169 
    170     //将原图像转换为二值图像  
    171     cvThreshold(pSrc, pTemp, 128, 1, CV_THRESH_BINARY);
    172     //图像细化  
    173     thinImage(pTemp, pDst);
    174 
    175     for (int i = 0; i<pDst->height; ++i)
    176     {
    177         for (int j = 0; j<pDst->width; ++j)
    178         {
    179             if (CV_IMAGE_ELEM(pDst, uchar, i, j) == 1)
    180                 CV_IMAGE_ELEM(pDst, uchar, i, j) = 255;
    181         }
    182     }
    183 
    184     namedWindow("src", CV_WINDOW_AUTOSIZE);
    185     namedWindow("dst", CV_WINDOW_AUTOSIZE);
    186     cvShowImage("src", pSrc);
    187     cvShowImage("dst", pDst);
    188 
    189     waitKey(0);
    190 }
  • 相关阅读:
    ASP.NET学习5 后台控制前台执行js的方法
    uml笔记
    Python拓展——import导入包之random随机数和turtle海龟作图(2)
    Python拓展——import导入包之random随机数和turtle海龟作图(1)
    蓝桥杯考完了
    Python第一单元测试(答案)
    Python第一单元测试
    Python第五课——嵌套for循环和if语句初步(2)
    Python第五课——嵌套for循环和if语句初步(1)
    Python第四课——import导入包和for循环(2)
  • 原文地址:https://www.cnblogs.com/hsy1941/p/7806517.html
Copyright © 2020-2023  润新知