通过霍夫直线检测方式获取直线,自定义提取直线(提取出两条接近平行的直线),将直线进行拟合

由于项目的需要,需要使用霍夫直线检测进行处理图像。这里进行笔记记录,话不多说,先上代码:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("result1.png");
	Mat gray, canny, binaryImage;
	cvtColor(img, gray, CV_RGB2GRAY);

	threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
	imshow("binaryImage", binaryImage);

	Canny(binaryImage, canny, 50, 120);

	vector<Vec4i> lines;
	HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);

	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			//将满足条件的点画出
			line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
			cout << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
			//line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
		}
	}
	imshow("img2", img);
	imwrite("shuchu.png", img);
	waitKey(0);
	return 0;
}

上面的代码并没有进行什么滤波与二值化处理,是最简单的一种方式。

霍夫直线检测函数的使用

首先是对霍夫直线检测代码之中HoughLinesP函数进行解释:

void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )

第一个参数:InputArray image,表示输入的图像。

第二个参数:OutputArray lines,表示输出的量,其中包含有相应的输出的直线的坐标。

第三个参数:double rho, 以像素为单位的距离精度。

第四个参数:double theta,以弧度为单位的角度精度。


一般前四个参数是不用管的,主要是看后面的三个参数。

第五个参数:int threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。 大于阈值 threshold 的线段才可以被检测通过并返回到结果中。

第六个参数: double minLineLength,存在默认值0,表示可以显示的最低线段长度。

第七个参数:double maxLineGap,有默认值0,允许将同一行点与点之间连接起来的最大的距离。

这里每个参数的含义可以详见博客如下所示:

HoughLinesP参数设置(看完还不会你砍死我!!!)_无情的搬砖机器的博客-CSDN博客_houghlinesp一、我是个标题1、随便在PPt画个图如下(1602*750):2、测试代码#include<iostream>#include<opencv2/opencv.hpp>using namespace std;using namespace cv;int detect(cv::Mat img) {cv::Mat can_img, gray_img;cv::cvtColor(img, gray_img, CV_BGR2GRAY);cv::Mat ..https://blog.csdn.net/Li_haiyu/article/details/106397532?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166746636316800182746543%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166746636316800182746543&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-106397532-null-null.142%5Ev62%5Econtrol,201%5Ev3%5Eadd_ask,213%5Ev1%5Econtrol&utm_term=HoughLinesP&spm=1018.2226.3001.4187

自定义方式进行线段提取

网上只是给出了如何进行霍夫直线的提取,但是具体信息的提取过程,网上并没有,所以由于项目的需要,想了以下的方式可以进行对于可用信息的提取。

使用的图片是已经截取好的,因为实际的项目之中,背景的干扰是非常小的。由于此处进行的是模拟实验,我想到的办法只有是在不进行原有的像素改变的过程之中,对于图片内容的截取。具体的截取过程见我的另一篇博客:基于OpenCV使用鼠标在图片之中提取自己想要的信息进行显示_YllasdW的博客-CSDN博客基于OpenCV使用鼠标在图片之中圈出自己想要的信息进行显示https://blog.csdn.net/m0_47489229/article/details/126959813

上面写的代码的运行结果如下所示:

但是我需要进行提取的是在直板两端平行的线,由上面结果可知实际图像之中是存在五条线,那么这里如何进行提取两端的线呢?

我这个地方也是仔细想了一想,但是也是非常的简单,我的思路如下所示:
①两个直线之间的间距问题,既然是存在三条直线,提取两端的直线,那两端的直线的间距必然是相对而言比较大的。
②起始点和终止点之间的距离,这个地方只能是作为第二个条件存在,在判断出第一个条件之后,提取两边最长的线段(当然这个思路不是特别好,但是我这里想着这样其实也是可以的)。
③提取两边直线的斜率最为相近的两条直线(相比于条件②,这个更加靠谱一点)

代码思路,上面几个条件使用过程,我采用使用思路①和思路③进行结合的方式,所需要使用的信息是在输出结果之中,输出点之中起始点和终止点就是可以的。

