/*public*/ void LineIntersector::computeIntersection(const Coordinate& p1,const Coordinate& p2,const Coordinate& p3,const Coordinate& p4) { inputLines[0][0]=&p1; inputLines[0][1]=&p2; inputLines[1][0]=&p3; inputLines[1][1]=&p4; result=computeIntersect(p1,p2,p3,p4); //numIntersects++; }
void computeIntersectList(std::vector<cv::Vec4i>& linesH, std::vector<cv::Vec4i>& linesV, std::vector<cv::Point2f>& interPoints) { // Calculate Intersections between Horizontal and Vertical Lines interPoints.reserve(linesH.size() * linesV.size() / 10); for (size_t i = 0; i < linesH.size(); i++) { for (size_t j = 0; j < linesV.size(); j++) { cv::Point2f point = computeIntersect(linesH[i], linesV[j]); if (point != cv::Point2f(-1, -1)) interPoints.push_back(point); } } }
int find_corners(cv::Mat& contour, unsigned thresh,std::vector<cv::Point2f>& _corners){ std::vector<std::vector<cv::Point> > contours; std::vector<cv::Vec4i> hierarchy; std::vector<cv::Vec4i> lines; cv::Mat gray; cv::cvtColor( contour, gray, CV_RGB2GRAY ); cv::HoughLinesP(gray, lines, 1, CV_PI/180, thresh, 30, 10); // Преобразованием Hough находим только прямые линии. получаем вектор lines (x1,y1,x2,y2) std::vector<cv::Point2f> corners; for (int i = 0; i < lines.size(); i++){ for (int j = i+1; j < lines.size(); j++) { cv::Point2f pt = computeIntersect(lines[i], lines[j]); if (pt.x >= 0 && pt.y >= 0) corners.push_back(pt); } } std::cout << lines.size()<<" : "<<corners.size() << std::endl; for (std::vector<cv::Point2f>::const_iterator i = corners.begin();i != corners.end(); ++i){ std::cout << *i << std::endl; } std::cout << "Counting" << std::endl; aproxCorners(corners); std::cout << "New" << std::endl; for (std::vector<cv::Point2f>::const_iterator i = corners.begin();i != corners.end(); ++i){ std::cout << *i << std::endl; } cv::Point2f center(0,0); for (int i = 0; i < corners.size(); i++) center += corners[i]; center *= (1. / corners.size()); _corners.clear(); if ( sortCorners(corners, center) > -1){ _corners = corners; }else{ return -1; } return 0; }
int main() { cv::Mat src = cv::imread("assets/perspective-quadrilateral.jpg"); if (src.empty()) return -1; cv::Mat bw; cv::cvtColor(src, bw, CV_BGR2GRAY); cv::blur(bw, bw, cv::Size(3, 3)); cv::Canny(bw, bw, 100, 100, 3); std::vector<cv::Vec4i> lines; cv::HoughLinesP(bw, lines, 1, CV_PI/180, 70, 30, 10); // Expand the lines for (int i = 0; i < lines.size(); i++) { cv::Vec4i v = lines[i]; lines[i][0] = 0; lines[i][1] = ((float)v[1] - v[3]) / (v[0] - v[2]) * -v[0] + v[1]; lines[i][2] = src.cols; lines[i][3] = ((float)v[1] - v[3]) / (v[0] - v[2]) * (src.cols - v[2]) + v[3]; } std::vector<cv::Point2f> corners; for (int i = 0; i < lines.size(); i++) { for (int j = i+1; j < lines.size(); j++) { cv::Point2f pt = computeIntersect(lines[i], lines[j]); if (pt.x >= 0 && pt.y >= 0) corners.push_back(pt); } } std::vector<cv::Point2f> approx; cv::approxPolyDP(cv::Mat(corners), approx, cv::arcLength(cv::Mat(corners), true) * 0.02, true); if (approx.size() != 4) { std::cout << "The object is not quadrilateral!" << std::endl; return -1; } // Get mass center for (int i = 0; i < corners.size(); i++) center += corners[i]; center *= (1. / corners.size()); sortCorners(corners, center); cv::Mat dst = src.clone(); // Draw lines for (int i = 0; i < lines.size(); i++) { cv::Vec4i v = lines[i]; cv::line(dst, cv::Point(v[0], v[1]), cv::Point(v[2], v[3]), CV_RGB(0,255,0)); } // Draw corner points cv::circle(dst, corners[0], 3, CV_RGB(255,0,0), 2); cv::circle(dst, corners[1], 3, CV_RGB(0,255,0), 2); cv::circle(dst, corners[2], 3, CV_RGB(0,0,255), 2); cv::circle(dst, corners[3], 3, CV_RGB(255,255,255), 2); // Draw mass center cv::circle(dst, center, 3, CV_RGB(255,255,0), 2); cv::Mat quad = cv::Mat::zeros(300, 220, CV_8UC3); std::vector<cv::Point2f> quad_pts; quad_pts.push_back(cv::Point2f(0, 0)); quad_pts.push_back(cv::Point2f(quad.cols, 0)); quad_pts.push_back(cv::Point2f(quad.cols, quad.rows)); quad_pts.push_back(cv::Point2f(0, quad.rows)); cv::Mat transmtx = cv::getPerspectiveTransform(corners, quad_pts); cv::warpPerspective(src, quad, transmtx, quad.size()); cv::imshow("image", dst); cv::imshow("quadrilateral", quad); cv::waitKey(); return 0; }
/////////////////////////////////////////////////////////////////// // Panel::CannyDetection() // Description: This function is called by DetectEdges() and it // is the Canny edge detection function which does not contain // debugging statements. We run the image through several different // image processing functions to prepare the image before edge // detection. After detection the edges we run Hough lines which // approximates lines of minimum length as specified in // Settings.xml. We find all intersections of the Hough lines // then make a minimum area rectangle around the intersections to // approximate the edges of the panel which we are trying to // measure. From there we use the unit conversion calculated // in DetectFeatures() to find a length and width of the current // panel. We report the length and width with a message box. /////////////////////////////////////////////////////////////////// Mat Panel::CannyDetection(Mat image, bool showImg) { Mat greyImage; cvtColor(image, greyImage, CV_BGR2GRAY); Mat eroded, dilated, thresh, blurredThresh, edges, edgesGray; vector<Vec2f> lines; threshold(greyImage, thresh, m_lowCannyThreshold, 255, THRESH_BINARY); erode(thresh, eroded, Mat()); dilate(eroded, dilated, Mat()); GaussianBlur(thresh, blurredThresh, Size(7, 7), m_sigmaX, m_sigmaY); Canny(blurredThresh, edges, m_cannyLow, m_cannyLow*m_ratio, 3); HoughLines(edges, lines, 1, CV_PI / 180, m_houghLength, 0, 0); cvtColor(edges, edgesGray, CV_GRAY2BGR); for (size_t i = 0; i < lines.size(); i++) { float rho = lines[i][0], theta = lines[i][1]; Point pt1, pt2; double a = cos(theta), b = sin(theta); double x0 = a*rho, y0 = b*rho; pt1.x = cvRound(x0 + 1000 * (-b)); pt1.y = cvRound(y0 + 1000 * (a)); pt2.x = cvRound(x0 - 1000 * (-b)); pt2.y = cvRound(y0 - 1000 * (a)); line(edgesGray, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA); } //////////////////////////////////////////////////////// // Compute the intersection from the lines detected //////////////////////////////////////////////////////// vector<Point2f> intersections; for (size_t i = 0; i < lines.size(); i++) { for (size_t j = 0; j < lines.size(); j++) { Vec2f line1 = lines[i]; Vec2f line2 = lines[j]; if (acceptLinePair(line1, line2, (float)CV_PI / 32)) { Point2f intersection = computeIntersect(line1, line2); if (intersection.x >= 0 && intersection.y >= 0) intersections.push_back(intersection); } } } if (intersections.size() > 0) { vector<Point2f>::iterator i; for (i = intersections.begin(); i != intersections.end(); ++i) { cout << "Intersection is " << i->x << ", " << i->y << endl; circle(image, *i, 2, Scalar(0, 255, 0), 3); } // Find the minimum bounding rectangle RotatedRect rect; Point2f rectPoints[4]; Scalar color = Scalar(255, 0, 0); if (intersections.size() == 4) { // TODO } rect = minAreaRect(intersections); rect.points(rectPoints); int j = 0; for (j; j < 4; j++) line(image, rectPoints[j], rectPoints[(j + 1) % 4], color, 5, 8); float topLength = (float)norm(rectPoints[1] - rectPoints[0]); float botLength = (float)norm(rectPoints[3] - rectPoints[2]); float panelWidthPixels = topLength < botLength ? topLength : botLength; float leftHeight = (float)norm(rectPoints[3] - rectPoints[0]); float rightHeight = (float)norm(rectPoints[2] - rectPoints[1]); float panelHeightPixels = leftHeight < rightHeight ? leftHeight : rightHeight; string dimensionDisplayPixels = "Pixels:\nWidth: " + to_string(panelWidthPixels) + " pixels\nHeight: " + to_string(panelHeightPixels) + " pixels"; // ShowMessage(dimensionDisplayPixels); if (m_conversionRate) { float panelWidthReal = panelWidthPixels / m_conversionRate; float panelHeightReal = panelHeightPixels / m_conversionRate; string dimensionDisplayActual = "Actual:\nWidth: " + to_string(panelWidthReal) + " cm\nHeight: " + to_string(panelHeightReal) + " cm"; ShowMessage(dimensionDisplayActual); } } if (showImg){ namedWindow("Intersections", CV_WINDOW_KEEPRATIO); imshow("Intersections", image); } ///////////////////////////////////////////////////////////// // End of Computing the intersection from the lines detected ///////////////////////////////////////////////////////////// return edges; }