图像练习-计算平行线距离opencv(03)

news2024/12/26 23:10:19

原图 

 

//对输入图像进行细化
cv::Mat ThinLine(const cv::Mat& matsrc, const int& iterations)
{
	//CvSize size = cvGetSize(src);
	cv::Mat dst = matsrc.clone();//拷贝一个数组给另一个数组
	int _iwidth = dst.cols;
	int _iheight = dst.rows;
	int n = 0, i = 0, j = 0;
	for (n = 0; n < iterations; n++)
	{
		cv::Mat temp = dst.clone();
		for (i = 0; i < temp.rows; i++)
		{
			for (int j = 0; j < temp.cols; j++)
			{
				if ((*temp.ptr<uchar>(i, j)) == 1)
				{
					int ap = 0;
					int p2 = (i == 0) ? 0 : (*temp.ptr<uchar>(i - 1, j));
					int p3 = (i == 0 || j == _iwidth - 1) ? 0 : (*temp.ptr<uchar>(i - 1, j + 1));
					if (p2 == 0 && p3 == 1)
					{
						ap++;
					}
					int p4 = (j == _iwidth - 1) ? 0 : (*temp.ptr<uchar>(i, j + 1));
					if (p3 == 0 && p4 == 1)
					{
						ap++;
					}
					int p5 = (i == _iwidth - 1 || j == _iwidth - 1) ? 0 : (*temp.ptr<uchar>(i + 1, j + 1));
					if (p4 == 0 && p5 == 1)
					{
						ap++;
					}
					int p6 = (i == _iwidth - 1) ? 0 : (*temp.ptr<uchar>(i + 1, j));
					if (p5 == 0 && p6 == 1)
					{
						ap++;
					}
					int p7 = (i == _iwidth - 1 || j == 0) ? 0 : (*temp.ptr<uchar>(i + 1, j - 1));
					if (p6 == 0 && p7 == 1)
					{
						ap++;
					}
					int p8 = (j == 0) ? 0 : (*temp.ptr<uchar>(i, j - 1));
					if (p7 == 0 && p8 == 1)
					{
						ap++;
					}
					int p9 = (i == 0 || j == 0) ? 0 : (*temp.ptr<uchar>(i - 1, j - 1));
					if (p8 == 0 && p9 == 1)
					{
						ap++;
					}
					if (p9 == 0 && p2 == 1)
					{
						ap++;
					}
					if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) > 1 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) < 7)
					{
						if (ap == 1)
						{
							if (p2 * p4 * p8 == 0)
							{
								if (p2 * p6 * p8 == 0)
								{
									(*dst.ptr<uchar>(i, j)) = 0;
								}
							}
						}
					}
				}

			}

		}
	}

	//将二值图像转换成灰度,以便显示
	for (i = 0; i < dst.rows; i++)
	{
		for (j = 0; j < dst.cols; j++)
		{
			if ((*dst.ptr<uchar>(i, j)) == 1)
			{
				(*dst.ptr<uchar>(i, j)) = 255;
			}
			else
			{
				(*dst.ptr<uchar>(i, j)) = 0;
			}
		}
	}

	return dst;
}

void LineDistance()
{
	cv::Mat src = cv::imread("平行线求距离.png", cv::IMREAD_COLOR);

	cv::Mat gray;
	cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);

	cv::Mat thre;
	cv::threshold(gray, thre, 128, 1, cv::THRESH_BINARY_INV);

	//第一步 对图像中的直线进行细化
	cv::Mat line = ThinLine(thre, 50);

	//第二步  提取直线的轮廓坐标
	std::vector<std::vector<cv::Point>> contours;
	cv::findContours(line, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);

	cv::Mat show = src.clone();
	cv::drawContours(show, contours, -1, cv::Scalar(255));

	//直线拟合 	
   //拟合结果为一个四元素的容器,比如Vec4f - (vx, vy, x0, y0)
   //其中(vx, vy) 是直线的方向向量 (x0, y0) 是直线上的一个点
	cv::Vec4d l0;
	cv::fitLine(contours[0], l0, cv::DIST_L2, 0, 0.01, 0.01);//拟合方法采用最小二乘法

	double cos_theta0 = l0[0];
	double sin_theta0 = l0[1];
	double x0 = l0[2], y0 = l0[3];

	double k0 = sin_theta0 / cos_theta0;
	double b0 = y0 - k0 * x0;
	printf("line0: y = %f * x + %f \n", k0 * 180.0 / CV_PI, b0);

	double x = 0;
	double y = k0 * x + b0;

	cv::Vec4d l1;
	//拟合方法采用最小二乘法
	cv::fitLine(contours[1], l1, cv::DIST_L2, 0, 0.01, 0.01);
	double cos_theta1 = l1[0];
	double sin_theta1 = l1[1];
	double x1 = l1[2], y1 = l1[3];

	double k1 = sin_theta1 / cos_theta1;
	double b1 = y1 - k1 * x1;
	printf("line1: y = %f * x + %f \n", k1 * 180.0 / CV_PI, b1);

	//第四部  计算两条直线之间的距离 公式是: |b1 - b0| / sqrt(A * A + B * B)
	double A = k0;
	double B = 1.0;
	double 	dis = abs(b1 - b0) / sqrt(A * A + B * B);
	printf("dis is %f \n", dis);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1040196.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【每日一题】658. 找到 K 个最接近的元素