在正式进行的过程,发现存在一个问题,就是思路①之中,直线可能并不是平行线,那么如何进行评价呢?所以对于思路①不如选定自己直线上面的同一纵坐标对应的横坐标进行比对,选取第一组的横坐标作为标准,依次进行相减,得到的数值取一个平均值,当数值大于这个数是一组,小于又是另外一组,进而可以分为左右两组直线。(发现自己好机智😀)

(由于我要提取的是4096*2160像素的图片,因此要恢复信息)见到上面的图片是没有问题的,但是当我恢复到原始的图像的大小的时候,发现是存在干扰问题的。

因此,图片进行提取的时候特别注意平行线的提取,一定要提取满足符合要求的地方,其余地方进行选取的时候,不要提取干扰的地方。

上面的数据就是很正常了。但是在写上述实现功能①代码时候,出现

这种情况也是需要进行考虑.

代码修改成为如下所示:


#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("result1.png");

	//设定图片的大小
	resize(img, img, Size(4096, 2160));
	Mat gray, canny, binaryImage;
	cvtColor(img, gray, CV_RGB2GRAY);

	threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
	imshow("binaryImage", binaryImage);

	Canny(binaryImage, canny, 50, 120);

	vector<Vec4i> lines;
	HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);

	
	int q1 = 0; //垂直直线
	int q = 0; //不是垂直直线的条数
	double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
	//这里设定当y相同的时候求取x的值,y设定为2160/2
	double X[20];
	double avX = 0;//x的平均值

	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			//将满足条件的点画出
			line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255 ), 2);
			cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;

			

			if (x1 != x2)
			{
				//求取直线
				k[i] = (double)((y1 - y2) / (x1 - x2));
				b[i] = (double)(y1 - k[i] * x1);

				X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
				avX = avX + X[i];
				cout << "k[i]:" << k[i] << "  " << "b[i]:" << b[i] << "  X[i]:" << b[i] << "  avX:" << avX << endl;

				q++;

			}
			else {
				X[i] = x1;
				avX = avX + X[i];

				q1++;
			}
			
		}
	}
	cout << "直线的条数:" << q +q1 <<endl;

	avX = (double)(avX / (double)(q + q1));

	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			if (X[i] > avX)
			{
				cout << "右侧直线:" << i << endl;
			}
			else
			{
				cout << "左侧直线:" << i << endl;
			}
		}
		
	}




	imshow("img2", img);
	imwrite("shuchu.png", img);
	waitKey(0);
	return 0;
}

运行结果如下所示:

可见线条2是竖直的直线,并且这里的直线分成了左右两个部分,接下来就是提取出左右斜率最为相近的两条直线.


#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("result1.png");

	//设定图片的大小
	resize(img, img, Size(4096, 2160));
	Mat gray, canny, binaryImage;
	cvtColor(img, gray, CV_RGB2GRAY);

	threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
	imshow("binaryImage", binaryImage);

	Canny(binaryImage, canny, 50, 120);

	vector<Vec4i> lines;
	HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);

	
	int q1 = 0; //垂直直线
	int q = 0; //不是垂直直线的条数
	double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
	//这里设定当y相同的时候求取x的值,y设定为2160/2
	double X[20];
	double avX = 0;//x的平均值

	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			//将满足条件的点画出
			line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255 ), 2);
			cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;

			

			if (x1 != x2)
			{
				//求取直线
				k[i] = (double)((y1 - y2) / (x1 - x2));
				b[i] = (double)(y1 - k[i] * x1);

				X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
				avX = avX + X[i];
				cout << "k[i]:" << k[i] << "  " << "b[i]:" << b[i] << "  X[i]:" << b[i] << "  avX:" << avX << endl;

				q++;

			}
			else {
				X[i] = x1;
				avX = avX + X[i];

				q1++;
			}
			
		}
	}

	imshow("img2", img);
	imwrite("shuchu.png", img);

	cout << "直线的条数:" << q +q1 <<endl;

	avX = (double)(avX / (double)(q + q1));

	double min = 0;//标记最小值---斜率差值
	int i1, i2;//左右直线
	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			if (X[i] > avX)
			{
				cout << "右侧直线:" << i << endl;

				double e = k[i];//抽取右侧直线的斜率
				int i3 = i;//记录此时的右侧直线的i值

				for (size_t i = 0; i < lines.size(); i++)
				{
					Vec4i I = lines[i];
					double x1 = I[0];
					double y1 = I[1];
					double x2 = I[2];
					double y2 = I[3];
					//筛选满足条件的点
					if (abs(x1 - x2) + abs(y1 - y2) > 50)
					{
						if (X[i] <= avX)//左侧直线操作
						{
							if (min < abs(k[i] - e))
							{
								min = abs(k[i] - e);
								i2 = i;
								i1 = i3;
							}
						}
					}
				}



			}
			else
			{
				cout << "左侧直线:" << i << endl;
			}
		}
		
	}
	cout << "两条最为相近的直线:  " << "左边直线:" << i2 << "  右边直线:" << i1 << endl;


	waitKey(0);
	return 0;
}

