Example #1
0
// y = ax + b, x = 0, ..., Points.size()
int FitLine(const DblVector& PointsY, double& a, double& b)
{
	DblVector PointsX;
	for(unsigned int i=0; i<PointsY.size(); i++)
			PointsX.push_back((double)i);
	return FitLine(PointsY, PointsX, a, b);
}
Example #2
0
int FitLineIt(const DblVector& PointsY, const DblVector& PointsX,
			  double& a, double& b, int It, double ErrWidth)
{
	// base case
	if(It==0) return 0;
	std::cout << "Line fitting no samples: " << PointsY.size() << std::endl;

	// fitting
	FitLine(PointsY, PointsX, a, b);

	double Error = 0.0;
	for(int i=0; i<(int)PointsY.size(); i++)
	{
		double Val0 = a*PointsX[i]+b;
		double Val1 = PointsY[i]; 
		Error += dblsqr(Val1-Val0);
		//std::cout << Val1 << " " << Val0 << std::endl;
	}
	Error /= (double)PointsY.size();
	Error = sqrt(Error);

	DblVector px, py; int Cnt=0;
	for(int k=0; k<(int)PointsX.size(); k++)
	{
		double Val = a*PointsX[k]+b;
		double Dist = sqrt(dblsqr(PointsY[k] - Val));
		if(Dist<Error*ErrWidth)
		{
			px.push_back(PointsX[k]);
			py.push_back(PointsY[k]);
			Cnt++;
		}
	}
	return FitLineIt(py, px, a, b, It-1, ErrWidth);
}
Example #3
0
void EdgeDetector::start()
{
	/*double t2 = (double)cv::getTickCount();

	double t = (double)cv::getTickCount();*/
	// 预处理
	for (int i = 0; i < ROI.size(); i++)
	{
		Dynamic_range(ROI[i]);
	}
	/*t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
	cout << "预处理time=" << t << "\t";

	t = (double)cv::getTickCount();*/
	// 获取边缘
	vector<vector<Point>> Contours;// 原图的边缘坐标
	vector<vector<Point>> ROI_Contours; // ROI上的边缘坐标
	Find_contours(ROI, Contours, ROI_Contours); // 找到的边缘对应于原图和ROI分别保存




	// 取边缘样点用于拟合
	vector<vector<Point>> Fit_contours; // 存储样点用于拟合

	for (int i = 0; i < ROI_Contours.size(); i++)
	{
		vector<Point> tm;
		for (int j = 50; j < ROI_Contours[i].size() - 50; j = j + 50) // 每隔50个点取一个
		{
			tm.push_back(ROI_Contours[i][j]);
		}
		Fit_contours.push_back(tm);
	}
	/*t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
	cout << "取边缘样点用于拟合time=" << t << "\t";


	t = (double)cv::getTickCount();*/
	// 边缘直线拟合
	vector<Vec4f> line_;   // 拟合后原图上的直线
	vector<Vec4f> line_roi; // 拟合后roi上的直线
	Vec4f Fit_Line;
	FitLine(Fit_contours, line_, line_roi, Fit_Line);	 // 直线拟合

	/*t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
	cout << "边缘直线拟合time=" << t << "\t";

	t = (double)cv::getTickCount();*/
	// 求出四个交点A\B\C\D
	vector<Point> Point_of_Intersection;
	PointOfIntersection(line_, Point_of_Intersection);
	block->A = Point_of_Intersection[3];
	block->B = Point_of_Intersection[2];
	block->C = Point_of_Intersection[1];
	block->D = Point_of_Intersection[0];

	vector<Point> corner;
	corner.push_back(block->A);
	corner.push_back(block->D);
	corner.push_back(block->C);
	corner.push_back(block->B);

	/*t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
	cout << "求出四个交点time=" << t << "\t";*/

	//Mat image1(src.size(), CV_8UC3, Scalar(0));
	//for (int i = 0; i < Contours.size(); i++)
	//{
	//	int a, b, c;
	//	switch (i)
	//	{
	//	case 0: a = 255; b = 0; c = 0; break;
	//	case 1: a = 0; b = 255; c = 0; break;
	//	case 2: a = 0; b = 0; c = 255; break;
	//	case 3: a = 255; b = 255; c = 255; break;
	//	}
	//	for (int j = 0; j < Contours[i].size(); j++)
	//	{
	//		image1.at<Vec3b>(Contours[i][j])[0] = a;
	//		image1.at<Vec3b>(Contours[i][j])[1] = b;
	//		image1.at<Vec3b>(Contours[i][j])[2] = c;
	//	}
	//}
	//vector<Mat> ROI_3(ROI);
	//for (int i = 0; i < ROI.size(); i++)
	//{
	//	cvtColor(ROI[i], ROI_3[i], CV_GRAY2BGR);
	//}
	//for (int i = 0; i < ROI_Contours.size(); i++)
	//{
	//	int a, b, c;
	//	switch (i)
	//	{
	//	case 0: a = 255; b = 0; c = 0; break;
	//	case 1: a = 0; b = 255; c = 0; break;
	//	case 2: a = 0; b = 0; c = 255; break;
	//	case 3: a = 255; b = 255; c = 255; break;
	//	}
	//	for (int j = 0; j < ROI_Contours[i].size(); j++)
	//	{
	//		ROI_3[i].at<Vec3b>(ROI_Contours[i][j])[0] = a;
	//		ROI_3[i].at<Vec3b>(ROI_Contours[i][j])[1] = b;
	//		ROI_3[i].at<Vec3b>(ROI_Contours[i][j])[2] = c;
	//	}
	//}

	/*t = (double)cv::getTickCount();*/
	// 崩边检测
	int starter = 0, ender = 0; // 一个边缘点集合的起始点和结束点
	int aa = 0, bb = 0, cc = 0, dd = 0;
	int aa1 = 0, bb1 = 0, cc1 = 0, dd1 = 0;

	// 瓷砖向右歪斜
	if ((block->A).y > (block->B).y)
	{
		aa1 = ROI_Contours[0].size();	bb1 = ROI_Contours[1].size();	cc = 0;	dd = 0;
		for (int i = 0; i < 50; i++)
		{
			int t0 = abs(Contours[0][i].x - Contours[0][i + 1].x);
			int t1 = abs(Contours[0][i].x - (block->A).x);
			if (t1 < 30){
				aa = i;		break;
			}
			else
				if (i == 49)	aa = 49;
		}

		for (int i = 0; i < 50; i++)
		{
			int t0 = abs(Contours[1][i].y - Contours[1][i + 1].y);
			int t1 = abs(Contours[1][i].y - (block->D).y);
			if (t1 < 30){
				bb = i;	break;
			}
			else
				if (i == 49)	bb = 49;
		}

		for (int i = ROI_Contours[2].size() - 2; i > ROI_Contours[2].size() - 50; i--)
		{
			int t0 = abs(Contours[2][i].x - Contours[2][i + 1].x);
			int t1 = abs(Contours[2][i].x - (block->C).x);
			if (abs(Contours[2][i].x - (block->C).x) < 30)	{
				cc1 = i;		break;
			}
			else
				if (i == ROI_Contours[2].size() - 49)
					cc1 = ROI_Contours[2].size() - 49;
		}


		for (int i = ROI_Contours[3].size() - 2; i > ROI_Contours[3].size() - 50; i--)
		{
			int t0 = abs(Contours[3][i].y - Contours[3][i + 1].y);
			int t1 = abs(Contours[3][i].y - (block->B).y);
			if (t1 < 30){
				dd1 = i;	break;
			}
			else
				if (i == ROI_Contours[3].size() - 49)
					dd1 = ROI_Contours[3].size() - 49;
		}
	}

	else  // 瓷砖向左歪斜
	{
		aa = 0; bb = 0;	cc1 = ROI_Contours[2].size();	dd1 = ROI_Contours[3].size();
		for (int i = ROI_Contours[0].size() - 2; i > ROI_Contours[0].size() - 50; i--)
		{
			if (abs(Contours[0][i].x - (block->D).x) < 30){
				aa1 = i;		break;
			}
			else
				if (i == ROI_Contours[0].size() - 49)	aa1 = ROI_Contours[0].size() - 49;
		}

		for (int i = ROI_Contours[1].size() - 2; i > ROI_Contours[1].size() - 50; i--)
		{
			if (abs(Contours[1][i].y - (block->C).y) < 30){ bb1 = i;		break; }
			else
				if (i == ROI_Contours[1].size() - 49)	bb1 = ROI_Contours[1].size() - 49;
		}

		for (int i = 0; i <50; i++)
		{
			if (abs(Contours[2][i].x - (block->B).x) < 30)	{
				cc = i;		break;
			}
			else
				if (i == 49)
					cc = 49;
		}


		for (int i = 0; i <50; i++)
		{
			if (abs(Contours[3][i].y - (block->A).y)<30)	{
				dd = i;		break;
			}
			else
				if (i == 49)
					dd = 49;
		}
	}


	// 崩边检测
	for (int index = 0; index < ROI_Contours.size(); index++)
	{
		int xp = 0, yp = 0;
		int st = 0, et = ROI_Contours[index].size();;
		switch (index)
		{
		case 0:	st = aa;	 et = aa1;	xp = xleft;	yp = yleft;	break;
		case 1:	st = bb;	 et = bb1;	xp = xdown;	yp = ydown;	break;
		case 2:	st = cc;     et = cc1;	xp = xright;	yp = yright;	break;
		case 3:	st = dd;	 et = dd1;	xp = xup;	yp = yup;	break;
		}



		for (int i = st; i < et; i += simple)  // 间隔simple个点采样检测
		{
			int tt = ROI_Contours[index][i].x;
			int tt1 = ROI_Contours[index][i].y;
			starter = st;	ender = 0;
			int dist = DistanceDetector(ROI_Contours[index][i], line_roi[index]);
			if (dist >= distance_threld)
			{
				if (i < st + 20)
					starter = 0;
				else
					starter = i - 19;
				if (starter > ROI_Contours[index].size() - 30)
					ender = ROI_Contours[index].size() - 1;
				else
					for (int q = i + 5; q < ROI_Contours[index].size(); q += 5)
					{
						int dist = DistanceDetector(ROI_Contours[index][q], line_roi[index]);
						if (dist < distance_threld)
						{
							ender = q + 20;
							i = q + 20;
							if (i>ROI_Contours[index].size() - 7)
							{
								i = ROI_Contours[index].size() - 1;
								ender = ROI_Contours[index].size() - 1;
							}
							break;
						}
					}
				if ((ender - starter > 39 + distance_threld) || (starter == st) || (ender == ROI_Contours[index].size() - 1))
				{
					/////////////////////////////////////////////////////////////////
					//cv::circle(ROI[index], ROI_Contours[index][starter + (ender - starter) / 2], (ender - starter) / 2, Scalar(255));
					/////////////////////////////////////////////////////////////////
					int flag = 0;
					int edge_deep = 0;
					for (int a = starter; a < ender; a++)
					{
						int dist = DistanceDetector(ROI_Contours[index][a], line_roi[index]);
						if (edge_deep < dist)
							edge_deep = dist;
						if (dist >= distance_threld)
						{
							int tt = ROI_Contours[index][a].x;
							int tt1 = ROI_Contours[index][a].y;
							flag++;
						}
					}

					if (flag > Edge_threld)
					{
						flag = 0;
						// 边角判别
						Point location;
						location.x = ROI_Contours[index][starter + (ender - starter) / 2].x + xp;
						location.y = ROI_Contours[index][starter + (ender - starter) / 2].y + yp;
						int length = (ender - starter);

						int current = index;
						int next = index + 1;
						if (next == 4) next = 0;
						double corner_distance_fir = sqrt(pow((location.x - corner[index].x), 2) + pow((location.y - corner[index].y), 2)) - length / 2;
						double corner_distance_sec = sqrt(pow((location.x - corner[next].x), 2) + pow((location.y - corner[next].y), 2)) - length / 2;
						if (corner_distance_fir < 10 || corner_distance_sec < 10)
						{
							Faults::BrokenCorner bc;
							bc.position = location;
							if (current % 2)
							{
								bc.width = length;
								bc.length = edge_deep;
							}
							else
							{
								bc.length = length;
								bc.width = edge_deep;
							}
							bc.deep = bc.length*bc.width / sqrt(pow(bc.length, 2) + pow(bc.width, 2));
							if (bc.deep > 300 || bc.length > 300)
								continue;
							faults->BrokenCorners.push_back(bc);
							//cv::circle(src, Point(bc.position.x, bc.position.y), bc.length, Scalar(255, 255, 250));
							/*break;*/
							i = ender + 5;
						}
						else
						{
							Faults::BrokenEdge be;
							/*Faults fs;*/
							be.position.x = ROI_Contours[index][starter + (ender - starter) / 2].x + xp;
							be.position.y = ROI_Contours[index][starter + (ender - starter) / 2].y + yp;
							if (index % 2)
							{
								be.length = (ender - starter)/**(double)(fs.GetMilliMeterPerPix_X())*/;
								be.deep = edge_deep/**(double)(fs.GetMilliMeterPerPix_Y())*/;
							}

							else
							{
								be.length = (ender - starter)/**(double)(fs.GetMilliMeterPerPix_Y())*/;
								be.deep = edge_deep/**(double)(fs.GetMilliMeterPerPix_X())*/;
							}
							if (be.deep > 300 || be.length > 300)
								continue;
							faults->BrokenEdges.push_back(be);
							/*break;*/
							i = ender + 5;
						}
					}
				}
			}
		}
	}
	Merge_Defects(faults->BrokenEdges);
	//for (int i = 0; i < (faults->BrokenEdges).size(); i++)
	//{
	//	cv::circle(src, Point((faults->BrokenEdges)[i].position.x, (faults->BrokenEdges)[i].position.y), (faults->BrokenEdges)[i].length, Scalar(255, 255, 250));
	//}
	
	//t = ((double)cv::getTickCount() - t) / cv::getTickFrequency();
	//cout << "崩边检测time=" << t << endl;
	//cout << "start time= " << ((double)cv::getTickCount() - t2) / cv::getTickFrequency() << endl;
}