iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >OpenCV实现图像细化算法
  • 836
分享到

OpenCV实现图像细化算法

OpenCV图像细化 2022-11-13 14:11:27 836人浏览 安东尼
摘要

目录1.基础概念2.细化过程3.代码实现4.实验结果1.基础概念 图像细化(Image Thinning),一般指二值图像的骨架化(Image Skeletonization)的一种

1.基础概念

图像细化(Image Thinning),一般指二值图像的骨架化(Image Skeletonization)的一种操作运算。细化是将图像的线条从多像素宽度减少到单位像素宽度过程的简称,一些文章经常将细化结果描述为“骨架化”、“中轴转换”和“对称轴转换”。

细化技术的一个主要应用领域是位图矢量化的预处理阶段,相关研究表明,利用细化技术生成的位图的骨架质量受到多种因素的影响,其中包括图像自身的噪声、线条粗细不均匀、端点的确定以及线条交叉点选定等,因而对线划图像进行细化从而生成高质量骨架的方法进行研究具有现实意义。

根据算法处理步骤的不同,细化算法分为迭代细化算法和非迭代细化算法。根据检查像素方法的不同,迭代细化算法又分为串行细化算法和并行细化算法。

迭代算法:即重复删除图像边缘满足一定条件的像素,最终得到单像素宽带骨架。

迭代方法依据其检查像素的方法又可以再分成:

  • 串行算法:在串行算法中,通过在每次迭代中用固定的次序检查像素来判断是否删除像素,在第n次迭代中像素p的删除取决于到执行过的所有操作,也就是必须在第(n-1)次迭代结果和第n次检测像素的基础之上进行像素删除操作;即是否删除像素在每次迭代的执行中是固定顺序的,它不仅取决于前次迭代的结果,也取决于本次迭代中已处理过像素点分布情况。
  • 并行算法:在并行算法中,第n次迭代中像素的删除只取决于(n-1)次迭代后留下的结果,因此所有像素能在每次迭代中以并行的方式独立的被检测;即像素点删除与否与像素值图像中的顺序无关,仅取决于前次迭代效果。

2.细化过程

细化算法有ZS算法和查表法。ZS细化算法是一种基于8领域的并行细化算法,通过对目标像素8领域进行分布的算术逻辑运算,来确定该像素是否能删除。八领域如下图所示。

在这里插入图片描述

细化判断依据为:内部点不能删除、孤立不能删除、直线端点不能删除。
ZS细化过程如下:

第一次迭代,若P1满足以下四个条件,说明P1为边界点,可以删除,将P1值设为0:
(1)2 小于等于 Pi从i=2到i=9的和 小于等于6
(2)S(P1)=1;
(3)P2×P4×P6=0;
(4)P4×P6×P8=0;

条件(1)中若P2至P9的和在2至6之间,说明P1为边界点。S(P1)表示目标像素P1的8邻域中,顺时针变化一周像素由0变1的次数。在目标点8邻域P2-P9的范围内,像素值由0变1的次数只能为1次。条件(2)保证了图像细化后的连通性。
第二次迭代中,像素点如果满足第一次迭代中的条件(1)和(2)及以下条件,则移除该像素点:

(5)P2×P4×P8=0;
(6)P2×P6×P8=0;

重复以上迭代过程,直至处理完所有像素点,此时细化完成。
查表法中,由于输入的图像是一张二值图,将其归一化为像素值只有0和1的图像,然后对其进行卷积操作。具体卷积操作为:将目标点的八领域和卷积进行点乘,接着将所有值相加即可得表的索引M,下一步用索引值M去找表中对应的值,对应的值为0或1,就把目标点的像素值修改为0或1,其中1为不可删除点,0位可删除点。重复上述步骤,遍历完所有像素点,对目标点进行查表、修改目标像素值,最后得到细化结果。

3.代码实现

#include<iOStream>
#include <OpenCV2\opencv.hpp>

using namespace std;
using namespace cv;

