视觉组学习内容:Zhang-Suen骨架提取算法

本文详述了使用Zhang-Suen骨架提取算法简化数字轮廓的过程,包括在Windows环境下编写函数代码,类的封装,Ubuntu环境的配置,以及在Linux终端使用g++编译。通过该任务,作者不仅理解了算法原理,还复习了C++面向对象编程,并深入学习了Ubuntu系统和opencv库的使用。
摘要由CSDN通过智能技术生成

前言

这是视觉组dalao给大家布置的学期末学习任务。
因为之前没有接触过linux,环境也没有配置好,对很多操作不够熟悉,做这个任务从头到尾大约花了两天合计15个小时的时间,中间还问过dalao两个小时左右的问题(此处给大佬比心),虽然和大佬说的三个小时相去甚远但是最后还是赶在ddl之前完成了任务。
总的来说收获很多,了解了ZhangSuen骨架提取算法的原理和算法实现,复习了面向对象编程的C++,还对linux系统(Ubuntu)有了进一步的了解,写第一篇博文记录一下大致过程和心得。

任务要求

使用ZhangSuen骨架提取算法实现简化数字轮廓

效果如图所示: Alt

实现要求

  • 使用类简化代码量,增强可读性;类的声明放在.h头文件中,函数实现单独放在.cpp文件中
  • 不允许包含<opencv2/opencv.hpp>;把要用到的模块搞清楚,包含最少的头文件
  • Linux下使用命令行或makefile编译程序,不允许使用pkg-config,不能有-lopencv_*这种写法,需要用到哪个库文件就明确调用哪个库文件

任务完成流程概要

1.在Windows平台的VS 2017上写好函数风格代码

这里参考了CSDN上和博客园的两篇文章,分别涉及原理和代码实现,链接附上

2.使用类对原函数进行封装与调试

  • 复习C++面向对象编程
    类的成员函数定义、初始化函数等概念的复习
  • 类的声明/定义/使用
    类的封装风格参考过图像处理之Zhang Suen细化算法 博主:gloomyfish,虽然是java平台的opencv,但是可以启发灵感
    代码应该是在Ubuntu的环境中直接写的,但是由于没有配置,所以先在Windows写好以后再到Ubuntu里面使用,代码见后。

3.配置Ubuntu环境

  • 换源
    换源是为了提高网络速度。这里弄了一阵子的时间,原因是因为很多教程都不是从零起步,而且有一定问题。很多网站上都是直接用vim(有可能没安装) 或者使用“打开”/"编辑"这种用语,对初入Ubuntu的小白很不友好。
    正确操作是先按Ctrl+Alt+T打开终端,然后输入sudo gedit /etc/apt/sources.list,在打开的文件窗口中将内容全部删除并复制上镜像源地址:参考Ubuntu 18.04换国内源 中科大源 阿里源 163源 清华源 博主:nudt_qxx,从中选一个复制粘贴(终端中的粘贴是Ctrl+Shift+V),然后把结尾CSDN附带的注释删除再保存就可以了,不知道需不需要重启。
  • 安装cmake(虽然没用上)
    用于cmake和makefile(?)
  • 安装opencv环境
    任务3要求在终端中编译(编译用g++,这个我是自己用sudo apt-get install g++安装的)或者用makefile。不配置opencv的环境无法编译项目。
    在终端中使用sudo apt-get install synapic,再在系统自带的新立得安装包管理器里搜索opencv就可以下载了。出乎意料的方便。
  • 安装编辑器及其他软件

4.在Terminal中使用g++完成编译

  • 使用g++编译
    大佬实力操作。
    到这一步要准备编译。首先把我写好的两个cpp和一个.h文件放到同一个文件夹下,然后在右键菜单中点击“在终端打开”,输入g++ -o Zhenglin main.cpp class.cpp `pkg-config --libs --cflags opencv`要求3是不允许使用pkg-config和-lopencv_*,那写g++ -o z class.cpp main.cpp -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs也是正确的。注意,虽然头文件没有,但是终端还是要通过-l调用-lopencv_imgcodecs,否则会报错。
    如果程序正确,编译成功了就会生成一个叫做Zhenglin的文件,此时再输入./Zhenglin就可以执行这个文件了。可以看到输出结果。
    结果
    注意:使用文件时要注意有没有输入的图片,需要在源文件中修改路径。

封装代码

头文件

#ifndef C_ZHANGSUEN_DIY_H
#define C_ZHANGSUEN_DIY_H

#include<opencv2/core.hpp>											///基本数据类型
#include<opencv2/imgproc/imgproc.hpp>								///图像存取&线性变换
#include<opencv2/highgui.hpp>										///输出接口&交互接口

using namespace std;
using namespace cv;

class Skeleton {
   
public:
	void initialize();
	void getDst(Mat src);
	void DstToImg();
	int getAP(int i, int j);
	int getBP(int i, int j);
	bool condition34IsOK_1(int i, int j);
	bool condition34IsOK_2(int i, int j);
	void erasePoint(int i, int j);
	Mat Mat_return();
	Skeleton();
private:
	Mat dst;
	Mat tmpImg;
	int height;
	int width;
};

//主函数调用函数 函数调用类 并在函数体中判断条件 最后利用函数体返回



Mat skeleton(Mat src);

