直线度检测

#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>
using namespace std;
using namespace cv;
float LineFitLeastSquares(vector<float> &data_x, vector<float >&data_y, int data_n);
void pretreatment(Mat &src, vector<vector<float>>&alldata_x, vector<vector<float>>&alldata_y, int n);
void Coordinatetransformation(vector<vector<float>>&alldata_x, vector<vector<float>>& alldata_y, vector<float >& data_x, vector<float >&data_y);

string loc = "F:/研究生/标准件检测项目/标准帮2/7.png";
string save_loc = "F:/研究生/标准件检测项目/标准帮2/pre7.png";
int main()
{

	//要绝对路径
	string path = "F:\\研究生\\标准件检测项目\\标准帮\\*.png";
	//cout << path << endl;
	vector<Mat> images;
	// 必须cv的String
	vector<String> fn;
	glob(path, fn, false);
	size_t count = fn.size();
	vector<vector<float>> alldata_x(count);
	vector<vector<float>> alldata_y(count);
	//----------------------------------------------------导图预处理--------------------------------------------------------
	for (int i = 0; i < count; i++)
	{
		Mat src = imread(fn[i],CV_8UC1);
		images.push_back(src);
		int n = i;
		alldata_x[n].resize(0);
		alldata_y[n].resize(0);
		pretreatment(src, alldata_x, alldata_y,n);
		cout << "第"<< fn[i] <<"张图处理完毕" << endl;
	}

	cout << "图片数量"<<alldata_x.size()<<endl;
	//---------------------------------------------------------整合坐标数据---------------------------------------------------------------
	int sz = alldata_x.size()*alldata_x[0].size();
	
	vector<float >data_x(sz), data_y(sz);
	cout << "数据长度"<<data_x.size()<<endl;
	Coordinatetransformation(alldata_x, alldata_y,data_x, data_y);
	cout << "排序完毕" << endl;
	//---------------------------------------------------计算直线度-----------------------------------------------
	
	//if (data_x.size() == data_y.size())
	//{
		int data_n = data_x.size();
		float max_min_gap = LineFitLeastSquares(data_x, data_y, data_n);
		cout << "直线度误差为\t" << max_min_gap * 5.411 << "微米" << endl;
	//}
	cout << "处理完毕" << endl;
	system("pause");
	waitKey();
	return 0;
}