运行结果:

注意:上面提取出来的两条直线不是两个都是垂直的,如果要是有垂直的情况需要再想(后面再想) 

并且注意上面标出的地方两条直线,代码如下所示:


#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("result1.png");
	Mat img1 = img;
	//设定图片的大小
	resize(img, img, Size(4096, 2160));
	Mat gray, canny, binaryImage;
	cvtColor(img, gray, CV_RGB2GRAY);

	threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
	imshow("binaryImage", binaryImage);

	Canny(binaryImage, canny, 50, 120);

	vector<Vec4i> lines;
	HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);

	
	int q1 = 0; //垂直直线
	int q = 0; //不是垂直直线的条数
	double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
	//这里设定当y相同的时候求取x的值,y设定为2160/2
	double X[20];
	double avX = 0;//x的平均值

	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			//将满足条件的点画出
			line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255 ), 2);
			cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;

			

			if (x1 != x2)
			{
				//求取直线
				k[i] = (double)((y1 - y2) / (x1 - x2));
				b[i] = (double)(y1 - k[i] * x1);

				X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
				avX = avX + X[i];
				cout << "k[i]:" << k[i] << "  " << "b[i]:" << b[i] << "  X[i]:" << b[i] << "  avX:" << avX << endl;

				q++;

			}
			else {
				X[i] = x1;
				avX = avX + X[i];

				q1++;
			}
			
		}
	}

	imshow("img2", img);
	imwrite("shuchu.png", img);

	cout << "直线的条数:" << q +q1 <<endl;

	avX = (double)(avX / (double)(q + q1));

	double min = 0;//标记最小值---斜率差值
	int i1, i2;//左右直线
	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			if (X[i] > avX && (x1-x2 !=0 ))
			{
				cout << "右侧直线:" << i << endl;

				double e = k[i];//抽取右侧直线的斜率
				int i3 = i;//记录此时的右侧直线的i值

				for (size_t i = 0; i < lines.size(); i++)
				{
					Vec4i I = lines[i];
					double x1 = I[0];
					double y1 = I[1];
					double x2 = I[2];
					double y2 = I[3];
					//筛选满足条件的点
					if (abs(x1 - x2) + abs(y1 - y2) > 50 )
					{
						if (X[i] <= avX && (x1 - x2 != 0))//左侧直线操作
						{
							if (min < abs(k[i] - e))
							{
								min = abs(k[i] - e);
								i2 = i;
								i1 = i3;
							}
						}
					}
				}
			}
			else
			{
				cout << "左侧直线:" << i << endl;
			}
		}
		
	}
	cout << "两条最为相近的直线:  " << "左边直线:" << i2 << "  右边直线:" << i1 << endl;

	/*
	int x31 = 0,x32 = 4096,x41 = 0,x42 = 4096 ;
	int y31, y32, y41, y42;
	y31 = k[i2] * x31 + b[i2];
	y32 = k[i2] * x32 + b[i2];
	y41 = k[i1] * x41 + b[i1];
	y42 = k[i1] * x42 + b[i1];
	*/
	resize(img1, img1, Size(4096, 2160));
		Vec4i I = lines[i2];
		double x31 = I[0];
		double y31 = I[1];
		double x32 = I[2];
		double y32 = I[3];
		line(img1, Point2d(x31, y31), Point2d(x32, y32), Scalar(0, 255, 255), 2);
		line(img1, Point2d(1706, 999), Point2d(1725, 1354), Scalar(0, 255, 255), 2);
		line(img1, Point2d(1767, 479), Point2d(1781, 693), Scalar(0, 255, 255), 2);
		 I = lines[i1];
		double x41 = I[0];
		double y41 = I[1];
		double x42 = I[2];
		double y42 = I[3];

	line(img1, Point2d(x41, y41), Point2d(x42, y42), Scalar(0, 255, 255), 2);


	
	imshow("img3", img1);
	imwrite("shuchu3.png", img1);
	waitKey(0);
	return 0;
}