//查表法//
Mat lookUpTable(Mat& mat, int lut[])
{
	Mat mat_in;
	mat.convertTo(mat_in, CV_16UC1);		 //8 转 16
	int MatX = mat_in.rows;
	int MatY = mat_in.cols;
	int num = 512;
	//表的维数和卷积核中的数据有关,小矩阵初始化按行赋值
	Mat kern = (Mat_<int>(3, 3) << 1, 8, 64, 2, 16, 128, 4, 32, 256);		//卷积核
	Mat mat_out = Mat::zeros(MatX, MatY, CV_16UC1);
	Mat mat_expend = Mat::zeros(MatX + 2, MatY + 2, CV_16UC1);

	Rect Roi(1, 1, MatY, MatX);				//(列,行,列,行)

	Mat mat_expend_Roi(mat_expend, Roi);	//确定扩展矩阵的Roi区域
	mat_in.copyTo(mat_expend_Roi);			//将传入矩阵赋给Roi区域

	Mat Mat_conv;

	//实用卷积核和和每一个八邻域进行点乘再相加,其结果为表的索引,对应值为0能去掉,为1则不能去掉
	filter2D(mat_expend, Mat_conv, mat_expend.depth(), kern);				//卷积
	Mat mat_index = Mat_conv(Rect(1, 1, MatY, MatX));
	for (int i = 0; i < MatX; i++)
	{
		for (int j = 0; j < MatY; j++)
		{
			int matindex = mat_index.at<short>(i, j);

			if ((matindex < num) && (matindex > 0))
			{
				mat_out.at<short>(i, j) = lut[matindex];
			}
			else if (matindex > num)
			{
				mat_out.at<short>(i, j) = lut[num - 1];
			}
		}
	}
	return mat_out;
}

//道路细化查表法//
Mat img_bone(Mat& mat)
{
	// mat 为细化后的图像
	Mat mat_in = mat;

	//在数字图像处理时,只有单通道、三通道 8bit 和 16bit 无符号(即CV_16U)的 mat 才能被保存为图像
	mat.convertTo(mat_in, CV_16UC1);

	int lut_1[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };

	int lut_2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1,
					0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
					0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 };

	Mat mat_bool;

	threshold(mat_in, mat_bool, 0, 1, THRESH_BINARY);	//二值图像归一化

	Mat mat_out;

	Mat image_iters;

	while (true)
	{
		mat_out = mat_bool;

		//查表:水平、垂直
		image_iters = lookUpTable(mat_bool, lut_1);
		mat_bool = lookUpTable(image_iters, lut_2);

		Mat diff = mat_out != mat_bool;

		//countNonZero函数返回灰度值不为0的像素数
		bool mat_equal = countNonZero(diff) == 0;		//判断图像是否全黑

		if (mat_equal)
		{
			break;
		}
	}
	Mat Matout;

	mat_bool.convertTo(Matout, CV_8UC1);

	return Matout;
}

//主函数
int main()
{
	Mat src_img, src_imgBool;

	//输入道路二值图,参数 0 是指imread按单通道的方式读入图像,即灰白图像
	src_img = imread("......png", 0);
	
	//去掉噪,例如过滤很小或很大像素值的图像点
	//threshold(src_img, src_imgBool, 0, 255, THRESH_OTSU);
	//threshold(src_img, src_imgBool, 0, 155, THRESH_OTSU);
	//imshow("Binary Image", src_imgBool);

	Mat imgbone = img_bone(src_img);

	//保存结果
	imwrite("D:\\Desktop\\......\\细化222.png", imgbone * 255);
	
	waiTKEy();
	system("pause");
	return 0;
}

4.实验结果

细化前

在这里插入图片描述

细化后

在这里插入图片描述

到此这篇关于OpenCV实现图像细化算法的文章就介绍到这了,更多相关OpenCV 图像细化内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: OpenCV实现图像细化算法