658. 找到 K 个最接近的元素 - 力扣&#xff08;LeetCode&#xff09; 给定一个 排序好 的数组 arr &#xff0c;两个整数 k 和 x &#xff0c;从数组中找到最靠近 x&#xff08;两数之差最小&#xff09;的 k 个数。返回的结果必须要是按升序排好的。 整数 a 比整数 b 更接近 …

抖音SEO矩阵系统源码开发搭建

1. 确定需求和功能&#xff1a;明确系统的主要目标和需要实现的功能&#xff0c;包括关键词研究、短视频制作、外链建设、数据分析、账号设置优化等方面。 2. 设计系统架构&#xff1a;根据需求和功能确定系统的架构&#xff0c;包括前端、后端、数据库等部分的设计&#xff0…

计算机组成原理之硬件的内部结构,拆开单独的硬件,查看硬件组成部分的结构和功能。

大家好&#xff0c;欢迎阅读《计算机组成原理》的系列文章&#xff0c;本系列文章主要教内容是从零学习计算机组成原理&#xff0c;内容通俗易懂&#xff0c;大家好好学习吧&#xff01;&#xff01;&#xff01; 更多的优质内容&#xff0c;请点击以下链接查看哦~~ ↓ ↓ ↓ …

【加载数据--自定义自己的Dataset类】

【加载数据自定义自己的Dataset类】 1 加载数据2 数据转换3 自定义Dataset类4 划分训练集和测试集5 提取一批次数据并绘制样例图 假设有四种天气图片数据全部存放与一个文件夹中&#xff0c;如下图所示&#xff1a; ├─dataset2 │ cloudy1.jpg │ cloudy10.jpg │ …

使用matlab产生二维动态曲线视频文件具体举例

使用matlab产生二维动态曲线视频文件举例 在进行有些函数变化过程时候&#xff0c;需要用到直观的动态显示&#xff0c;本博文将举例说明利用Matlab编程进行二维动态曲线的生成视频文件。 一、问题描述 利用matlab编程实现 y 1 s i n ( t ) , y 2 c o s ( t ) , y 3 s i …

JAVA_多线程的实现方式

线程的状态 方式一&#xff1a; public class Thread1 extends Thread {Overridepublic void run() {synchronized (this) {for (int i 0; i < 100; i) {System.out.println(getName() "" i);}}} } Thread1 thread1 new Thread1(); thread1.start(); 方式二…

用flex实现grid布局

