// 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); }
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); }
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; }