//预处理
void pretreatment(Mat &src, vector<vector<float>>&alldata_x, vector<vector<float>>&alldata_y,int n)
{
		
	Mat bisrc, morsrc, blursrc;
	//src = imread(loc, CV_8UC1);

	Point2f center(src.rows / 2, src.cols / 2);
	double theta = -1.93669905;
	double scal = 1;
	Mat M2 = getRotationMatrix2D(center, theta, scal);
	warpAffine(src, src, M2, Size(6000, 4000));//在对像素数要求精度很高的情况下,旋转变换之后图像的Size应该扩大,否则图像缩小了,像素数减少!
	
	
	Mat roi(src, Range(600, 2700), Range(150, 5400));

	bilateralFilter(roi, blursrc, 0, 100, 5, 4);

	threshold(blursrc, bisrc, 125, 255, THRESH_BINARY_INV);
	//imshow("二值", bisrc);
	//normalize(bisrc, bisrc, 0, 1, NORM_MINMAX);
	//形态学操作消除白点,黑点;
	Mat kernel=getStructuringElement(MORPH_RECT,Size(13,13));
	//morphologyEx(bisrc, morsrc, MORPH_CLOSE, kernel);//先膨胀后腐蚀的过程称为闭运算。用来填充物体内细小空洞、连接邻近物体、平滑其边界的同时并不明显改变其面积。
	morphologyEx(bisrc, morsrc, MORPH_OPEN, kernel);//先腐蚀后膨胀的过程称为开运算。用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。
	//namedWindow("形态学", WINDOW_KEEPRATIO);
	//imshow("形态学", morsrc);


	//--------------------------------------------------保存图片-----------------------------------------------------------------
	//imwrite(save_loc, morsrc);
	
	/*Mat bisrc;
	img= imread("F:/研究生/标准件检测项目/标准帮/pre1.png",CV_8UC1);*/
	Mat sub_canny_output;
	vector<vector<Point>> contours;
	vector<Vec4i> hi;//hierarchy都包含4个整型数据,分别表示:后一个轮廓的序号、前一个轮廓的序号、子轮廓的序号、父轮廓的序号

	//canny 轮廓提取
	Canny(morsrc, sub_canny_output, 80, 160);
	findContours(sub_canny_output, contours, hi, RETR_LIST, CHAIN_APPROX_NONE, Point(0, 0));
	cout << "下轮廓长度" << contours[0].size() << '\t' << "上轮廓长度" << contours[1].size() << endl;
	//sort(contours[0].begin(),contours[0].end());
	//sort(contours[1].begin(), contours[1].end());
	for (int i = 0; i < contours[1].size();i++) {
		contours[1][i].y+= 1;
		//cout<<"点"<<contours[1][i]<<'\t'<<"下点"<<contours[0][i]<<endl;
	}
	
//轮廓排序
	int num_elems = 0.5*contours[0].size();
	alldata_x[n].resize(num_elems);
	alldata_y[n].resize(num_elems);
	cout << "alldata_x长度" << alldata_x[n].size() << '\t' << "alldata_y长度" << alldata_y[n].size() << endl;
	//vector<float >data_x(num_elems), data_y(num_elems);//!!!!!!!!!!!!!!!!!
	vector<int >updata_x(num_elems), updata_y(num_elems);
	vector<int >bedata_x(num_elems), bedata_y(num_elems);
	for (int i = 0; i < num_elems; i ++) {
		for (int j = 0; j < contours[0].size();j++) {
			if (contours[0][j].x == i)
			{
				updata_x[i] = contours[0][j].x;
				updata_y[i] = contours[0][j].y;
				break;
			}
		}
	//cout << "下第一个点x"<<updata_x[i]<<'\t'<<"上第一个点y"<<updata_y[i]<<endl;
	}
	cout << "上第一个点x" << updata_x[50] << '\t' << "上第一个点y" << updata_y[50] << endl;
	for (int i = 0; i < num_elems; i++) {
		for (int j = 0; j < contours[1].size(); j++) {
			if (contours[1][j].x == i)
			{
				bedata_x[i] = contours[1][j].x;
				bedata_y[i] = contours[1][j].y;
				break;
			}
		}
	//cout << "下第一个点x" << bedata_x[i] <<'\t'<< "上第一个点y" << bedata_y[i] << endl;
	}
	cout << "下第一个点x" << bedata_x[50] << '\t' << "下第一个点y" << bedata_y[50] << endl;
	//建立两个数组
	for (size_t p = 0; p < num_elems; p++)
	{
		alldata_x[n][p] = (0.5*(bedata_x[p] + updata_x[p]));
		alldata_y[n][p] = (0.5*(bedata_y[p] + updata_y[p]));
		
		if (p==50) {
			cout << "第" << 50 + 1 << "个点的x坐标为" << alldata_x[n][50] << endl;
			cout << "第" << 50 + 1 << "个点的y坐标为" << alldata_y[n][50] << endl;
		}
	}
	
}


//坐标变换 
void Coordinatetransformation(vector<vector<float>>&alldata_x, vector<vector<float>>&alldata_y, vector<float> &data_x, vector<float> &data_y)
{

	for (int i = 0; i < alldata_x.size(); i++) {
		if (i == 0)
		{
			for (int n = 0; n < alldata_x[0].size(); n++)
				data_x[n]=(alldata_x[0][n]);
		}
		else {
			int startloc = i * alldata_x[0].size();
			float end_x = alldata_x[i - 1].back();
			for (int j = 0; j < alldata_x[i].size(); j++)
			{
				alldata_x[i][j] =  end_x+ alldata_x[i][j];
				data_x[startloc+j]=(alldata_x[i][j]);
			}
		}
	}
	cout << "x坐标排序完毕" << endl;
	for (int i = 0; i < alldata_y.size(); i++) {
		if (i == 0)
		{
			for (int n = 0; n < alldata_y[0].size(); n++)
				data_y[n]=(alldata_y[0][n]);
		}
		else {
			int startloc = i * alldata_y[0].size();
			float begin_y = alldata_y[i].front();
			float end_y = alldata_y[i - 1].back();
			for (int j = 0; j < alldata_y[i].size(); j++)
			{
				alldata_y[i][j]=end_y  + alldata_y[i][j] - begin_y;
				data_y[startloc+j]=(alldata_y[i][j]);
			}
		}
	}

	cout << "y坐标排序完毕" << endl;
}