输出结果:

进而得到最为相似的平行的两条直线.

接下来就是将上述的直线进行拟合成为一条直线.


#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("result1.png");
	Mat img1 = img;
	//设定图片的大小
	resize(img, img, Size(4096, 2160));
	Mat gray, canny, binaryImage;
	cvtColor(img, gray, CV_RGB2GRAY);

	threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
	imshow("binaryImage", binaryImage);

	Canny(binaryImage, canny, 50, 120);

	vector<Vec4i> lines;
	HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);

	
	int q1 = 0; //垂直直线
	int q = 0; //不是垂直直线的条数
	double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
	//这里设定当y相同的时候求取x的值,y设定为2160/2
	double X[20];
	double avX = 0;//x的平均值

	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			//将满足条件的点画出
			line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255 ), 2);
			cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;

			

			if (x1 != x2)
			{
				//求取直线
				k[i] = (double)((y1 - y2) / (x1 - x2));
				b[i] = (double)(y1 - k[i] * x1);

				X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
				avX = avX + X[i];
				cout << "k[i]:" << k[i] << "  " << "b[i]:" << b[i] << "  X[i]:" << b[i] << "  avX:" << avX << endl;

				q++;

			}
			else {
				X[i] = x1;
				avX = avX + X[i];

				q1++;
			}
			
		}
	}

	imshow("img2", img);
	imwrite("shuchu.png", img);

	cout << "直线的条数:" << q +q1 <<endl;

	avX = (double)(avX / (double)(q + q1));

	double min = 0;//标记最小值---斜率差值
	int i1, i2;//左右直线
	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			if (X[i] > avX && (x1-x2 !=0 ))
			{
				cout << "右侧直线:" << i << endl;

				double e = k[i];//抽取右侧直线的斜率
				int i3 = i;//记录此时的右侧直线的i值

				for (size_t i = 0; i < lines.size(); i++)
				{
					Vec4i I = lines[i];
					double x1 = I[0];
					double y1 = I[1];
					double x2 = I[2];
					double y2 = I[3];
					//筛选满足条件的点
					if (abs(x1 - x2) + abs(y1 - y2) > 50 )
					{
						if (X[i] <= avX && (x1 - x2 != 0))//左侧直线操作
						{
							if (min < abs(k[i] - e))
							{
								min = abs(k[i] - e);
								i2 = i;
								i1 = i3;
							}
						}
					}
				}
			}
			else
			{
				cout << "左侧直线:" << i << endl;
			}
		}
		
	}
	cout << "两条最为相近的直线:  " << "左边直线:" << i2 << "  右边直线:" << i1 << endl;

	/*
	int x31 = 0,x32 = 4096,x41 = 0,x42 = 4096 ;
	int y31, y32, y41, y42;
	y31 = k[i2] * x31 + b[i2];
	y32 = k[i2] * x32 + b[i2];
	y41 = k[i1] * x41 + b[i1];
	y42 = k[i1] * x42 + b[i1];
	*/
	resize(img1, img1, Size(4096, 2160));
		Vec4i I = lines[i2];
		double x31 = I[0];
		double y31 = I[1];
		double x32 = I[2];
		double y32 = I[3];
		line(img1, Point2d(x31, y31), Point2d(x32, y32), Scalar(0, 255, 255), 2);
		
		 I = lines[i1];
		double x41 = I[0];
		double y41 = I[1];
		double x42 = I[2];
		double y42 = I[3];

	line(img1, Point2d(x41, y41), Point2d(x42, y42), Scalar(0, 255, 255), 2);

	//画出拟合直线
	double K = (double)(k[i2] + k[i1]) / 2.0;
	double B = (double)(b[i2] + b[i1]) / 2.0;
	double x51 = 0;
	double y51 = K * x51 + B;
	
	double x52 = 4096;
	double y52 = K * x52 + B;
	line(img1, Point2d(x51, y51), Point2d(x52, y52), Scalar(255, 0, 0), 3);
	
	
	imshow("img3", img1);
	imwrite("shuchu3.png", img1);
	waitKey(0);
	return 0;
}

