骨架细化
参考自:http://blog.csdn.net/qianchenglenger/article/details/19332011
图像细化(Image Thinning),一般指二值图像的骨架化(Image Skeletonization) 的一种操作运算。
 所谓的细化就是经过一层层的剥离,从原来的图中去掉一些点,但仍要保持原来的形状,直到得到图像的骨架。骨架,可以理解为图象的中轴。
好的细化算法一定要满足:
这里,我们对“Zhang并行快速细化算法”进行了实现(注意,该算法为并行算法,而我们在实现过程中并没有并行化处理,所以,效率并没有达到最好)。
参考:
博客http://blog.sina.com.cn/s/blog_6f611c3001017y5m.html
论文https://wenku.baidu.com/view/966dfe0a581b6bd97f19ea8e.html
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 
 | #include <opencv2/opencv.hpp>#include <opencv2/core/core.hpp>
 #include <iostream>
 #include <vector>
 
 using namespace cv;
 using namespace std;
 
 
 
 
 
 
 
 cv::Mat thinImage(const cv::Mat & src_binary, const int maxIterations = -1)
 {
 assert(src_binary.type() == CV_8UC1);
 cv::Mat dst;
 int width = src_binary.cols;
 int height = src_binary.rows;
 src_binary.copyTo(dst);
 int count = 0;
 while (true)
 {
 count++;
 if (maxIterations != -1 && count > maxIterations)
 break;
 std::vector<uchar *> mFlag;
 
 for (int i = 0; i < height; ++i)
 {
 uchar * p = dst.ptr<uchar>(i);
 for (int j = 0; j < width; ++j)
 {
 
 
 
 
 uchar p1 = p[j];
 if (p1 != 1) continue;
 uchar p4 = (j == width - 1) ? 0 : *(p + j + 1);
 uchar p8 = (j == 0) ? 0 : *(p + j - 1);
 uchar p2 = (i == 0) ? 0 : *(p - dst.step + j);
 uchar p3 = (i == 0 || j == width - 1) ? 0 : *(p - dst.step + j + 1);
 uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1);
 uchar p6 = (i == height - 1) ? 0 : *(p + dst.step + j);
 uchar p5 = (i == height - 1 || j == width - 1) ? 0 : *(p + dst.step + j + 1);
 uchar p7 = (i == height - 1 || j == 0) ? 0 : *(p + dst.step + j - 1);
 if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6)
 {
 int ap = 0;
 if (p2 == 0 && p3 == 1) ++ap;
 if (p3 == 0 && p4 == 1) ++ap;
 if (p4 == 0 && p5 == 1) ++ap;
 if (p5 == 0 && p6 == 1) ++ap;
 if (p6 == 0 && p7 == 1) ++ap;
 if (p7 == 0 && p8 == 1) ++ap;
 if (p8 == 0 && p9 == 1) ++ap;
 if (p9 == 0 && p2 == 1) ++ap;
 
 if (ap == 1 && p2 * p4 * p6 == 0 && p4 * p6 * p8 == 0)
 {
 
 mFlag.push_back(p + j);
 }
 }
 }
 }
 
 
 for (std::vector<uchar *>::iterator i = mFlag.begin(); i != mFlag.end(); ++i)
 {
 **i = 0;
 }
 
 
 if (mFlag.empty())
 {
 break;
 }
 else
 {
 mFlag.clear();
 }
 
 
 for (int i = 0; i < height; ++i)
 {
 uchar * p = dst.ptr<uchar>(i);
 for (int j = 0; j < width; ++j)
 {
 
 
 
 
 uchar p1 = p[j];
 if (p1 != 1) continue;
 uchar p4 = (j == width - 1) ? 0 : *(p + j + 1);
 uchar p8 = (j == 0) ? 0 : *(p + j - 1);
 uchar p2 = (i == 0) ? 0 : *(p - dst.step + j);
 uchar p3 = (i == 0 || j == width - 1) ? 0 : *(p - dst.step + j + 1);
 uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1);
 uchar p6 = (i == height - 1) ? 0 : *(p + dst.step + j);
 uchar p5 = (i == height - 1 || j == width - 1) ? 0 : *(p + dst.step + j + 1);
 uchar p7 = (i == height - 1 || j == 0) ? 0 : *(p + dst.step + j - 1);
 
 if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6)
 {
 int ap = 0;
 if (p2 == 0 && p3 == 1) ++ap;
 if (p3 == 0 && p4 == 1) ++ap;
 if (p4 == 0 && p5 == 1) ++ap;
 if (p5 == 0 && p6 == 1) ++ap;
 if (p6 == 0 && p7 == 1) ++ap;
 if (p7 == 0 && p8 == 1) ++ap;
 if (p8 == 0 && p9 == 1) ++ap;
 if (p9 == 0 && p2 == 1) ++ap;
 
 if (ap == 1 && p2 * p4 * p8 == 0 && p2 * p6 * p8 == 0)
 {
 
 mFlag.push_back(p + j);
 }
 }
 }
 }
 
 
 for (std::vector<uchar *>::iterator i = mFlag.begin(); i != mFlag.end(); ++i)
 {
 **i = 0;
 }
 
 
 if (mFlag.empty())
 {
 break;
 }
 else
 {
 mFlag.clear();
 }
 }
 return dst;
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | int main(int argc, char*argv[]){
 Mat src = imread("1.jpg");
 imshow("原图", src);
 if (src.empty())
 {
 std::cout << "读取文件失败!" << std::endl;
 return -1;
 }
 
 Mat src_gray;
 cvtColor(src,src_gray,CV_BGR2GRAY);
 Mat src_binary;
 
 cv::threshold(src_gray, src_binary, 128, 1, cv::THRESH_BINARY);
 
 cv::Mat dst = thinImage(src_binary);
 
 dst = dst * 255;
 
 cv::imshow("骨架细化后", dst);
 cv::waitKey(0);
 }
 
 |