基于opencv的骨架提取算法
时间: 2023-10-28 07:06:04 浏览: 295
基于OpenCV的骨架提取算法可以通过以下步骤实现:
1. 读入图像并进行预处理,如二值化、去噪等操作。
2. 对预处理后的图像进行边缘检测,可以使用Canny算子。
3. 对边缘图像进行膨胀操作,使得边缘连接成为连通区域。
4. 对膨胀后的图像进行骨架提取,可以使用Zhang-Suen骨架提取算法。
5. 对提取得到的骨架进行后处理,如去掉断点、去掉小分支等操作。
6. 可以将处理后的骨架图像进行可视化或保存。
需要注意的是,骨架提取算法的效果受到图像质量、预处理参数等因素的影响,需要根据具体情况进行调整。
相关问题
骨架提取算法python
骨架提取算法,又称为细化算法,是一种可以将二值图像中的对象细化为单像素宽度的算法。下面是一个基于Python的骨架提取算法示例:
```python
import cv2
import numpy as np
def thinning(img):
# 定义细化算法需要的核
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
size = np.size(img)
skel = np.zeros(img.shape, np.uint8)
# 循环直到没有像素需要细化为止
while True:
eroded = cv2.erode(img, kernel)
temp = cv2.dilate(eroded, kernel)
temp = cv2.subtract(img, temp)
skel = cv2.bitwise_or(skel, temp)
img = eroded.copy()
zeros = size - cv2.countNonZero(img)
if zeros == size:
break
return skel
# 读入二值图像
img = cv2.imread('image.png', 0)
# 对图像进行反色处理
img = cv2.bitwise_not(img)
# 进行骨架提取
skel = thinning(img)
# 显示结果
cv2.imshow('Original Image', img)
cv2.imshow('Thinning Image', skel)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
在这个示例中,我们使用OpenCV库来读取和显示图像,并定义了一个名为"thinning"的函数来进行骨架提取。在该函数中,我们使用了腐蚀和膨胀操作来实现细化算法,并循环直到没有像素需要细化为止。最后,我们将得到的骨架图像显示出来。
请用C代码或C++代码,实现zi.jpg的两种骨架提取算法:顺序细化和北、南、东、西提取算法。
由于图像骨架提取算法比较复杂,需要用到图像处理的相关知识,因此下面只提供基本思路和代码示例,具体实现可能需要根据实际情况进行调整。
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;
}
```
阅读全文