输出结果:

就是这样,上述思路之中主要是进行提取两条平行线的思路需要注意,一步一步来就是非常简单的. 

最终版,但是上面的代码并不能检测到竖直直线的存在,反正最后写出来了,可麻烦了,代码不想看第二遍,代码如下所示:



#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
	Mat img = imread("左相机123.bmp");
	Mat img1 = img;
	Mat img3 = imread("左相机123.bmp");
	//设定图片的大小
	resize(img, img, Size(4096, 2160));
	Mat gray, canny, binaryImage;
	cvtColor(img, gray, CV_RGB2GRAY);

	threshold(gray, binaryImage, 150, 220, THRESH_BINARY);
	imshow("binaryImage", binaryImage);

	Canny(binaryImage, canny, 50, 120);

	vector<Vec4i> lines;
	HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);

	
	int q1 = 0; //垂直直线
	int q2 = 0;
	int qs = 0;
	bool S = false;//是否存在左右直线
	int q = 0; //不是垂直直线的条数
	double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
	//这里设定当y相同的时候求取x的值,y设定为2160/2
	double X[20];//放入的是数竖直的线
	double avX = 0;//x的平均值 __ 不包括竖直直线
	double avXS = 0;//数值直线
	double maxR = 0;//记录竖直差
	double maxL = 0;
	double xr, xl;

	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			//将满足条件的点画出
			line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
			cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;



			if (x1 != x2)
			{
				//求取直线
				k[i] = (double)((y1 - y2) / (x1 - x2));
				b[i] = (double)(y1 - k[i] * x1);

				X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
				avX = avX + X[i];
				cout << "k[i]:" << k[i] << "  " << "b[i]:" << b[i] << "  X[i]:" << b[i] << "  avX:" << avX << endl;

				q++;

			}

			else {//竖直直线
				X[i] = x1;
				avX = avX + X[i];
				avXS = avXS + X[i];
		
				qs++;

				if ((avX / qs - X[i]) > 5)/**************************************************************************************************************************************************/
				{
					S = true;
				}

				
				

			}


		}
	}
	avXS = avXS / qs;
	cout << "中间竖直直线x坐标" << avXS << endl;

	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			if(S == true && x1 == x2)//两条直线之间的距离大于5个像素
			{
				if ((maxR < abs(x1 - avXS)) && x1 >= avXS)//选出最小的右侧竖直直线
				{
					maxR = abs(x1 - avXS);
					cout << "maxR:" << maxR << endl;
					q2++;
				}
				else if (x1 >= avXS) {
					q2++;
					cout << "maxR:" << maxR << endl;
				}
				if ((maxL < abs(x1 - avXS)) && x1 <= avXS)//选出最小的右侧竖直直线
				{
					maxL = abs(x1 - avXS);
					cout << "maxL:" << maxL << endl;
					q1++;
				}
				else if (x1 <= avXS)
				{
					q1++;
					cout << "maxL:" << maxL << endl;
				}
			

			}
		}


		
	}


	
	imshow("img2", img);
	imwrite("shuchu.png", img);
	waitKey(0);

	cout << "直线的总条数:" << q + q1 + q2 <<endl;



	cout << "左侧竖直直线条数:" <<  q1 << endl;
	cout << "右侧竖直直线条数:" << q2 << endl;


	avX = (double)(avX / (double)(q + q1 + q2));
	cout << "总直线x平均坐标" << avX << endl;
	cout << "竖直直线x平均坐标" << avXS << endl;
	double min = 0;//标记最小值---斜率差值
	


	double xrpoint, xlpoint;
	int i1, i2;//左右直线
	for (size_t i = 0; i < lines.size(); i++)
	{
		Vec4i I = lines[i];
		double x1 = I[0];
		double y1 = I[1];
		double x2 = I[2];
		double y2 = I[3];
		//筛选满足条件的点
		if (abs(x1 - x2) + abs(y1 - y2) > 50)
		{
			if ((q1 > 0) && (q2 > 0) && (x1 - x2 == 0 ))//说明是存在两条竖直的直线
			{
				
				if ( (x1 >= avXS) && (maxR == abs(x1 - avXS)))//选出最大的右侧竖直直线
				{
					//划线并且记录
					line(img3, Point2d(x1, 0), Point2d(x1, 2160), Scalar(0, 255, 255), 2);
					xrpoint = x1;
					cout << "总直线x平均坐标1" << xrpoint << endl;
					cout << "划线" << endl;
				}
				if ((x1 <= avXS) && (maxL == abs(x1 - avXS)))//选出最小的左侧竖直直线
				{
					//划线并且记录
					line(img3, Point2d(x1, 0), Point2d(x1, 2160), Scalar(0, 255, 255), 2);
					xlpoint = x1;
					cout << "总直线x平均坐标2" << xlpoint << endl;
					cout << "划线" << endl;
				}
				
			}
			else if ((x1-x2 !=0 ))//右侧不是竖直直线---这个地方是之前写的,可以运行
			{
				cout << "右侧不是竖直的直线:" << i << endl;

				double e = k[i];//抽取右侧直线的斜率
				int i3 = i;//记录此时的右侧直线的i值

				for (size_t i = 0; i < lines.size(); i++)
				{
					Vec4i I = lines[i];
					double x1 = I[0];
					double y1 = I[1];
					double x2 = I[2];
					double y2 = I[3];
					//筛选满足条件的点
					if (abs(x1 - x2) + abs(y1 - y2) > 50 )
					{
						if (X[i] <= avX && (x1 - x2 != 0))//左侧不是竖直直线操作
						{
							if (min < abs(k[i] - e))
							{
								min = abs(k[i] - e);
								i2 = i;
								i1 = i3;
								
							}
						}
					}
				}
			}
			else
			{
				cout << "左侧直线:" << i << endl;
			}
		}
		
	}

	
	/*
	int x31 = 0,x32 = 4096,x41 = 0,x42 = 4096 ;
	int y31, y32, y41, y42;
	y31 = k[i2] * x31 + b[i2];
	y32 = k[i2] * x32 + b[i2];
	y41 = k[i1] * x41 + b[i1];
	y42 = k[i1] * x42 + b[i1];
	*/
	
	if (q1 > 0 && q2 > 0)
	{
		//resize(img3, img3, Size(4096, 2160));
		line(img3, Point2d((xlpoint+ xrpoint)/2.0, 0), Point2d((xlpoint + xrpoint) / 2.0, 2160), Scalar(255, 0, 255), 2);
		cout << "存在两条竖直直线:" << "情况一:" << endl;
		imwrite("输出最终结果直线.png", img3);
		resize(img3, img3, Size(1024, 540));//显示改变大小
		imshow("img3", img3);
		waitKey(0);
	}
	
	else {
		resize(img1, img1, Size(4096, 2160));
		Vec4i I = lines[i2];
		double x31 = I[0];
		double y31 = I[1];
		double x32 = I[2];
		double y32 = I[3];
		line(img1, Point2d(x31, y31), Point2d(x32, y32), Scalar(0, 255, 255), 2);

		I = lines[i1];
		double x41 = I[0];
		double y41 = I[1];
		double x42 = I[2];
		double y42 = I[3];

		line(img1, Point2d(x41, y41), Point2d(x42, y42), Scalar(0, 255, 255), 2);

		//画出拟合直线
		double K = (double)(k[i2] + k[i1]) / 2.0;
		double B = (double)(b[i2] + b[i1]) / 2.0;
		double x51 = 0;
		double y51 = K * x51 + B;

		double x52 = 4096;
		double y52 = K * x52 + B;
		line(img1, Point2d(x51, y51), Point2d(x52, y52), Scalar(255, 0, 0), 3);
		cout << "斜率K:" << K << " B:" << B << endl;


		imwrite("shuchu3.png", img1);
		resize(img1, img1, Size(1024, 540));//显示改变大小
		imshow("img3", img1);
		waitKey(0);
	}
	
	return 0;
}

效果图:

左右两条是提取的竖直直线,中间就是自己想要的那一条直线.

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值