//最小二乘法确定直线度误差
float LineFitLeastSquares(vector<float> &data_x, vector<float >&data_y, int data_n)//分别代表x数组,y数组(两数组顺序确定)以及点的数量
{
	float A = 0.0;//x平方累加和
	float B = 0.0;//x累加和
	float C = 0.0;//xy累加和
	float D = 0.0;//y累加和
	//float E = 0.0;
	//float F = 0.0;

	for (int i = 0; i < data_n; i++)
	{
		A += data_x[i] * data_x[i];
		B += data_x[i];
		C += data_x[i] * data_y[i];
		D += data_y[i];
	}

	// 计算斜率a和截距b  
	float a, b, temp = 0;
	if (temp = (data_n*A - B * B))// 判断分母不为0  
	{
		a = (data_n*C - B * D) / temp;
		b = (A*D - B * C) / temp;
	}
	else
	{
		a = 1;
		b = 0;
	}
	//计算点到直线的距离,将距离值存入一个向量中
	vector<float> gaps(data_n);//!!!!!!!!!!!!!!!!!!
	vector<float> y(data_n);//!!!!!!!!!!!!!!!!!
	for (int i = 0; i < data_n; i++) {
		y[i] = a * data_x[i] + b;
		gaps[i] = data_y[i] - y[i];
	}

	//选出向量中最大最小值,做差取决对值返回
	float max_gap = *max_element(gaps.begin(), gaps.end());//!!!!!!!!!!!!!!
	float min_gap = *min_element(gaps.begin(), gaps.end());//!!!!!!!!!!!!!!!!!
	float max_min_gap = abs(max_gap) + abs(min_gap);
	return max_min_gap;

}
### 回答1: Halcon是一款强大的机器视觉软件,它提供了丰富的工具和功能来实现各种视觉检测任务。Halcon支持直线度检测,是指检测指定区域内的直线是否符合一定的直线度标准,以确定直线的质量。 在Halcon中,可以使用直线度检测工具来检测直线度。该工具基于数学算法,在给定的直线上进行采样并计算直线的偏差,以确定直线的质量。用户可以设置检测区域、采样点数、直线度标准等参数,以满足不同的检测需求。 Halcon的直线度检测功能可以用于检测各种工件的直线度,如机械零件、板材、玻璃等。根据检测结果,可以判断工件的质量是否合格,并进行后续处理,如分类、计数、分拣等。 总之,Halcon的直线度检测功能为工业生产提供了一种高效、精确的检测方法,有助于提高生产效率和产品品质。 ### 回答2: Halcon直线度检测是一种基于人工智能技术的图像处理方法,适用于对工业产品的直线度进行检测。该方法通过选择图像中的直线特征并精确测量,可以快速、准确地得出直线度的数值,并自动判断产品是否符合质量标准。 Halcon直线度检测系统主要分为两个部分:图像预处理和直线度测量。首先,将待测产品的图像进行拍摄并预处理,消除影响因素如噪点等,提取出产品中的直线特征。然后,使用图像处理算法计算直线度,并根据预设的标准进行判断,生成检测结果。从而实现对产品直线度的快速、准确测量。 Halcon直线度检测系统具有以下优点:首先,它可以高效地进行工业生产线中的自动化检测,比传统的人工检测更为准确。其次,Halcon直线度检测可以减少生产中的浪费,通过提前检测出存在线度问题的产品,以便在后续生产过程中及时进行调整。最后,它协助厂商从技术层面提升产品质量、提高客户满意度,形成从量到质的转变。 在实际应用中,Halcon直线度检测可以应用于很多领域,例如汽车、电子、医疗设备等制造行业中。它减少了传统的人工检测时间,提高了检测的准确性和效率,并且能够及时发现问题,降低了生产成本,更好地满足现代化工业在自动化检测方面的需求。 ### 回答3: Halcon直线度检测是一种基于数字图像处理技术的在线测量方法,用于评估产品的直线度。该方法基于边缘检测和曲线拟合算法,能够自动检测和量化物体表面的直线度。 在进行Halcon直线度检测时,首先需要将物体的图像获取并进行预处理,包括灰度化、平滑滤波和边缘检测等操作。然后利用Halcon中的曲线拟合方法,对检测到的边缘进行拟合,从而得到物体表面的直线。 通过Halcon直线度检测,可以快速、准确地评估物体表面的直线度,并得到线性偏差、线性误差等量化指标,为产品制造和质控提供了强有力的支持。同时,该技术也具有灵活性和可重复性等特点,能够适用于不同材料和尺寸的物体检测。 总的来说,Halcon直线度检测是一种基于数字图像处理技术的高效、准确的在线测量方法,适用于产品直线度评估和质量控制等领域。随着数字图像处理技术的不断发展和完善,该方法也将得到进一步的应用和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值