1. css代码 .flexColumn(columns, gutterSize) {display: flex;flex-flow: row wrap;margin: calc(gutterSize / -2);> div {flex: 0 0 calc(100% / columns);padding: calc(gutterSize / 2);box-sizing: border-box;} }2.用法 .grid-show-item3 {width: 100%;display: fl…

天洑软件祝贺“星耀蓉城 篮能可贵”四城邀请赛暨西北工业大学校友篮球嘉年华活动圆满举办

9月16日&#xff0c;由西北工业大学成都校友会主办&#xff0c;成都市新都区文化体育和旅游局承办&#xff0c;天洑软件、泸州老窖、陕西省篮球协会、龙湖地产、奥伦达科技、南京全信、成都鑫长源、四川银行、优仿科技、华科机电、小鱼易连、四川省篮球协会、GAME7篮球俱乐部赞…

云安全之访问控制介绍

访问控制技术背景 信息系统自身的复杂性、网络的广泛可接入性等因素&#xff0c;系统面临日益增多的安全威胁&#xff0c;安全问题日益突出&#xff0c;其中一个重要的问题是如何有效地保护系统的资源不被窃取和破坏。 访问控制技术内容包括访问控制策略、访问控制模型、访问…

virtualbox无界面打开linux虚拟机的bat脚本,以及idea(代替Xshell)连接linux虚拟机的方法

virtualbox无界面打开linux虚拟机的bat脚本&#xff0c;以及idea连接linux虚拟机的方法 命令行运行代码成功运行的效果图 idea连接linux虚拟机的方法【重要】查看虚拟机的IP地址idea中选择菜单&#xff08;该功能可代替Xshell软件&#xff09;配置设置连接成功进入idea中的命令…

MySQL数据库入门到精通9--运维篇

1. 日志 1.1 错误日志 错误日志是 MySQL 中最重要的日志之一&#xff0c;它记录了当 mysqld 启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时&#xff0c;建议首先查看此日志。 该日志是默认开启的&am…

解决安装 RabbitMQ 安装不成功的问题

由于RabbitMQ是基于erlang的&#xff0c;所以&#xff0c;在正式安装RabbitMQ之前&#xff0c;需要先安装一下erlang。 1、下载mq https://www.rabbitmq.com/download.html 2、下载erlang&#xff08;点击下载路径根据下载的MQ版本对应下载erl版本&#xff09; https://www.…

客户端负载均衡_什么是负载均衡

为什么需要负载均衡 俗话说在生产队薅羊毛不能逮着一只羊薅&#xff0c;在微服务领域也是这个道理。面对一个庞大的微服务集群&#xff0c;如果你每次发起服务调用都只盯着那一两台服务器&#xff0c;在大用户访问量的情况下&#xff0c;这几台被薅羊毛的服务器一定会不堪重负…

澳大利亚新版《2023年消费品(36个月以下儿童玩具) 安全标准》发布 旨在降低危险小零件的伤害

2023年9月4日&#xff0c;澳大利亚政府发布了新的儿童玩具强制性安全标准《2023年消费品(36个月以下儿童玩具)安全标准》&#xff08;Consumer Goods (Toys for Children up to and including 36 Months of Age) Safety Standard 2023&#xff09;。该强制性标准旨在尽可能地降…

2023/9/24总结

Redis Redis 是一个基于内存的键值数据库 安装 Window下Redis的安装和部署详细图文教程&#xff08;Redis的安装和可视化工具的使用&#xff09;_redis安装_明金同学的博客-CSDN博客 出现上面代表安装成功了 redis 一共有 16 个库 安装后 再安装图形化界面 图形界面十分方便…

Java————网络编程

一 、网络编程基础 1. 为什么需要网络编程 用户在浏览器中&#xff0c;打开在线视频网站&#xff0c; 如优酷看视频&#xff0c;实质是通过网络&#xff0c; 获取到网络上的一个视频资源。 与本地打开视频文件类似&#xff0c;只是视频文件这个资源的来源是网络。 相比本地资…

ubuntu20.04部署ntp服务器ntpd(ntpdate )

文章目录 步骤1. 安装NTP2. 配置NTP3. 重启NTP服务4. 检查NTP服务状态5. 验证NTP同步ntpq -p检查本地ntp服务是否正常服务器不能连外网&#xff0c;如何配置&#xff1f; ntpdate -q xxx查询ntp服务器时间 步骤 1. 安装NTP 首先&#xff0c;在终端中更新你的包列表&#xff0…

vue项目 H5 动态设置浏览器标题

1&#xff0c;先将要展示的标题存本地 if (that.PromotionInfo.Title) {localStorage.setItem("AcTitle", that.PromotionInfo.Title)} 2,现在路由meta中设置标题&#xff0c;再在路由守卫中设置 import Vue from vue import Router from vue-router import prom…

游戏录屏软件推荐,教你录制高清游戏视频

“有没有好用的游戏录屏软件推荐呀&#xff0c;最近当上了游戏主播&#xff0c;平台要求每天都要发一个游戏视频&#xff0c;可是我的游戏录屏软件太拉胯了&#xff0c;录制出来的视频非常糊&#xff0c;导致平台审核不通过&#xff0c;所以想问问大家有没有游戏录屏软件推荐一…