示例#1
0
void paperRegistration::detectFigures(cv::vector<cv::vector<cv::Point>>& squares, cv::vector<cv::vector<cv::Point>>& triangles,
	float minLength, float maxLength, int tresh_binary)
{
	if (currentDeviceImg.empty())
		return;
	
	//cv::Mat image = currentDeviceImg;
	//cv::Mat image = cv::imread("C:/Users/sophie/Desktop/meinz.png", CV_LOAD_IMAGE_GRAYSCALE);// cv::imread(path, CV_LOAD_IMAGE_GRAYSCALE);  
	//resize(image, image, cv::Size(500,700));

	squares.clear();  
	triangles.clear();	
	
	cv::Mat gray;
	cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(7,7));
	cv::vector<cv::vector<cv::Point> > contours;

	//compute binary image
	//use dilatation and erosion to improve edges
	threshold(currentDeviceImg, gray, tresh_binary, 255, cv::THRESH_BINARY_INV);	
	dilate(gray, gray, element, cv::Point(-1,-1));
	erode(gray, gray, element, cv::Point(-1,-1));
	
	// find contours and store them all as a list
	cv::findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
	
	//test each contour
	cv::vector<cv::Point> approx;
	cv::vector<cv::vector<cv::Point> >::iterator iterEnd = contours.end();
	for(cv::vector<cv::vector<cv::Point> >::iterator iter = contours.begin(); iter != iterEnd; ++iter)
	{
		// approximate contour with accuracy proportional
		// to the contour perimeter
		cv::approxPolyDP(*iter, approx, arcLength(*iter, true)*0.03, true);
	     
		//contours should be convex
		if (isContourConvex(approx))
		{
			// square contours should have 4 vertices after approximation and 
			// relatively large length (to filter out noisy contours)
			if( approx.size() == 4)
			{
				bool rectangular = true;	 
				for( int j = 3; j < 6; j++ )
				{
					// if cosines of all angles are small
					// (all angles are ~90 degree) then write
					// vertices to result
					 if (fabs(90 - fabs(computeAngle(approx[j%4], approx[j-3], approx[j-2]))) > 7)
					 {
						rectangular = false;
						break;
					 }
				}
				
				if (!rectangular)
					continue;
				
				float side1 = computeLength(approx[0], approx[1]);
				float side2 = computeLength(approx[1], approx[2]);
					
				if (side1 > minLength && side1 < maxLength && 
					side2 > minLength && side2 < maxLength)
					squares.push_back(approx);
			}		
			// triangle contours should have 3 vertices after approximation and 
			// relatively large length (to filter out noisy contours)
			else if ( approx.size() == 3)
			{
				float side1 = computeLength(approx[0], approx[1]);
				float side2 = computeLength(approx[1], approx[2]);
				float side3 = computeLength(approx[2], approx[0]);
				
				if (side1 > minLength && side1 < maxLength && 
					side2 > minLength && side2 < maxLength &&
					side3 > minLength && side3 < maxLength)
					triangles.push_back(approx);
			}
		}
	}
}
示例#2
0
void DkPageSegmentation::findRectangles(const cv::Mat& img, std::vector<DkPolyRect>& rects, int channel, int threshold) const {

    cv::Mat imgL;
    cv::normalize(img, imgL, 255, 0, cv::NORM_MINMAX);

	// downscale
	if (scale != 1.0f)
		cv::resize(imgL, imgL, cv::Size(), scale, scale, CV_INTER_LINEAR);

	std::vector<std::vector<cv::Point> > contours;

	int threshStep = dsc::round(255.0 / numThresh);
	//std::cout << "thresh step: " << threshStep << std::endl;

	cv::Mat gray;
	std::vector<DkPolyRect> rectsL;

	std::vector<int> indexes;
	if (threshold == -1) {

		// use less thresholds for a/b channels
		if (channel > 0)
			threshStep *= 2;

		for (int idx = 0; idx < 255; idx += threshStep)
			indexes.push_back(idx);
	}
	else
		indexes.push_back(threshold);

	// try several threshold levels
	for (int thr : indexes) {

		if (thr == 0) {

			int thresh = 80;
			Canny(imgL, gray, thresh, thresh*3, 5);
			// dilate canny output to remove potential
			// holes between edge segments
			//dilate(gray, gray, cv::Mat(), cv::Point(-1,-1));

			//cv::imwrite("C:/VSProjects/DocScan/img/tests/edge.png", gray);
		}
		else
			gray = imgL >= thr;

        cv::erode(gray, gray, cv::Mat(), cv::Point(-1,-1));

		// find contours and store them all as a list
		findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

		if (looseDetection) {
			std::vector<std::vector<cv::Point> > hull;
			for (int i = 0; i < (int)contours.size(); i++) {

				double cArea = contourArea(cv::Mat(contours[i]));

				if (fabs(cArea) > mMinArea*scale*scale && (!mMaxArea || fabs(cArea) < mMaxArea*(scale*scale))) {
					std::vector<cv::Point> cHull;
					cv::convexHull(cv::Mat(contours[i]), cHull, false);
					hull.push_back(cHull);
				}
			}

			contours = hull;
		}

		std::vector<cv::Point> approx;

		// DEBUG ------------------------
		//cv::Mat pImg = imgL.clone();
		//cv::cvtColor(pImg, pImg, CV_GRAY2BGR);
		// DEBUG ------------------------

		// test each contour
		for (size_t i = 0; i < contours.size(); i++) {
			// approxicv::Mate contour with accuracy proportional
			// to the contour perimeter
			approxPolyDP(cv::Mat(contours[i]), approx, arcLength(cv::Mat(contours[i]), true)*0.02, true);

			double cArea = contourArea(cv::Mat(approx));

			// DEBUG ------------------------
			//if (fabs(cArea) < mMaxArea)
				//fillConvexPoly(pImg, &approx[0], (int)approx.size(), cv::Scalar(255,0,0));
			// DEBUG ------------------------

			// square contours should have 4 vertices after approxicv::Mation
			// relatively large area (to filter out noisy contours)
			// and be convex.
			// Note: absolute value of an area is used because
			// area may be positive or negative - in accordance with the
			// contour orientation
			if (approx.size() == 4 &&
				fabs(cArea) > mMinArea*scale*scale &&
				(!mMaxArea || fabs(cArea) < mMaxArea*scale*scale) &&
				isContourConvex(cv::Mat(approx))) {

				DkPolyRect cr(approx);
				//std::cout << mMinArea*scale*scale << " < " << fabs(cArea) << " < " << mMaxArea*scale*scale << std::endl;

				// if cosines of all angles are small
				// (all angles are ~90 degree)
				if(/*cr.maxSide() < std::max(tImg.rows, tImg.cols)*maxSideFactor && */
					(!maxSide || cr.maxSide() < maxSide*scale) &&
					cr.getMaxCosine() < 0.3 ) {

					cr.setChannel(channel);
					cr.setThreshold(thr);
					rectsL.push_back(cr);
				}
			}
		}
		// DEBUG ------------------------
		//cv::cvtColor(pImg, pImg, CV_RGB2BGR);
		//cv::imwrite("C:/VSProjects/DocScan/img/tests/poly" + Utils::num2str(thr) + ".png", pImg);
		// DEBUG ------------------------
	}

	for (size_t idx = 0; idx < rectsL.size(); idx++)
		rectsL[idx].scale(1.0f/scale);


	// filter rectangles which are found because of the image border
	for (const DkPolyRect& p : rectsL) {

		DkBox b = p.getBBox();

		if (b.size().height < img.rows*maxSideFactor &&
			b.size().width < img.cols*maxSideFactor) {
			rects.push_back(p);
		}
	}

	//cv::normalize(dbgImg, dbgImg, 255, 0, cv::NORM_MINMAX);

}
示例#3
0
bool ProcessingThread::CrossDetect(Mat gray, vector<Point2f> &cross)
{
	double tresholdmin = 0.6;
	int tresholdmin_int = 6;
	int tresholdmax_int = 6;
	int tresholdCannyMin = 1400;
	int tresholdCannyMax = 1500;

	bool found = true;
	vector<Mat> contours;
	vector<Point> approx;

	//Mat gray;
	//cvtColor(img, gray, CV_BGR2GRAY);

	Mat bw;
	Canny(gray, bw, tresholdCannyMin, tresholdCannyMax, 5);

	findContours(bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

	for (int i = 0; i < contours.size(); i++)
	{
		approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

		if (fabs(contourArea(contours[i])) < 100 || isContourConvex(approx) || (approx.size() != 8))
			continue;

		double x0 = approx[0].x;
		double x1 = approx[1].x;
		double x2 = approx[2].x;
		double x3 = approx[3].x;
		double x4 = approx[4].x;
		double x5 = approx[5].x;
		double x6 = approx[6].x;
		double x7 = approx[7].x;

		double y0 = approx[0].y;
		double y1 = approx[1].y;
		double y2 = approx[2].y;
		double y3 = approx[3].y;
		double y4 = approx[4].y;
		double y5 = approx[5].y;
		double y6 = approx[6].y;
		double y7 = approx[7].y;

		double length_top = (((abs(x0 - x1) + abs(x0 - x7)) / 2) + ((abs(y0 - y1) + abs(y0 - y7)) / 2)) / 2;
		double length_bot = (((abs(x3 - x4) + abs(x4 - x5)) / 2) + ((abs(y3 - y4) + abs(y4 - y5)) / 2)) / 2;
		double ratio1 = ((((length_top + length_bot) / length_top - 0.5) + ((length_top + length_bot) / length_bot - 0.5))) / 2 - 0.5;

		double length_left = (((abs(x2 - x1) + abs(x2 - x3)) / 2) + ((abs(y2 - y1) + abs(y2 - y3)) / 2)) / 2;
		double length_right = (((abs(x6 - x7) + abs(x6 - x5)) / 2) + ((abs(y6 - y7) + abs(y6 - y5)) / 2)) / 2;
		double ratio2 = ((((length_left + length_right) / length_left - 0.5) + ((length_left + length_right) / length_right - 0.5))) / 2 - 0.5;

		if (abs((ratio1 + ratio2) / 2 - 1) > 0.2)
		{
			found = false;
			continue;
		}

		for (int j = 0; j < approx.size() - 3; j++){
			double ang1 = angle(approx[j], approx[j + 1], approx[j + 2]);
			double ang2 = angle(approx[j + 1], approx[j + 2], approx[j + 3]);
			//printf("ang1: %f\t, ang2: %f \n", ang1, ang2);
			if (ang1 > 0.7){
				if (!(ang1 > 0.7 && ang2 < 0.3))
				{
					found = false;
					continue;
				}
			}
		}

		if (found)
		{
			for each(Point pt in approx)
				cross.push_back((Point2f)pt);
			return true;
		}

	}
	return found;
}