#endif //C_ZHANGSUEN_DIY_H

主文件

//*recoverd by Zhenglin/on 2018/12/29 
#include "ZhangSuen_DIY.h"/

Mat skeleton(Mat src);

int main(){
   
    Mat src = imread("E:/Python/6.jpg");
	Mat gray, binary, dst, skeleton_image;

	//图像预处理
	cvtColor(src, gray, CV_BGR2GRAY);
	threshold(gray, binary, 200, 255, CV_THRESH_BINARY);			///二值化需要在灰度基础上进行
	namedWindow("Binary", 0);										///只能对黑底白线进行提取,否则需要位反
	imshow("Binary", binary);

	//骨架提取
	skeleton_image = skeleton(binary);<
  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ZHANG-SUEN算法是一种用于图像二值化后的细化处理的算法。它可以将图像中的细线条变得更加细长和连续。以下是ZHANG-SUEN算法的步骤[^1]: 1. 初始化一个标志位,用于指示是否有像素点被删除。 2. 对于图像中的每个像素点,执行以下两个子步骤: a. 检查当前像素点是否为背景(黑色),如果是则跳过。 b. 检查当前像素点是否满足以下两个条件: - 周围8个像素点中,有且仅有一个像素点是背景(黑色)。 - 当前像素点的周围8个像素点中,从左上角开始顺时针方向计数,有2到6个像素点是背景(黑色)。 如果满足以上两个条件,则将当前像素点标记为待删除,并将标志位设置为True。 3. 对于图像中的每个像素点,执行以下两个子步骤: a. 检查当前像素点是否为背景(黑色),如果是则跳过。 b. 检查当前像素点是否满足以下两个条件: - 周围8个像素点中,有且仅有一个像素点是背景(黑色)。 - 当前像素点的周围8个像素点中,从左上角开始顺时针方向计数,有2到6个像素点是背景(黑色)。 如果满足以上两个条件,则将当前像素点标记为待删除,并将标志位设置为True。 4. 重复步骤2和步骤3,直到没有像素点被标记为待删除。 5. 对于图像中的每个像素点,执行以下两个子步骤: a. 检查当前像素点是否为背景(黑色),如果是则跳过。 b. 检查当前像素点是否满足以下两个条件: - 周围8个像素点中,有且仅有一个像素点是背景(黑色)。 - 当前像素点的周围8个像素点中,从左上角开始顺时针方向计数,有2到6个像素点是背景(黑色)。 如果满足以上两个条件,则将当前像素点标记为待删除,并将标志位设置为True。 6. 重复步骤4和步骤5,直到没有像素点被标记为待删除。 7. 细化处理完成。 以下是一个使用ZHANG-SUEN算法进行图像细化的Python代码示例[^1]: ```python import cv2 def zhang_suen_thinning(image): # 将图像转换为二值图像 ret, binary_image = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY) # 初始化标志位 has_deletion = True while has_deletion: has_deletion = False # 第一次迭代 for i in range(1, binary_image.shape - 1): for j in range(1, binary_image.shape - 1): if binary_image[i, j] == 0: continue # 获取周围8个像素点的值 neighbors = [binary_image[i-1, j-1], binary_image[i-1, j], binary_image[i-1, j+1], binary_image[i, j-1], binary_image[i, j+1], binary_image[i+1, j-1], binary_image[i+1, j], binary_image[i+1, j+1]] # 计算周围像素点的背景(黑色)数量 num_background = neighbors.count(0) # 计算周围像素点的背景(黑色)到非背景(白色)的过渡数量 num_transitions = 0 for k in range(len(neighbors)): if neighbors[k] == 255 and neighbors[(k+1) % len(neighbors)] == 0: num_transitions += 1 # 检查是否满足删除条件 if num_background == 1 and 2 <= num_transitions <= 6: binary_image[i, j] = 0 has_deletion = True # 第二次迭代 for i in range(1, binary_image.shape - 1): for j in range(1, binary_image.shape - 1): if binary_image[i, j] == 0: continue # 获取周围8个像素点的值 neighbors = [binary_image[i-1, j-1], binary_image[i-1, j], binary_image[i-1, j+1], binary_image[i, j-1], binary_image[i, j+1], binary_image[i+1, j-1], binary_image[i+1, j], binary_image[i+1, j+1]] # 计算周围像素点的背景(黑色)数量 num_background = neighbors.count(0) # 计算周围像素点的背景(黑色)到非背景(白色)的过渡数量 num_transitions = 0 for k in range(len(neighbors)): if neighbors[k] == 255 and neighbors[(k+1) % len(neighbors)] == 0: num_transitions += 1 # 检查是否满足删除条件 if num_background == 1 and 2 <= num_transitions <= 6: binary_image[i, j] = 0 has_deletion = True # 将二值图像转换为灰度图像 thinned_image = cv2.cvtColor(binary_image, cv2.COLOR_BINARY2GRAY) return thinned_image # 读取图像 image = cv2.imread('input_image.png', cv2.IMREAD_GRAYSCALE) # 进行细化处理 thinned_image = zhang_suen_thinning(image) # 显示结果 cv2.imshow('Thinned Image', thinned_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 请注意,上述代码中的`input_image.png`是输入图像的文件名,你需要将其替换为你自己的图像文件名。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值