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

news/2024/7/7 18:34:15

原图 

 

//对输入图像进行细化
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://lihuaxi.xjx100.cn/news/1571470.html

相关文章

【操作系统】24王道考研笔记——第五章 IO管理

第五章 IO管理 一、IO设备 1.1 基本概念与分类 1.2 IO控制器 电子部件 IO控制器组成 值得注意的小细节&#xff1a;①一个I/O控制器可能会对应多个设备&#xff1b; ②数据寄存器、控制寄存器、状态寄存器可能有多个&#xff08;如&#xff1a;每个控制/状态寄存器对应一个…

Elasticsearch:与多个 PDF 聊天 | LangChain Python 应用教程(免费 LLMs 和嵌入)

在本博客中&#xff0c;你将学习创建一个 LangChain 应用程序&#xff0c;以使用 ChatGPT API 和 Huggingface 语言模型与多个 PDF 文件聊天。 如上所示&#xff0c;我们在最最左边摄入 PDF 文件&#xff0c;并它们连成一起&#xff0c;并分为不同的 chunks。我们可以通过使用 …

https跳过SSL认证时是不是就是不加密的,相当于http?

https跳过SSL认证时是不是就是不加密的,相当于http?&#xff0c;其实不是&#xff0c;HTTPS跳过SSL认证并不相当于HTTP&#xff0c;也不意味着没有加密。请注意以下几点&#xff1a; HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;本质上是在HTTP的基础上…

计算机是怎么跑起来的(2)?程序如何驱动硬件工作的?

上文计算机是怎么跑起来的?从零开始手动组装微型计算机我们说了&#xff0c;如何手动从来组装一台计算机&#xff0c;那组装完后的计算机上是怎么跑起来程序的呢&#xff1f;程序是如何驱动硬件工作的&#xff1f; 前面我们通过DMA将代码输入到内存的指定位置&#xff0c;然后…

Idea 样式及注释配置

一、设置类的注释模板 /*** Description* Author lxx* Date: ${DATE} ${TIME}* Mender:*/ 1、选择File→Settings→Editor→File and Code Templates→Files→Class。 2、File Header里就是创建类时的注释模板&#xff0c;下面Description中有描述一些可以配置的参数&#xf…

基于KubeFATE的FATE-LLM任务实战

随着大型语言模型的不断蓬勃发展&#xff0c;相关新模型&#xff0c;新应用和新范式也在不断涌现&#xff0c;自 4 月发布以来&#xff0c;FATE-LLM 已经迭代发布了多个版本&#xff0c;不断完善大语言模型在联邦学习场景下的支持&#xff0c;以解决构建、使用大模型时的数据隐…

关于FreeRDP访问设备需要权限问题

FreeRDP访问设备需要权限问题&#xff0c;可能和libusb报错LIBUSB_ERROR_ACCESS libusb_open -3有关。 1.临时的方法 sudo chmod -R 777 /dev/bus/usb2.永久方法 在上面临时方法的基础上&#xff0c;再执行下面操作 sudo vim /etc/udev/rules.d/90-myusb.rules 在打开的文件…

网络安全CTF比赛有哪些事?——《CTF那些事儿》告诉你

目录 前言 一、内容简介 二、读者对象 三、专家推荐 四、全书目录 前言 CTF比赛是快速提升网络安全实战技能的重要途径&#xff0c;已成为各个行业选拔网络安全人才的通用方法。但是&#xff0c;本书作者在从事CTF培训的过程中&#xff0c;发现存在几个突出的问题&#xff1…