图像处理-形态学操作


C++代码提取骨架的实现:(代码来自opencv的扩展模块ximgproc.hpp)

cpp 复制代码
void thinningIteration(Mat &img, int iter, int thinningType)
{
	Mat marker = Mat::zeros(img.size(), CV_8UC1);
	if (thinningType == 0)
	{
		for (int i = 1; i < img.rows - 1; i++)
		{
			for (int j = 1; j < img.cols - 1; j++)
			{
				if (img.at<uchar>(i, j) == 0)
				{
					continue;
				}
				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) : (p2 * p4 * p8);
				int m2 = iter == 0 ? (p4 * p6 * p8) : (p2 * p6 * p8);

				if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
					marker.at<uchar>(i, j) = 1;
			}
		}
	}
	if (thinningType == 1) //THINNING_GUOHALL
	{
		for (int i = 1; i < img.rows - 1; i++)
		{
			for (int j = 1; j < img.cols - 1; j++)
			{
				if (img.at<uchar>(i, j) == 0)
				{
					continue;
				}
				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 C = ((!p2) & (p3 | p4)) + ((!p4) & (p5 | p6)) +
					((!p6) & (p7 | p8)) + ((!p8) & (p9 | p2));
				int N1 = (p9 | p2) + (p3 | p4) + (p5 | p6) + (p7 | p8);
				int N2 = (p2 | p3) + (p4 | p5) + (p6 | p7) + (p8 | p9);
				int N = N1 < N2 ? N1 : N2;
				int m = iter == 0 ? ((p6 | p7 | (!p9)) & p8) : ((p2 | p3 | (!p5)) & p4);

				if ((C == 1) && ((N >= 2) && ((N <= 3)) & (m == 0)))
					marker.at<uchar>(i, j) = 1;
			}
		}
	}
	img &= ~marker;
}

Mat thinning(Mat input, int thinningType)
{
	Mat output = input.clone();
	// Enforce the range of the input image to be in between 0 - 255
	output /= 255;

	Mat prev = Mat::zeros(output.size(), CV_8UC1);
	Mat diff;

	do {
		thinningIteration(output, 0, thinningType);
		thinningIteration(output, 1, thinningType);
		absdiff(output, prev, diff);
		output.copyTo(prev);
	} while (countNonZero(diff) > 0);

	output *= 255;
	return output;
}
相关推荐
前端摸鱼匠几秒前
面试题7:Encoder-only、Decoder-only、Encoder-Decoder三种架构的差异与适用场景?
人工智能·深度学习·ai·面试·职场和发展·架构·transformer
ryrhhhh几秒前
矩阵跃动技术创新:GEO搜索占位+AI智能体双融合,重构企业获客链路
大数据·人工智能
no_work1 分钟前
基于python的hog+svm实现混凝土裂缝目标检测
人工智能·python·目标检测·计算机视觉
小陈工1 分钟前
2026年3月21日技术资讯洞察:云原生理性回归与Python异步革命
人工智能·python·云原生·数据挖掘·回归
柯儿的天空3 分钟前
【OpenClaw 全面解析:从零到精通】第 018 篇:OpenClaw 多智能体协作系统——多 Agent 路由、任务委托与负载均衡
运维·人工智能·aigc·负载均衡·ai编程·ai写作·agi
2301_766558653 分钟前
矩阵跃动OpenClaw龙虾机器人:本地AI智能体+GEO优化,企业流量自动化落地
人工智能·矩阵·机器人
crediks5 分钟前
MTGR(美团生成式推荐框架)总结文档
人工智能·深度学习·算法
Bonnie3736 分钟前
云原生vs传统IT架构-核心差异与迁移必要性
人工智能·程序人生·云原生·架构·个人开发
倔强的石头1067 分钟前
技术拆解:P2P组网如何一键远程AI
人工智能·网络协议·p2p
维度攻城狮7 分钟前
AI 工具加持:ComfyUI 节点开发极速上手
人工智能·python·comfyui·工作流·节点图