请用C代码或C++代码,实现zi.jpg的两种骨架提取算法:顺序细化和北、南、东、西提取算法。
时间: 2023-12-03 13:46:49 浏览: 87
由于图像骨架提取算法比较复杂,需要用到图像处理的相关知识,因此下面只提供基本思路和代码示例,具体实现可能需要根据实际情况进行调整。
1. 顺序细化算法
顺序细化算法是一种迭代算法,主要思想是不断对二值化图像进行腐蚀操作,直到得到骨架为止。具体步骤如下:
1)将二值化图像进行膨胀操作,得到初始图像。
2)对初始图像进行迭代处理,每次迭代时进行以下操作:
a. 对当前图像进行腐蚀操作。
b. 对腐蚀后的图像进行骨架判断,如果满足条件则将该像素点置为0。
c. 判断是否所有骨架点都已经被删除,如果是则结束迭代。
d. 否则继续迭代。
下面是使用OpenCV库实现的顺序细化算法的示例代码:
```c++
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void thinningIteration(Mat& img, int iter)
{
Mat marker = Mat::zeros(img.size(), CV_8UC1);
for (int i = 1; i < img.rows - 1; i++)
{
for (int j = 1; j < img.cols - 1; j++)
{
uchar p2 = img.at<uchar>(i - 1, j);
uchar p3 = img.at<uchar>(i - 1, j + 1);
uchar p4 = img.at<uchar>(i, j + 1);
uchar p5 = img.at<uchar>(i + 1, j + 1);
uchar p6 = img.at<uchar>(i + 1, j);
uchar p7 = img.at<uchar>(i + 1, j - 1);
uchar p8 = img.at<uchar>(i, j - 1);
uchar p9 = img.at<uchar>(i - 1, j - 1);
int A = (p2 == 0 && p3 == 1) + (p3 == 0 && p4 == 1) +
(p4 == 0 && p5 == 1) + (p5 == 0 && p6 == 1) +
(p6 == 0 && p7 == 1) + (p7 == 0 && p8 == 1) +
(p8 == 0 && p9 == 1) + (p9 == 0 && p2 == 1);
int B = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
int m1 = iter == 0 ? ((p2 * p4 * p6) == 0) : ((p2 * p4 * p8) == 0);
int m2 = iter == 0 ? ((p4 * p6 * p8) == 0) : ((p2 * p6 * p8) == 0);
if (A == 1 && (B >= 2 && B <= 6) && m1 == 1 && m2 == 1)
{
marker.at<uchar>(i, j) = 1;
}
}
}
img &= ~marker;
}
void thinning(Mat& img)
{
img /= 255;
Mat prev = Mat::zeros(img.size(), CV_8UC1);
Mat diff;
do
{
thinningIteration(img, 0);
thinningIteration(img, 1);
absdiff(img, prev, diff);
img.copyTo(prev);
} while (countNonZero(diff) > 0);
img *= 255;
}
int main()
{
Mat src = imread("zi.jpg", IMREAD_GRAYSCALE);
Mat dst;
threshold(src, dst, 128, 255, THRESH_BINARY);
thinning(dst);
imshow("src", src);
imshow("dst", dst);
waitKey(0);
return 0;
}
```
2. 北、南、东、西提取算法
北、南、东、西提取算法是一种基于邻域关系的算法,主要思想是对每个像素点进行判断,如果该点满足条件,则将其标记为骨架点。具体步骤如下:
1)对二值化图像进行膨胀操作。
2)对膨胀后的图像进行遍历,对于每个像素点(x,y),进行以下操作:
a. 统计(x,y)的8邻域中1的个数,如果不等于1则跳过。
b. 统计(x,y)的4邻域中1的个数,如果等于1或2,则将(x,y)标记为骨架点。
下面是使用C++实现的北、南、东、西提取算法的示例代码:
```c++
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void skeletonize(Mat& img)
{
Mat skel(img.size(), CV_8UC1, Scalar(0));
Mat temp(img.size(), CV_8UC1);
threshold(img, img, 1, 255, THRESH_BINARY);
do
{
morphologyEx(img, temp, MORPH_OPEN, getStructuringElement(MORPH_CROSS, Size(3, 3)));
bitwise_not(temp, temp);
bitwise_and(img, temp, temp);
bitwise_or(skel, temp, skel);
erode(img, img, getStructuringElement(MORPH_CROSS, Size(3, 3)));
} while (countNonZero(img) > 0);
img = skel;
}
int main()
{
Mat src = imread("zi.jpg", IMREAD_GRAYSCALE);
Mat dst;
threshold(src, dst, 128, 1, THRESH_BINARY);
skeletonize(dst);
dst *= 255;
imshow("src", src);
imshow("dst", dst);
waitKey(0);
return 0;
}
```
阅读全文