本文链接: https://www.lsjlt.com/news/171505.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • OpenCV实现图像细化算法
    目录1.基础概念2.细化过程3.代码实现4.实验结果1.基础概念 图像细化(Image Thinning),一般指二值图像的骨架化(Image Skeletonization)的一种...
    99+
    2022-11-13
    OpenCV 图像细化
  • OpenCV图像算法实现图像切分图像合并示例
    目录将一张图片切分成多个小图片并将小图片合并为原图图像切分图像合并验证友情提示将一张图片切分成多个小图片并将小图片合并为原图 最近用到一个功能,需要将一张原图切分成多个小图像,然后对...
    99+
    2022-11-13
  • OpenCV图像算法怎么实现图像切分图像合并
    本篇内容介绍了“OpenCV图像算法怎么实现图像切分图像合并”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!将一张图片切分成多个小图片并将小图...
    99+
    2023-06-30
  • OpenCV如何实现图像去噪算法
    今天小编给大家分享一下OpenCV如何实现图像去噪算法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、函数参考1、Prim...
    99+
    2023-07-02
  • OpenCV实现拼图算法
    本文实例为大家分享了OpenCV实现拼图算法的具体代码,供大家参考,具体内容如下 编程环境:VS2012+OpenCV2.4.6 功能: 第一种是将指定三幅图的指定位置的像素直接搬移...
    99+
    2022-11-12
  • OpenCV实现图像去噪算法的步骤详解
    目录一、函数参考1、Primal-dual算法2、非局部均值去噪算法三、OpenCV源码1、源码路径2、源码代码四、效果图像示例一、函数参考 1、Primal-dual算法 Prim...
    99+
    2022-11-13
  • C++中实现OpenCV图像分割与分水岭算法
    分水岭算法是一种图像区域分割法,在分割的过程中,它会把跟临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性是分水...
    99+
    2022-11-12
  • C++ OpenCV如何实现图像双三次插值算法
    本篇内容主要讲解“C++ OpenCV如何实现图像双三次插值算法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++ OpenCV如何实现图像双三次插值算法”吧!一、图像双三...
    99+
    2023-06-21
  • C++OpenCV实现图像双三次插值算法详解
    目录前言一、图像双三次插值算法原理二、C++ OpenCV代码1.计算权重矩阵2.遍历插值3. 测试及结果前言 近期在学习一些传统的图像处理算法,比如传统的图像插值算法等。传统的图像...
    99+
    2022-11-12
  • OpenCV 图像梯度的实现方法
    目录概述梯度运算礼帽黑帽Sobel 算子计算 x计算 y计算 x+y融合概述 OpenCV 是一个跨平台的计算机视觉库, 支持多语言, 功能强大. 今天小白就带大家一起携手走进 Op...
    99+
    2022-11-12
  • 详解Python+OpenCV实现图像二值化
    目录一、图像二值化1.效果2.源码二、图像二值化(调节阈值)1.源码一2.源码二一、图像二值化 1.效果 2.源码 import cv2 import numpy as np im...
    99+
    2022-11-11
  • OpenCV图像的二值化怎么实现
    这篇“OpenCV图像的二值化怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“OpenCV图像的二值化怎么实现”文章吧...
    99+
    2023-07-05
  • 深入探讨opencv图像矫正算法实战
    摘要 在机器视觉中,对于图像的处理有时候因为放置的原因导致ROI区域倾斜,这个时候我们会想办法把它纠正为正确的角度视角来,方便下一步的布局分析与文字识别,这个时候通过透视变换就可以取...
    99+
    2022-11-12
  • OpenCV实现图像膨胀
    图像的膨胀与图像腐蚀是一对相反的过程,与图像腐蚀相似,图像膨胀同样需要结构元素用于控制图像膨胀的效果。结构元素可以任意指定结构的中心点,并且结构元素的尺寸和具体内容都可以根据需求自己...
    99+
    2022-11-12
  • OpenCV实现图像腐蚀
    图像的腐蚀过程与图像的卷积操作类似,都需要模板矩阵来控制运算的结果,在图像的腐蚀和膨胀中这个模板矩阵被称为结构元素。与图像卷积相同,结构元素可以任意指定图像的中心点,并且结构元素的尺...
    99+
    2022-11-12
  • openCV实现图像分割
    本次实验为大家分享了openCV实现图像分割的具体实现代码,供大家参考,具体内容如下 一.实验目的 进一步理解图像的阈值分割方法和边缘检测方法的原理。 掌握图像基本全局阈值方法和最大...
    99+
    2022-11-12
  • opencv实现图像平移
    本文实例为大家分享了opencv实现图像平移的具体代码,供大家参考,具体内容如下 图像平移指的是沿水平方向或垂直方向进行图像的移动。 平移变换公式: 对于原始图像而言,正变换矩阵:...
    99+
    2022-11-13
    opencv 图像平移
  • opencv实现图像校正
    本文实例为大家分享了opencv实现图像校正的具体代码,供大家参考,具体内容如下 1.引言:python实现倾斜图像校正操作 2.思路流程: (1)读入,灰度化;(2)高斯模糊;(3...
    99+
    2022-11-11
  • Python OpenCV超详细讲解图像堆叠的实现
    目录准备工作水平堆叠垂直堆叠图像栈堆叠准备工作 右击新建的项目,选择Python File,新建一个Python文件,然后在开头import cv2导入cv2库,import num...
    99+
    2022-11-13
  • OpenCV图像分割之分水岭算法与图像金字塔算法详解
    目录前言一、使用分水岭算法分割图像1、cv2.distanceTransform()函数2、cv2.connectedComponents()函数3、cv2.watershed()函...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作