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;
}
void ImageProcessor::process(MultispectralImage frame)
{
	MultispectralImage frame8Bit;
	QList<imgDesc> results;

	quint8 i;

	Mat filterMask;
	Mat maskedFCImage;
	double maxVal = 0;
	double maxTemp = 0.0;

	Mat temp;
	double spread;

	Mat motionMask;

	errorOccurred = false;

	lockConfig.lockForRead();

	//main processing tasks
	//*********************

	//subtract dark image, if enabled
	if(myConfig.calibration.subtractDark && !frame.getDarkSubtracted())
	{
		for(i = 1; i < frame.getChannelCount(); i++)
		{
			//subtract dark image from current image
			Mat tmp;
			cv::subtract(frame.getImageByChannelNumber(i),
						 frame.getDarkImage(),
						 tmp);

			//set result as new channel image
			frame.setChannelImage(frame.getWavebands().at(i), tmp);
		}

		frame.setDarkSubtracted(true);
	}

	//perform skin detection by using quotient filters, if enabled
	if(myConfig.detectSkinByQuotient && (myConfig.quotientFilters.size() > 0))
	{
		//clear result list
		skinDetectionResults.clear();

		//signal processing of all filters
		emit doSkinDetection(frame);
	}

	//if image depth is more than 8bit, image has to be resampled to be displayed
	if(frame.getDepth() > 8)
	{
		//if automatic contrast is enabled, find the brightest spot in all channels
		if(myConfig.contrastAutomatic)
		{
			//iterate through all bands (except dark) to find maximum value
			for(i = 1; i < frame.getChannelCount(); i++)
			{
				minMaxLoc(frame.getImageByChannelNumber(i), NULL, &maxTemp);
				if ( maxTemp > maxVal )
				{
					maxVal = maxTemp;
				}
			}

			//subtract contrast dark offset from maximum
			maxVal -= myConfig.contrastOffset;

			//slowly increase or decrease contrast value
			if((maxVal / myConfig.contrastValue) < 220)
			{
				myConfig.contrastValue -= (myConfig.contrastValue - (maxVal / 255)) / 10;
			}
			else if((maxVal / myConfig.contrastValue) > 250)
			{
				myConfig.contrastValue += ((maxVal / 255) - myConfig.contrastValue) / 10;
			}
		}

		//calculate spread factor
		spread = 1.0 / (double)myConfig.contrastValue;

		//configure GUI image object
		frame8Bit.setSize(frame.getWidth(), frame.getHeight());
		frame8Bit.setDepth(8);

		//scale down every band
		for (i = 0; i < frame.getChannelCount(); i++)
		{
			//subtract contrast offset, if enabled
			Mat tempOffset;
			if(myConfig.contrastOffset > 0)
			{
				subtract(frame.getImageByChannelNumber(i),
						 Scalar(myConfig.contrastOffset),
						 tempOffset);
			}
			else
			{
				tempOffset = frame.getImageByChannelNumber(i);
			}

			//convert to 8 bit using spread factor
			tempOffset.convertTo(temp, 8, spread );
			frame8Bit.setChannelImage(frame.getWavebands().at(i), temp.clone());
		}
	}
	else
	{
		frame8Bit = frame;
	}

	//detect edges
	if(myConfig.edgeDetection)
	{
		QMapIterator<qint16, Mat> it(frame8Bit.getImages());
		while(it.hasNext())
		{
			it.next();

			Mat edges = doEdgeDetection(it.value(), myConfig.edgeThreshold);

			struct imgDesc edgeResult;
			edgeResult.desc = QString("Edges %1nm").arg(it.key());
			edgeResult.img = edges;
			results.append(edgeResult);
		}
	}

	//Estimate distance (in separate thread)
	if (myConfig.estimateDistance)
	{
		//make edge mask on selected image
		Mat edges;
		if(autoSelectCannyImage) //automatically select sharpest band image for edge detection
		{
			Canny(frame8Bit.getImageByChannelNumber(lastSharpestBand), edges, cannyLowThresh, cannyHighThresh);
		}
		else //use band image selected by the user (in GUI)
		{
			Canny(frame8Bit.getImageByChannelNumber(cannyImage), edges, cannyLowThresh, cannyHighThresh);
		}

		//emit signals to distance estimation thread
		distEstimationResults.clear();
		emit setDistEstimParams((int)myConfig.sharpMetric, edges, myConfig.sharpnessNbrhdSize, medianKernel);
		emit doDistanceEstimation(frame8Bit);

		//wait for thread to finish
		while (!errorOccurred && distEstimationResults.size() < 1) //frame8Bit.getChannelCount()-1)
		{
			QCoreApplication::processEvents();
		}
		if(errorOccurred)
		{
			emit errorProcessing(ImageSourceException("Error in task: estimateDistanceByChromAberr."));
			return;
		}

		//append distance estimation result to results in order to display them
		if(!distEstimationResults.empty())
		{
			//get 8 bit image from 1st list entry (at position 0)
			results.append(distEstimationResults.at(0));
		}
	}

	//wait for threads to finish:
	//***************************

	//wait until all threads are finished, get results and delete them

	if(myConfig.detectSkinByQuotient && (myConfig.quotientFilters.size() > 0))
	{
		maskedFCImage = Mat::zeros(frame8Bit.getDarkImage().rows,
								   frame8Bit.getDarkImage().cols, CV_8UC3);

		//wait until all threads are finished and get results
		while(!errorOccurred &&
			  (myConfig.quotientFilters.size() > skinDetectionResults.size()))
		{
			QCoreApplication::processEvents(QEventLoop::AllEvents);
		}
		if(errorOccurred)
		{
			emit errorProcessing(ImageSourceException("Error in task: detectSkinByQuotients."));
			return;
		}
		//multiply (cut) the filter masks
		filterMask = skinDetectionResults.at(0);
		for(i = 1; i < skinDetectionResults.size(); i++ )
		{
			multiply(filterMask, skinDetectionResults.at(i),
					 filterMask, 1.0);
		}

		//remove positive pixels with motion artifacts
		if(myConfig.suppressMotion && (lastFrame.getChannelCount() == frame.getChannelCount()))
		{
			motionMask = Mat::ones(maskedFCImage.rows, maskedFCImage.cols, CV_8UC1);

			for(i= 0; i < frame.getChannelCount(); i++)
			{
				Mat diffF, threshF, thresh;
				Mat curF, prevF;

				//get frame channels and convert to float
				frame.getImageByChannelNumber(i).convertTo(curF, CV_32F);
				lastFrame.getImageByChannelNumber(i).convertTo(prevF, CV_32F);

				//calculate absolute difference between current and previous frame
				absdiff(curF, prevF, diffF);

				//threshold the absolute difference
				threshold(diffF, threshF, myConfig.motionThreshold, 1.0, THRESH_BINARY_INV);

				//convert to 8 bit unsigned
				threshF.convertTo(thresh, CV_8U);

				//update motion mask with new thresholded difference mask
				multiply(motionMask, thresh, motionMask);
			}

			//now multiply motion mask with filter mask to remove positive filter results
			//where there was motion detected
			multiply(motionMask, filterMask, filterMask);

			//add motion mask to results
			struct imgDesc motionResult;
			motionResult.desc = "Motion";
			threshold(motionMask, motionResult.img, 0, 255, THRESH_BINARY_INV) ;
			results.append(motionResult);
		}

		//Morph result:
		if(myConfig.morphResult)
		{
			Mat element(4,4,CV_8U,Scalar(1));
			morphologyEx(filterMask, filterMask, MORPH_OPEN, element);
		}

		//set mask on top of (8bit) false colour image
		bitwise_or(maskedFCImage,
				   frame8Bit.getFalseColorImage(myConfig.falseColorChannels),
				   maskedFCImage, filterMask);

		if(myConfig.showMaskContours)
		{
			vector<vector<Point> > contours;
			CvScalar green = CV_RGB(0,255,0);
			//CvScalar blue = CV_RGB(0,0,255);

			findContours(filterMask, contours,
						 CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

			drawContours(maskedFCImage, contours, -1, green, 2, 8);
		}

		struct imgDesc skinMask;
		struct imgDesc skinResult;

		skinMask.desc = "QF Mask";
		threshold(filterMask, skinMask.img, 0, 255, THRESH_BINARY) ;
		results.append(skinMask);

		skinResult.desc = "Masked FC Image";
		skinResult.img = maskedFCImage;
		results.append(skinResult);
	}

	lockConfig.unlock();

	emit finishedProcessing(frame, frame8Bit, results);

	lastFrame = frame;
}
// 计算点所在的连通域外接矩形,并绘制
bool CAnswerCardApp::GetArchorPointRect(QPoint pt,int ap_idx,bool is_draw)
{
	//输入有效性检查
	if (ap_idx<0||ap_idx>3)
	{
		return false;
	}
	//连通域检测
	vector<vector<cv::Point> > contours;
	vector<Vec4i>hierarchy;

	CvRect roirect;
	int roisize=img_bw.rows*0.05;
	roirect.width=roirect.height=2*roisize;
	roirect.x=min(max(0,pt.x()-roisize),img_bw.cols-roirect.width);
	roirect.y=min(max(0,pt.y()-roisize),img_bw.rows-roirect.height);
	Mat roi;
	img_bw(roirect).copyTo(roi);

	findContours(roi,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE );

	bool isFound =false;
	if( !contours.empty())
	{
		for( unsigned int i = 0; i< contours.size(); i++ )
		{
			//不在多边形内部
			if (pointPolygonTest(contours.at(i),cv::Point(pt.x()-roirect.x,pt.y()-roirect.y),false)<0)
				continue;
			anchorPoints[ap_idx] = boundingRect(contours.at(i));
			anchorPoints[ap_idx].x += roirect.x;
			anchorPoints[ap_idx].y += roirect.y;
			isFound = true;
		}
	}

	//是否需要绘制
	if (is_draw)
	{
		//判断数据与图像是否同步
		if (is_synchronous)
		{
			switch(ap_idx)
			{
			case 0:
				cv::putText(img_show,"1",cv::Point2d(anchorPoints[ap_idx].x,anchorPoints[ap_idx].y+anchorPoints[ap_idx].height*0.9),FONT_HERSHEY_COMPLEX,.6,anchor_point_color,2);
				break;
			case 1:
				cv::putText(img_show,"2",cv::Point2d(anchorPoints[ap_idx].x,anchorPoints[ap_idx].y+anchorPoints[ap_idx].height*0.9),FONT_HERSHEY_COMPLEX,.6,anchor_point_color,2);
				break;
			case 2:
				cv::putText(img_show,"3",cv::Point2d(anchorPoints[ap_idx].x,anchorPoints[ap_idx].y+anchorPoints[ap_idx].height*0.9),FONT_HERSHEY_COMPLEX,.6,anchor_point_color,2);
				break;
			case 3:
				cv::putText(img_show,"4",cv::Point2d(anchorPoints[ap_idx].x,anchorPoints[ap_idx].y+anchorPoints[ap_idx].height*0.9),FONT_HERSHEY_COMPLEX,.6,anchor_point_color,2);
				break;

			}
			rectangle(img_show,anchorPoints[ap_idx],anchor_point_color,anchor_point_thickness);
		}else
			is_synchronous = false;
	}
	//是否找到对应的连通域
	if (isFound)
		return true;
	else
		return false;
	
}
vector<Point> Camera::Follow() //prima void
{
    //float* contour=new float[height*width]();
    float* output=new float[height*width]();
    vector<float> temp = ToArray(Mat::zeros(height, width, CV_8UC1 ));
    output = &temp[0];
    cout << "[START] Active Contour " << endl;
    
    // Follow the camera
    cout << "Following the camera ...";
    cout << flush;
    Point center(-1,-1); Vec3b hsv; Mat mask, gray, HSV; Scalar lowerb, upperb;
    int erosion_size = 2, dilation_size = 10;
    Mat erodeElement = getStructuringElement(MORPH_RECT, Size(2 * erosion_size + 1, 2 * erosion_size + 1), Point(erosion_size, erosion_size) );
    Mat dilateElement = getStructuringElement(MORPH_RECT, Size(2 * dilation_size + 1, 2 * dilation_size + 1), Point(dilation_size, dilation_size) );
    vector<float> frameArray, maskArray;
    Mat ROI = Mat::zeros( height, width, CV_8UC1 );
    int count = 0; double sum = 0; 
    
    //while(waitKey(1) == -1) {//da togliere
        /*if (capture.read(frame) == NULL) {
            cout << "[ERROR] frame not read" << endl;
            return;
        }*/ //frame già settato
        clock_t startTime = clock(); // compute the time
        cvtColor(frame, gray, COLOR_RGB2GRAY);        
        cvtColor(frame, HSV, COLOR_RGB2HSV);
        
        setMouseCallback("Frame", onMouse);
        
        if( drawing_box ) 
            draw_box(&frame, roi);
        
        if(clicked) {
            // Init mask
            if(!haveMask) {
                // Take hsv from mouse
                center = initCenter;
                hsv = HSV.at<Vec3b>(center.y,center.x);
                haveMask = true;
                //cout << "HSV: " << hsv << endl;
                lowerb = Scalar(hsv.val[0] - 30, hsv.val[1] - 50, hsv.val[2] - 50);
                upperb = Scalar(hsv.val[0] + 30, hsv.val[1] + 50, hsv.val[2] + 50);
                //cout << "lowerb: " << lowerb << endl;
                //cout << "upperb: " << upperb << endl;  
                ROI = Mat::zeros( height, width, CV_8UC1 );
                rectangle( ROI, roi.tl(), roi.br(), Scalar(255), -1);
                
                sum = 0; count = 0; //benchmark
                
            }
            
            // Create the mask
            
            inRange(HSV, lowerb , upperb, mask);
            dilate(mask, mask, dilateElement);
            mask = mask.mul(ROI);
            
            //imshow("mask", mask);
            
            frameArray = ToArray(gray);
            maskArray = ToArray(mask);
            ActiveContour(&frameArray[0], output, contour, &maskArray[0], width, height, roi.br().y);  
            
            Mat OUT = ToMat(output, height, width);
            OUT.convertTo(OUT, CV_8UC1);
            //imshow("Output", OUT);
            
            vector<vector<Point> > contours;
            vector<Vec4i> hierarchy;
            findContours(OUT, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
            
            vector<Rect> boundRect( contours.size() );
            
            for( int i = 0; i < contours.size(); i++ )
            { 
                boundRect[i] = boundingRect( Mat(contours[i]) );
            }
            
            /// Draw polygonal contour + bonding rects + circles
            Mat drawing = Mat::zeros( height, width, CV_8UC3 );
            circle(frame, center, 5, Scalar(0,0,255), 5);
            
            for( int i = 0; i< contours.size(); i++ )
            {
                
                if(boundRect[i].contains(center)) {
                    
                    drawContours( frame, contours, i, Scalar(255,255,255), 1, 8, vector<Vec4i>(), 0, Point() );
                    rectangle( frame, boundRect[i].tl(), boundRect[i].br(), Scalar(0,255,0), 2, 8, 0 );
                    
                    // Center
                    center.x = boundRect[i].tl().x + boundRect[i].size().width/2;
                    center.y = boundRect[i].tl().y + boundRect[i].size().height/2;
                    
                    int x = boundRect[i].size().width;
                    int y = boundRect[i].size().height;
                    int v = (int)(sqrt((x/(y+EPS))*area));
                    int h = (int)(area/v);
                    int deltax = (int)((h-y)/2);
                    int deltay = (int)((v-x)/2);
                    int tlx = boundRect[i].tl().x -deltax;
                    int tly = boundRect[i].tl().y -deltay;
                    int brx = boundRect[i].br().x +deltax;
                    int bry = boundRect[i].br().y +deltay;
                    tlx = (tlx < 0) ? 0 : tlx;
                    brx = (brx > width) ? width : brx;
                    tly = (tly < 0) ? 0 : tly;
                    bry = (bry > height) ? height : bry;                   
                    roi = Rect(Point(tlx,tly),Point(brx,bry));
                    ROI = Mat::zeros( height, width, CV_8UC1 );
                    rectangle( ROI, roi.tl(), roi.br(), Scalar(255), -1);
                    rectangle( frame, roi.tl(), roi.br(), Scalar(0,0,255), 2, 8, 0 );
                    //imshow("ROI", ROI);
                    break;
                }
            }
        }
        imshow("Frame", frame);
        sum += double( clock() - startTime ) / (double)CLOCKS_PER_SEC;
        count++;
        
//  }
    cout << sum / count << endl << flush;
    return contours.front();
}
void SupportVectorMachineDemo(Mat& class1_samples, char* class1_name, Mat& class2_samples, char* class2_name, Mat& unknown_samples)
{
    float labels[MAX_SAMPLES];
    float training_data[MAX_SAMPLES][2];
	CvSVM SVM;

    // Image for visual representation of (2-D) feature space
    int width = MAX_FEATURE_VALUE+1, height = MAX_FEATURE_VALUE+1;
    Mat feature_space = Mat::zeros(height, width, CV_8UC3);

	int number_of_samples = 0;
	// Loops three times:
	//  1st time - extracts feature values for class 1
	//  2nd time - extracts feature values for class 2 AND trains SVM
	//  3rd time - extracts feature values for unknowns AND predicts their classes using SVM
	for (int current_class = 1; current_class<=UNKNOWN_CLASS; current_class++)
	{
		Mat gray_image,binary_image;
		if (current_class == 1)
			cvtColor(class1_samples, gray_image, CV_BGR2GRAY);
		else if (current_class == 2)
			cvtColor(class2_samples, gray_image, CV_BGR2GRAY);
		else cvtColor(unknown_samples, gray_image, CV_BGR2GRAY);        
		threshold(gray_image,binary_image,128,255,THRESH_BINARY_INV);

	    vector<vector<Point>> contours;
		vector<Vec4i> hierarchy;
		findContours(binary_image,contours,hierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);
		Mat contours_image = Mat::zeros(binary_image.size(), CV_8UC3);
		contours_image = Scalar(255,255,255);
		// Do some processing on all contours (objects and holes!)
		vector<vector<Point>> hulls(contours.size());
		vector<vector<int>> hull_indices(contours.size());
		vector<vector<Vec4i>> convexity_defects(contours.size());
		vector<Moments> contour_moments(contours.size());
		for (int contour_number=0; (contour_number>=0); contour_number=hierarchy[contour_number][0])
		{
			if (contours[contour_number].size() > 10)
			{
				convexHull(contours[contour_number], hulls[contour_number]);
				convexHull(contours[contour_number], hull_indices[contour_number]);
				convexityDefects( contours[contour_number], hull_indices[contour_number], convexity_defects[contour_number]);
				contour_moments[contour_number] = moments( contours[contour_number] );
				// Draw the shape and features
				Scalar colour( rand()&0x7F, rand()&0x7F, rand()&0x7F );
				drawContours( contours_image, contours, contour_number, colour, CV_FILLED, 8, hierarchy );
				char output[500];
				double area = contourArea(contours[contour_number])+contours[contour_number].size()/2+1;
				// Draw the convex hull
				drawContours( contours_image, hulls, contour_number, Scalar(127,0,127) );
				// Highlight any convexities
				int largest_convexity_depth=0;
				for (int convexity_index=0; convexity_index < (int)convexity_defects[contour_number].size(); convexity_index++)
				{
					if (convexity_defects[contour_number][convexity_index][3] > largest_convexity_depth)
						largest_convexity_depth = convexity_defects[contour_number][convexity_index][3];
					if (convexity_defects[contour_number][convexity_index][3] > 256*2)
					{
						line( contours_image, contours[contour_number][convexity_defects[contour_number][convexity_index][0]], contours[contour_number][convexity_defects[contour_number][convexity_index][2]], Scalar(0,0, 255));
						line( contours_image, contours[contour_number][convexity_defects[contour_number][convexity_index][1]], contours[contour_number][convexity_defects[contour_number][convexity_index][2]], Scalar(0,0, 255));
					}
				}
				// Compute moments and a measure of the deepest convexity
				double hu_moments[7];
				HuMoments( contour_moments[contour_number], hu_moments );
				double diameter = ((double) contours[contour_number].size())/PI;
				double convexity_depth = ((double) largest_convexity_depth)/256.0;
				double convex_measure = convexity_depth/diameter;
				int class_id = current_class;
				float feature[2] = { (float) convex_measure*((float) MAX_FEATURE_VALUE), (float) hu_moments[0]*((float) MAX_FEATURE_VALUE) };
				if (feature[0] > ((float) MAX_FEATURE_VALUE)) feature[0] = ((float) MAX_FEATURE_VALUE);
				if (feature[1] > ((float) MAX_FEATURE_VALUE)) feature[1] = ((float) MAX_FEATURE_VALUE);
				if (current_class == UNKNOWN_CLASS)
				{
					// Try to predict the class
					Mat sampleMat = (Mat_<float>(1,2) << feature[0], feature[1]);
					float prediction = SVM.predict(sampleMat);
					class_id = (prediction == 1.0) ? 1 : (prediction == -1.0) ? 2 : 0;
				}
				char* current_class_name = (class_id==1) ? class1_name : (class_id==2) ? class2_name : "Unknown";

				sprintf(output,"Class=%s, Features %.2f, %.2f", current_class_name, feature[0]/((float) MAX_FEATURE_VALUE), feature[1]/((float) MAX_FEATURE_VALUE));
				Point location( contours[contour_number][0].x-40, contours[contour_number][0].y-3 );
				putText( contours_image, output, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
				if (current_class == UNKNOWN_CLASS)
				{
				}
				else if (number_of_samples < MAX_SAMPLES)
				{
					labels[number_of_samples] = (float) ((current_class == 1) ? 1.0 : -1.0);
					training_data[number_of_samples][0] = feature[0];
					training_data[number_of_samples][1] = feature[1];
					number_of_samples++;
				}
			}
		}
		if (current_class == 1)
		{
			Mat temp_output = contours_image.clone();
			imshow(class1_name, temp_output );
		}
		else if (current_class == 2)
		{
			Mat temp_output2 = contours_image.clone();
			imshow(class2_name, temp_output2 );

			// Now that features for both classes have been determined, train the SVM
			Mat labelsMat(number_of_samples, 1, CV_32FC1, labels);
			Mat trainingDataMat(number_of_samples, 2, CV_32FC1, training_data);
			// Set up SVM's parameters
			CvSVMParams params;
			params.svm_type    = CvSVM::C_SVC;
			params.kernel_type = CvSVM::POLY;
			params.degree = 1;
			params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
			// Train the SVM
			SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

			// Show the SVM classifier for all possible feature values
			Vec3b green(192,255,192), blue (255,192,192);
			// Show the decision regions given by the SVM
			for (int i = 0; i < feature_space.rows; ++i)
				for (int j = 0; j < feature_space.cols; ++j)
				{
					Mat sampleMat = (Mat_<float>(1,2) << j,i);
					float prediction = SVM.predict(sampleMat);
					if (prediction == 1)
						feature_space.at<Vec3b>(i,j) = green;
					else if (prediction == -1)
					    feature_space.at<Vec3b>(i,j)  = blue;
				}
			// Show the training data (as dark circles)
			for(int sample=0; sample < number_of_samples; sample++)
				if (labels[sample] == 1.0)
					circle( feature_space, Point((int) training_data[sample][0], (int) training_data[sample][1]), 3, Scalar( 0, 128, 0 ), -1, 8);
				else circle( feature_space, Point((int) training_data[sample][0], (int) training_data[sample][1]), 3, Scalar( 128, 0, 0 ), -1, 8);
			// Highlight the support vectors (in red)
			int num_support_vectors = SVM.get_support_vector_count();
			for (int support_vector_index = 0; support_vector_index < num_support_vectors; ++support_vector_index)
			{
				const float* v = SVM.get_support_vector(support_vector_index);
				circle( feature_space,  Point( (int) v[0], (int) v[1]),   3,  Scalar(0, 0, 255));
			}
			imshow("SVM feature space", feature_space);
		}
		else if (current_class == 3)
		{
			imshow("Classification of unknowns", contours_image );
		}
	}
}
  vector<PlateRegion> DetectorMorph::detect(Mat frame, std::vector<cv::Rect> regionsOfInterest) {

    Mat frame_gray,frame_gray_cp;

    if (frame.channels() > 2)
    {
      cvtColor( frame, frame_gray, CV_BGR2GRAY );
    }
    else
    {
      frame.copyTo(frame_gray);
    }

    frame_gray.copyTo(frame_gray_cp);
    blur(frame_gray, frame_gray, Size(5, 5));

    vector<PlateRegion> detectedRegions;
    for (int i = 0; i < regionsOfInterest.size(); i++) {
      Mat img_open, img_result;
      Mat element = getStructuringElement(MORPH_RECT, Size(30, 4));
      morphologyEx(frame_gray, img_open, CV_MOP_OPEN, element, cv::Point(-1, -1));

      img_result = frame_gray - img_open;

      if (config->debugDetector && config->debugShowImages) {
        imshow("Opening", img_result);
      }

      //threshold image using otsu thresholding
      Mat img_threshold, img_open2;
      threshold(img_result, img_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);

      if (config->debugDetector && config->debugShowImages) {
        imshow("Threshold Detector", img_threshold);
      }

      Mat diamond(5, 5, CV_8U, cv::Scalar(1));

	diamond.at<uchar>(0, 0) = 0;
	diamond.at<uchar>(0, 1) = 0;
	diamond.at<uchar>(1, 0) = 0;
	diamond.at<uchar>(4, 4) = 0;
	diamond.at<uchar>(3, 4) = 0;
	diamond.at<uchar>(4, 3) = 0;
	diamond.at<uchar>(4, 0) = 0;
	diamond.at<uchar>(4, 1) = 0;
	diamond.at<uchar>(3, 0) = 0;
	diamond.at<uchar>(0, 4) = 0;
	diamond.at<uchar>(0, 3) = 0;
	diamond.at<uchar>(1, 4) = 0;
			
      morphologyEx(img_threshold, img_open2, CV_MOP_OPEN, diamond, cv::Point(-1, -1));
      Mat rectElement = getStructuringElement(cv::MORPH_RECT, Size(13, 4));
      morphologyEx(img_open2, img_threshold, CV_MOP_CLOSE, rectElement, cv::Point(-1, -1));

      if (config->debugDetector && config->debugShowImages) {
        imshow("Close", img_threshold);
        waitKey(0);
      }

      //Find contours of possibles plates
      vector< vector< Point> > contours;
      findContours(img_threshold,
              contours, // a vector of contours
              CV_RETR_EXTERNAL, // retrieve the external contours
              CV_CHAIN_APPROX_NONE); // all pixels of each contours

      //Start to iterate to each contour founded
      vector<vector<Point> >::iterator itc = contours.begin();
      vector<RotatedRect> rects;

      //Remove patch that are no inside limits of aspect ratio and area.    
      while (itc != contours.end()) {
        //Create bounding rect of object
        RotatedRect mr = minAreaRect(Mat(*itc));
        
        if (mr.angle < -45.) {
					mr.angle += 90.0;
					swap(mr.size.width, mr.size.height);
				}  
        
        if (!CheckSizes(mr))
          itc = contours.erase(itc);
        else {
          ++itc;
					rects.push_back(mr);
        }
      }

     //Now prunning based on checking all candidate plates for a min/max number of blobsc
Mat img_crop, img_crop_b, img_crop_th, img_crop_th_inv;
vector< vector< Point> > plateBlobs;
vector< vector< Point> > plateBlobsInv;
double thresholds[] = { 10, 40, 80, 120, 160, 200, 240 };
const int num_thresholds = 7;
int numValidChars = 0;
Mat rotated;
for (int i = 0; i < rects.size(); i++) {
	numValidChars = 0;
	RotatedRect PlateRect = rects[i];
	Size rect_size = PlateRect.size;

	// get the rotation matrix
	Mat M = getRotationMatrix2D(PlateRect.center, PlateRect.angle, 1.0);
	// perform the affine transformation
	warpAffine(frame_gray_cp, rotated, M, frame_gray_cp.size(), INTER_CUBIC);
	//Crop area around candidate plate
	getRectSubPix(rotated, rect_size, PlateRect.center, img_crop);

	 if (config->debugDetector && config->debugShowImages) {
		imshow("Tilt Correction", img_crop);
		waitKey(0);
	}

	for (int z = 0; z < num_thresholds; z++) {

		cv::threshold(img_crop, img_crop_th, thresholds[z], 255, cv::THRESH_BINARY);
		cv::threshold(img_crop, img_crop_th_inv, thresholds[z], 255, cv::THRESH_BINARY_INV);

		findContours(img_crop_th,
			plateBlobs, // a vector of contours
			CV_RETR_LIST, // retrieve the contour list
			CV_CHAIN_APPROX_NONE); // all pixels of each contours

		findContours(img_crop_th_inv,
			plateBlobsInv, // a vector of contours
			CV_RETR_LIST, // retrieve the contour list
			CV_CHAIN_APPROX_NONE); // all pixels of each contours

		int numBlobs = plateBlobs.size();
		int numBlobsInv = plateBlobsInv.size();
	
		float idealAspect = config->charWidthMM / config->charHeightMM;
		for (int j = 0; j < numBlobs; j++) {
			cv::Rect r0 = cv::boundingRect(cv::Mat(plateBlobs[j]));
			
			if (ValidateCharAspect(r0, idealAspect))
				numValidChars++;
		}

		for (int j = 0; j < numBlobsInv; j++) {
			cv::Rect r0 = cv::boundingRect(cv::Mat(plateBlobsInv[j]));
			if (ValidateCharAspect(r0, idealAspect))
				numValidChars++;
		}

	}
	//If too much or too lcittle might not be a true plate
	//if (numBlobs < 3 || numBlobs > 50) continue;
	if (numValidChars < 4  || numValidChars > 50) continue;

        PlateRegion PlateReg;

        // Ensure that the rectangle isn't < 0 or > maxWidth/Height
        Rect bounding_rect = PlateRect.boundingRect();
        PlateReg.rect = expandRect(bounding_rect, 0, 0, frame.cols, frame.rows);
        
        
        detectedRegions.push_back(PlateReg);

      }

    }
    
    return detectedRegions;
  }
Exemple #7
0
/**
 * Find a list of candidate marker from a given scene
 *
 * @param current frame, in grayscale 8UC1 format
 * @return a list of marker candidates
 **/
vector<Marker> MarkerDetector::findMarkerCandidates( Mat& frame ) {
    vector<Marker> candidates;
    
    /* Do some thresholding, in fact you should tune the parameters here a bit */
    Mat thresholded;
    threshold( frame, thresholded, 50.0, 255.0, CV_THRESH_BINARY );
    
    /* Find contours */
    vector<vector<Point>> contours;
    findContours( thresholded.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE );
    
    for( vector<Point> contour: contours ) {
        /* Approximate polygons out of these contours */
        vector<Point> approxed;
        approxPolyDP( contour, approxed, contour.size() * 0.05, true );
        
        /* Make sure it passes our first candidate check */
        if( !checkPoints( approxed ) )
            continue;
        
        /* Do some perspective transformation on the candidate marker to a predetermined square */
        Marker marker;
        marker.matrix = Mat( markerHeight, markerWidth, CV_8UC1 );
        std::copy( approxed.begin(), approxed.end(), back_inserter( marker.poly ) );
        
        /* Apply sub pixel search */
        cornerSubPix( thresholded, marker.poly, Size(5, 5), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001) );
        
        /* Projection target */
        const static vector<Point2f> target_corners = {
            Point2f( -0.5f, -0.5f ),
            Point2f( +5.5f, -0.5f ),
            Point2f( +5.5f, +5.5f ),
            Point2f( -0.5f, +5.5f ),
        };
        
        /* Apply perspective transformation, to project our 3D marker to a predefined 2D coords */
        Mat projection = getPerspectiveTransform( marker.poly, target_corners );
        warpPerspective( thresholded, marker.matrix, projection, marker.matrix.size() );
        
        /* Ignore those region that's fully black, or not surrounded by black bars */
        if( sum(marker.matrix) == Scalar(0) ||
           countNonZero( marker.matrix.row(0)) != 0 ||
           countNonZero( marker.matrix.row(markerHeight - 1)) != 0 ||
           countNonZero( marker.matrix.col(0)) != 0 ||
           countNonZero( marker.matrix.col(markerWidth - 1)) != 0 ) {
            continue;
        }
        
        
        /* Find the rotation that has the smallest hex value */
        pair<unsigned int, unsigned int> minimum = { numeric_limits<unsigned int>::max(), 0 };
        vector<unsigned int> codes(markerHeight);
        unsigned int power = 1 << (markerWidth - 3);
        
        /* Rotate the marker 4 times, store the hex code upon each rotation */
        for( int rotation = 0; rotation < 4; rotation++ ) {
            stringstream ss;
            codes[rotation] = 0;
            
            for( int i = 1; i < markerHeight - 1; i++ ) {
                unsigned int code = 0;
                for ( int j = 1; j < markerWidth - 1; j++ ){
                    int value = static_cast<int>(marker.matrix.at<uchar>(i, j));
                    if( value == 0 )
                        code = code + ( power >> j );
                }
                
                ss << hex << code;
            }
            ss >> codes[rotation];
            
            if( minimum.first > codes[rotation] ) {
                minimum.first  = codes[rotation];
                minimum.second = rotation;
            }
            
            flip( marker.matrix, marker.matrix, 1 );
            marker.matrix = marker.matrix.t();
        }
        
        
        rotate( marker.poly.begin(), marker.poly.begin() + ((minimum.second + 2) % 4), marker.poly.end() );
        for( int i = 0; i < minimum.second; i++ ) {
            flip( marker.matrix, marker.matrix, 1 );
            marker.matrix = marker.matrix.t();
        }
        
        marker.code = minimum.first;
        
        candidates.push_back( marker );
    }
    
    return candidates;
}
void sktinfoextractor::hacerUpdate(){
    int hhh=cam->numContextosIniciados;
    if(cam->numContextosIniciados>0){
        if(numFrames==0){
#ifdef _WIN32 || _WIN64
            GetSystemTime(&inicio);
#else
            gettimeofday(&inicio,NULL);
#endif
        }
        bool* update=new bool[cam->numContextosIniciados];

        //if(cam->updateCam(true,0,true,false)){
        int tid;

        Moments moms;
        int b;
        Point2f pt;
        if(cam->numContextosIniciados>1){
            omp_set_num_threads(2);
#pragma omp parallel private(tid,moms,b,pt) shared(update)
            {
                /// TODO : FIX FOR LESS AVAILABLE THREADS THAN CONTEXTS
                tid = omp_get_thread_num();
                //if(tid!=0){
                //  tid--;
                cameras* cc=cam;
                if(tid<cc->numContextosIniciados){
                    if(cc->updateCam(false,tid,true,false)){
                        cc->retriveDepthAndMask(tid,depths[tid],masks[tid]);
                        cc->retrivePointCloudFast(tid,&(depths[tid]),&(pCs[tid]));
                        if(cConfig[tid]->method=="Background"){
                            depths[tid].convertTo(depthsS[tid],CV_32FC1,1.0/6000);
                            sktP[tid]->processImage(depthsS[tid],toBlobs[tid],masks[tid]);
                        }
                        else
                        {
                            sktP[tid]->processImage(pCs[tid],toBlobs[tid],masks[tid]);
                        }
                        findContours(toBlobs[tid], blobs[tid],CV_RETR_LIST,CV_CHAIN_APPROX_NONE);
                        finBlobs[tid].clear();
                        blobSizes[tid].clear();
                        for(b=0; b<blobs[tid].size(); b++)
                        {
                            moms=moments(blobs[tid][b],true);
                            if(moms.m00>cConfig[tid]->minBlobSize)
                            {
                                //Point2f pt((int)(moms.m10 / moms.m00),(int)(moms.m01 / moms.m00));
                                //circle(toBlobs[k],pt,sqrt((double)moms.m00/3.14),cvScalar(255),-1);
                                //Save blob centers
                                pt.x=(int)(moms.m10 / moms.m00);
                                pt.y=(int)(moms.m01 / moms.m00);
                                finBlobs[tid].push_back(pt);
                                blobSizes[tid].push_back((int)moms.m00);
                            }
                        }
                        update[tid]=true;
                    }
                    else{update[tid]=false;}
                }
                //}
            }
        }
        else{
            if(cam->updateCam(false,0,true,false)){
                cam->retriveDepthAndMask(0,depths[0],masks[0]);
                cam->retrivePointCloudFast(0,&(depths[0]),&(pCs[0]));
                if(cConfig[0]->method=="Background"){
                    depths[0].convertTo(depthsS[0],CV_32FC1,1.0/6000);
                    sktP[0]->processImage(depthsS[0],toBlobs[0],masks[0]);
                }
                else
                {
                    sktP[0]->processImage(pCs[0],toBlobs[0],masks[0]);
                }
                findContours(toBlobs[0], blobs[0],CV_RETR_LIST,CV_CHAIN_APPROX_NONE);
                finBlobs[0].clear();
                blobSizes[0].clear();
                for(b=0; b<blobs[0].size(); b++)
                {
                    moms=moments(blobs[0][b],true);
                    if(moms.m00>cConfig[0]->minBlobSize)
                    {
                        //Point2f pt((int)(moms.m10 / moms.m00),(int)(moms.m01 / moms.m00));
                        //circle(toBlobs[k],pt,sqrt((double)moms.m00/3.14),cvScalar(255),-1);
                        //Save blob centers
                        pt.x=(int)(moms.m10 / moms.m00);
                        pt.y=(int)(moms.m01 / moms.m00);
                        finBlobs[0].push_back(pt);
                        blobSizes[0].push_back((int)moms.m00);
                    }
                }
                update[0]=true;
            }
            else{update[0]=false;}
        }
        bool doUpdate=true;
        for(int i=0;i<cam->numContextosIniciados;i++){
            doUpdate=(doUpdate && update[i]);
        }
        if(doUpdate){
            vector<Point2f> ou=finBlobs[0];
            if(cam->numContextosIniciados>1 && update[1]){
                if(ui->mixActive->isChecked()){
                    //Run through blob centers and get 3d vector
                    //Convert 3d vectors to the first cam
                    int count=0;
                    XnPoint3D* rP=real;
                    Vec3f v;
                    //cout <<"SIZE : " << finBlobs[1].size() << endl;
                    for(int i=0;i<finBlobs[1].size();i++){
                        if(count<999 && calMat.cols>2){
                            /// POSIBLE SPEEDUP : USE POINTERS
                            v=pCs[1].at<Vec3f>(finBlobs[1][i].y,finBlobs[1][i].x);
                            ///
                            (*rP).X=v[0]*matC[0][0]+v[1]*matC[0][1]+v[2]*matC[0][2] +matC[0][3];
                            (*rP).Y=v[0]*matC[1][0]+v[1]*matC[1][1]+v[2]*matC[1][2] +matC[1][3];
                            (*rP).Z=v[0]*matC[2][0]+v[1]*matC[2][1]+v[2]*matC[2][2] +matC[2][3];
                            count++;rP++;}
                    }
                    //Convert results to projected in first cam
                    if(count >0)
                        cam->depthG[0].ConvertRealWorldToProjective(count,real,proj);

                    rP=proj;

                    for(int i=0;i<count;i++){
                        //circle(final,Point(proj[i].X,proj[i].Y),sqrt((double)blobSizes[1][i]/3.14),cvScalar(0,0,255),-1);
                        if(!hasCloseBlob2(rP,finBlobs[0],mD)){
                            //cout << "1 : "<< (int)(rP->X) << "," << (int)(rP->Y) << endl;
                            ou.push_back(Point2f(rP->X,rP->Y));
                        }
                        rP++;
                    }
                }
                else{
                    ou.insert(ou.end(), finBlobs[1].begin(), finBlobs[1].end() );
                }
            }
            if(sendTuio && isServerCreated){
                if(calSKT->isCalibrated){
                    calSKT->convertPointVector(&ou);
                }
                tds->sendCursors(ou,minDataUpdate);
            }
            if(useDC){
                if(calSKT->isCalibrated){
                    calSKT->convertPointVector(&ou);
                }
                dc->updateData(ou,minDataUpdate);
            }
            numFrames++;
        }
        if(numFrames==10){
            numFrames=0;

#ifdef _WIN32 || _WIN64
            SYSTEMTIME fin;
            GetSystemTime(&fin);
            double timeSecs=(double)(fin.wSecond+(double)fin.wMilliseconds/1000.0-((double)inicio.wMilliseconds/1000.0+inicio.wSecond))/10;
#else
            struct timeval fin;
            gettimeofday(&fin,NULL);
            double timeSecs=(double)(fin.tv_sec+(double)fin.tv_usec/1000000.0-((double)inicio.tv_usec/1000000.0+inicio.tv_sec))/10;
#endif
            //cout << timeSecs << endl;
            double dif=1.0/timeSecs;
            //cout << "FPS : " << dif <<endl;
            ui->framesPerSec->setText(QString::number(dif));
        }
        delete update;
    }
}
Exemple #9
0
Mat ScreenDetector::getTransformationMatrix(Error& error)
{
    bool approxFound = false;

    // convert image to HSV
    cvtColor(img, hsv, CV_BGR2HSV);

    // threshold the image
    inRange(hsv, hsvMin, hsvMax, thresholded);

    // Optimize threshold by reducing noise
    erode(thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) );
    dilate( thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) );
    dilate( thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) );
    erode(thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) );
    GaussianBlur(thresholded, thresholded, Size(3,3), 0);

    Mat forContours;
    thresholded.copyTo(forContours);
    // find all contours
    Contours contours;
    Contour approximatedScreen;
    findContours(forContours, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
    int nbContours = contours.size();
    cout << nbContours << " contours found, debug: " << DEBUG << endl;

    if(nbContours == 0)
    {
        error.setError("Unable to find the screen",
                       "The camera doesn't detect any screen or green element."
                       "Please check if your screen is turned on and directed toward the screen");
        return img;
    }

    sort(contours.begin(), contours.end(), contour_compare_area);

    // find the contour with the biggest area that have 4 points when approximated
    for(int i=0; i < nbContours; ++i)
    {
        approxPolyDP(contours.at(i), approximatedScreen, approximateEpsilon * arcLength(contours.at(i), true), true);
        // our screen has 4 point when approximated
        if(approximatedScreen.size() == 4)
        {
            approxFound = true;
            break;
        }
    }

    if(!approxFound)
    {
        error.setError("Unable to find the screen properly",
                       "It seems that the screen is not fully detectable by the camera. Try to reduce light in your room");
        return img;
    }

    if(DEBUG)
    {
        namedWindow("debug", WINDOW_KEEPRATIO);
        namedWindow("thresholded_calibration", WINDOW_KEEPRATIO);
        Mat debug = Mat::zeros(img.rows, img.cols, CV_8UC3);
        polylines(debug, approximatedScreen, true, Scalar(0,0,255), 3);
        imshow("debug", debug);
        imshow("thresholded_calibration", thresholded);
    }

    return transformImage(approximatedScreen);
}
Template::Template(QString path){
    width = -2;
    height = -2;
    for (int i = 0; i < TEMPLATES_COUNT; i++){
        QString file = path + QString::number(i) + ".png";
        cv::Mat im = cv::imread(file.toStdString());
        cvtColor(im, images[i], CV_RGB2GRAY);

        if (width == -2){
            width = images[i].cols;
        }
        else if (images[i].cols != width){
            qDebug() << "Error : all templates must be the same size";
        }

        if (height == -2){
            height = images[i].rows;
        }
        else if (images[i].rows != height){
            qDebug() << "Error : all templates must be the same size";
        }

        std::vector<std::vector<cv::Point> > templateContours;
        std::vector<cv::Vec4i> hierarchy;

        findContours(images[i].clone(), templateContours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));

        if (templateContours.size() == 0){
            qDebug() << "Error, template doesn't have a contour";
        }
        else {
            cv::Moments imageMoments = moments(templateContours[0], false);
            massCenters[i] = cv::Point2f(imageMoments.m10/imageMoments.m00 , imageMoments.m01/imageMoments.m00);
        }

        cv::Mat firstHalf = cv::Mat(images[i].clone(), cv::Rect(0, 0, images[i].cols/2, images[i].rows));
        cv::Mat secondHalf = cv::Mat(images[i].clone(), cv::Rect(images[i].cols/2, 0, images[i].cols/2, images[i].rows));

        halfMassCenters[i][0] = getMassCenterFromImage(firstHalf);
        halfMassCenters[i][1] = getMassCenterFromImage(secondHalf);

        cv::Mat firstHalfHori = cv::Mat(images[i].clone(), cv::Rect(0, 0, images[i].cols, images[i].rows/2));
        cv::Mat secondHalfHori = cv::Mat(images[i].clone(), cv::Rect(0, images[i].rows/2, images[i].cols, images[i].rows/2));

        halfMassCentersHori[i][0] = getMassCenterFromImage(firstHalfHori);
        halfMassCentersHori[i][1] = getMassCenterFromImage(secondHalfHori);


        Histogram* hori = new Histogram(width);
        Histogram* verti = new Histogram(height);

        for (int x = 0; x < images[i].cols; x++){
            for (int y = 0; y < images[i].rows; y++){
                hori->add(x, images[i].at<uchar>(y, x)/255.0);
                verti->add(y ,images[i].at<uchar>(y, x)/255.0);
            }
        }

        histoHori[i] = hori;
        histoVerti[i] = verti;
    }
}
int main(int argc, char** argv)
{
long totaltime, intTime, intTime_o, colTime, colTime_o , orTime, orTime_o;
if(argc != 2)
{
	cout << "No image"<<endl;
	return -1;
}
cout<<"Loading Image: ";
cout<< argv[1]<<endl;
Mat inputImage = imread(argv[1], CV_LOAD_IMAGE_COLOR);

if(!inputImage.data)
{
	cout <<"Invalid Image"<<endl;
}

Mat IntensityImg, finalImage;
for(int counter = 0; counter < 1; counter++)
{
totaltime = timestamp();

intTime = timestamp();
IntensityImg = Get_Intensity_Image(inputImage);
vector<Mat> Intensity_Maps = Pyr_CenSur(IntensityImg);
Mat AggInt = aggregateMaps(Intensity_Maps);
normalize(AggInt, AggInt, 0, 255, NORM_MINMAX, -1);
intTime_o = timestamp() - intTime;

colTime = timestamp();
vector<Mat> color_map;
color_map = Normalize_color(inputImage, IntensityImg);
vector<Mat> RGBYMap(6); 
for(int i = 0; i<6; i++)
addWeighted(color_map[i], 0.5, color_map[i+6], 0.5, 0, RGBYMap[i], -1);
Mat AggColor = aggregateMaps(RGBYMap);
normalize(AggColor, AggColor, 0, 255, NORM_MINMAX, -1);
colTime_o = timestamp() - colTime;

orTime = timestamp();
Mat AggOr;
AggOr = getGaborImage(IntensityImg);
normalize(AggOr, AggOr, 0, 255, NORM_MINMAX, -1);
orTime_o = timestamp() - orTime;

finalImage = (AggInt + AggColor + AggOr) /3;
normalize(finalImage, finalImage, 0, 255, NORM_MINMAX, -1);

for(int bCtr = 0; bCtr<4; bCtr++)
{
	pyrUp(finalImage, finalImage);
}

cout <<"Intensity Time: "<< (intTime_o) << "\n";
cout <<"Color Time: "<< (colTime_o) << "\n";
cout <<"Orientation Time: "<< (orTime_o) << "\n";
cout <<"Total Time: "<< (timestamp() - totaltime) << "\n";
}



Mat contImg;
inRange(finalImage, 160, 230, contImg);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;

findContours(contImg, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
for(int i = 0; i>=0; i =hierarchy[i][0])
{
	Scalar color(rand()&255, rand()&255, rand()&255);
	drawContours(inputImage, contours, i, color, 3, 8, hierarchy);
}

imwrite("Salient_Image.jpg" , inputImage);

waitKey(0);
return 0;
}
Exemple #12
0
	int getPegthresholdFromUser(IplImage *img, Gui *gui, string message, int pegThreshVal, Rect r, cv::Mat &fgMaskPeg)
	{
		cv::Mat element[1];
		int count = 0;

		element[0] = getStructuringElement(MORPH_ELLIPSE, Size(8, 8), Point(0, 0));
		
		window_name = gui->windowName();
		cvDestroyWindow(window_name.c_str());
		cvNamedWindow(window_name.c_str(), CV_WINDOW_AUTOSIZE);
		cvMoveWindow(window_name.c_str(), 100, 100);

		img0 = (IplImage *)cvClone(img);
		char TrackbarName[50];
		sprintf(TrackbarName, "thresh x %d", slider_max);

		slider_val = pegThreshVal;
		createTrackbar(TrackbarName, window_name, &slider_val, slider_max, 0);

		

		Mat src, im1, im3;
		src = Mat(img0);

		im1 = Mat::zeros(src.size(), src.type());
		cvtColor(src, im3, CV_BGR2HSV);
		vector<vector<Point> > pegsI;
		while (1)
		{
			pegsI.clear();
			Mat channel[3];
			split(im3, channel);


			//Mat fgMaskRing;
			inRange(channel[2], slider_val, 255, fgMaskPeg);
			// ROI
			for (int y = 0; y < fgMaskPeg.rows; y++)
			{
				for (int x = 0; x < fgMaskPeg.cols; x++)
				{
					if (!(x >= r.tl().x && x <= r.br().x && y >= r.tl().y && y <= r.br().y))
					{
						fgMaskPeg.at<uchar>(Point(x, y)) = 0;
					}
				}
			}
			erode(fgMaskPeg, fgMaskPeg, element[0]);
			dilate(fgMaskPeg, fgMaskPeg, element[0]);
			erode(fgMaskPeg, fgMaskPeg, element[0]);
			dilate(fgMaskPeg, fgMaskPeg, element[0]);

			//p.copyTo(p, fgMaskPeg);
			for (int y = 0; y < src.rows; y++)
			{
				for (int x = 0; x < src.cols; x++)
				{
					if (fgMaskPeg.at<uchar>(Point(x, y)))
					{
						im1.at<Vec3b>(Point(x, y)) = src.at<Vec3b>(Point(x, y));
					}
					else
					{
						im1.at<Vec3b>(Point(x, y)) = Vec3b(0,0,0);
					}
				}
			}

			Mat mask = fgMaskPeg.clone();
			vector<Vec4i> hierarchy_ring;

			//imshow("Initial mask", initial_ring_mask);
			findContours(mask, pegsI, hierarchy_ring, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
			count = pegsI.size();



			cout << "count Pegs->" << count << endl;
			cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, 8);
			putText(im1, message.c_str(), cvPoint(0, 60), CV_FONT_HERSHEY_SIMPLEX, .7, Scalar(255, 255, 0), 1);

			imshow(window_name.c_str(), im1);
			char key = cvWaitKey(40);
			if ((key == '\r' || key == '\n' || key == '\r\n'))
			{
				if (count == 12)
				{
					break;
				}
			}
			count = 0;
		} 
		cvReleaseImage(&img0);
		return slider_val;
	}
std::pair<int, int> GetThresholdedImage(
	cv::Mat& img_BGR, cv::Mat& img_THR,
	int& HueLow, int& HueHigh, int& SatLow, int& SatHigh, int& ValueLow, int& ValueHigh,
	cv::Scalar Color, int *nr_pixels_ptr,
	int HueLow2, int HueHigh2, int SatLow2, int SatHigh2, int ValueLow2, int ValueHigh2)
{
	std::cout << "GetThresholdedImage starting" << std::endl;
	cv::RNG rng(12345);
	// Convert the image into an HSV image
	cv::Mat img_HSV; cv::cvtColor(img_BGR, img_HSV, CV_BGR2HSV);

	if (manual)
	{
		cv::inRange(img_HSV, cv::Scalar(lowerH, lowerS, lowerV),
		            cv::Scalar(upperH, upperS, upperV), img_THR);
	}
	else
	{
		cv::Mat img_THR1;
		cv::Mat img_THR2;
		cv::inRange(img_HSV, cv::Scalar(HueLow, SatLow, ValueLow),
		            cv::Scalar(HueHigh, SatHigh, ValueHigh), img_THR1);

		if (HueLow2 != -1   &&
		    HueHigh2 != -1  &&
		    SatLow2 != -1   &&
		    SatHigh2 != -1  &&
		    ValueLow2 != -1 &&
		    ValueHigh2 != -1)
		{
			// Optional arguments for second thresholds are set
			cv::inRange(img_HSV, cv::Scalar(HueLow2, SatLow2, ValueLow2),
			            cv::Scalar(HueHigh2, SatHigh2, ValueHigh2), img_THR2);
			cv::bitwise_or(img_THR1, img_THR2, img_THR);
		}
		else
		{
			img_THR = img_THR1;
		}
	}

	int kernel_size = 5;
	cv::Mat kernel = cv::Mat::ones( kernel_size, kernel_size, CV_32F ) / (float)(kernel_size * kernel_size);
	cv::dilate(img_THR, img_THR, kernel, cv::Point(-1,-1), 3, cv::BORDER_CONSTANT, cv::morphologyDefaultBorderValue());
	cv::erode (img_THR, img_THR, kernel, cv::Point(-1,-1), 4, cv::BORDER_CONSTANT, cv::morphologyDefaultBorderValue());
	// cv::floodFill(img_THR, cv::Point(0, 0), cv::Scalar(0), NULL, cv::Scalar(20), cv::Scalar(20), 4);

	// Detect edges using canny
	cv::Mat canny_output; int thresh = 100;
	cv::Canny(img_THR, canny_output, thresh, thresh * 2, 3);
	// Find contours
	std::vector<std::vector<cv::Point> > contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
	// Aproximate contours
	std::vector<std::vector<cv::Point> > approxContours;
	approxContours.resize(contours.size());
	// Draw contours
	for (unsigned int i = 0; i < contours.size(); i++)
	{
		cv::Scalar color(rand()&255, rand()&255, rand()&255);
		// cv::drawContours(img_BGR, contours, i, color, CV_FILLED, 8, hierarchy );
		cv::drawContours(img_THR, contours, i,   255, CV_FILLED, 8, hierarchy );
	}
	cv::medianBlur(img_THR, img_THR, 5);

	// Blur image
	cv::GaussianBlur(img_THR, img_THR, cv::Size(7,7), 15000, 15000, cv::BORDER_DEFAULT);

	// Detect edges using Threshold
	cv::threshold(img_THR, img_THR, 100, 250, cv::THRESH_BINARY);

	// Find contours
	findContours(img_THR, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));

	// Find the convex hull object for each contour
	std::vector<std::vector<cv::Point> > hull(contours.size());
	for(unsigned int i = 0; i < contours.size(); i++)
	{
		convexHull(cv::Mat(contours[i]), hull[i], false);
	}

	// Draw contours + hull results
	for(unsigned int i = 0; i< contours.size(); i++)
	{
		cv::Scalar color = cv::Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255));
		drawContours(img_BGR, contours, i, color, 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());
		drawContours(img_THR,     hull, i, color, 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());
	}

	// for (unsigned int i = 0; i < contours.size(); i++)
	// {
	// 	approxPolyDP(cv::Mat(contours[i]), approxContours[i], 4, 1);
	// 	drawContours(img_BGR, contours      , i, CV_RGB(rand()&255, rand()&255, rand()&255) );
	// 	// drawContours(img_BGR, approxContours, i, CV_RGB(rand()&255, rand()&255, rand()&255) );
	// }

	// cv::Mat draw_contour = cv::Mat::zeros(canny_output.size(), CV_8UC3);
	// for (unsigned int i = 0; i < contours.size(); i++)
	// {
	// 	cv::Scalar color = cv::Scalar(rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255));
	// 	cv::drawContours(img_BGR, contours, i, color, 2, 8, hierarchy, 0, cv::Point());
	// }

	// Detect blobs
	std::vector<cv::KeyPoint> keyPoints;
	blobDetector->detect(img_THR, keyPoints);
	// Draw keypoints
	cv::drawKeypoints(img_BGR, keyPoints, img_BGR,
	                  CV_RGB(rand()&255, rand()&255, rand()&255),
	                  cv::DrawMatchesFlags::DEFAULT);

	float X_obj = 0; float Y_obj = 0;

	std::cout << "*Keypoints " << keyPoints.size() << "  *Contours  " << contours.size()  << std::endl;
	for (unsigned int i = 0; i < keyPoints.size(); i++) // check the logic of this for loop
	{
		float X = keyPoints[i].pt.x;
		float Y = keyPoints[i].pt.y;
		float R = keyPoints[i].size;
		int intR = (int)R;
		if (intR > *nr_pixels_ptr) *nr_pixels_ptr = intR;
		circle(img_BGR, cv::Point(X, Y), R + 5, Color, 8, 0);
		X_obj += X; Y_obj += Y;
		std::cout << "  i: " << i << "  (X -|- Y) : (" << X << " -|- " << Y << ") Radius: " << R << std::endl;
	}
	X_obj /= keyPoints.size();
	Y_obj /= keyPoints.size();

	std::pair<int, int> return_value(-1, -1);

	if (keyPoints.size() != 0)
	{
		X_obj_old = X_obj; Y_obj_old = Y_obj;
		return_value.first = X_obj;
		return_value.second = Y_obj;
		circle(img_BGR, cv::Point(X_obj, Y_obj), 5, CV_RGB(255,255,255), 4, 8, 0);
	}
	else
	{
		std::cout << "******************** NO BLOBS FOUND ********************" << std::endl;
		circle(img_BGR, cv::Point(X_obj_old, Y_obj_old), 5, CV_RGB(255,255,255), 4, 8, 0);
	}

	// std::cout << "Reached end of GetThresholdedImage" << std::endl;

	// sleep(5);

	return return_value;
}
Exemple #14
0
void VisionNode::CameraCallback(CCamera *cam, const void *buffer, int buffer_length) {
    cv::Mat myuv(HEIGHT + HEIGHT / 2, WIDTH, CV_8UC1, (unsigned char *) buffer);
    cv::cvtColor(myuv, img, CV_YUV2RGBA_NV21);
    cv::cvtColor(img, img_gray, CV_RGBA2GRAY);

    communication::MarkerPosition markerPosition;
    markerPosition.header.stamp = ros::Time::now();
    static uint next_id = 0;
    markerPosition.header.seq = next_id++;
    markerPosition.cameraID = ID;

    static uint counter = 0;
    t2 = std::chrono::high_resolution_clock::now();
    time_span = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
    markerPosition.fps = (double)counter/time_span.count();
    counter++;

    if(time_span.count()>30){ // reset every 30 seconds
        counter = 0;
        t1 = std::chrono::high_resolution_clock::now();
        std_msgs::Int32 msg;
        msg.data = ID;
        cameraID_pub->publish(msg);
    }

    cv::Mat filtered_img;
    cv::threshold(img_gray, filtered_img, threshold_value, 255, 3);

    // find contours in result, which hopefully correspond to a found object
    vector <vector<cv::Point>> contours;
    vector <cv::Vec4i> hierarchy;
    findContours(filtered_img, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE,
                 cv::Point(0, 0));

    // filter out tiny useless contours
    double min_contour_area = 10;
    for (auto it = contours.begin(); it != contours.end();) {
        if (contourArea(*it) < min_contour_area) {
            it = contours.erase(it);
        }
        else {
            ++it;
        }
    }

    // publish the markerPositions
    vector<cv::Point2f> centers(contours.size());
    vector<float> radius(contours.size());
    for (int idx = 0; idx < contours.size(); idx++) {
        minEnclosingCircle(contours[idx], centers[idx], radius[idx]);
        communication::Vector2 pos;
        pos.x = WIDTH - centers[idx].x;
        pos.y = centers[idx].y;
        markerPosition.marker_position.push_back(pos);
    }
    //imshow("camera", img);
    //waitKey(1);
    markerPosition.markerVisible=contours.size();
    marker_position_pub->publish(markerPosition);

    if(publish_video_flag && counter%3==0){
        // get centers and publish
        for (int idx = 0; idx < contours.size(); idx++) {
            drawContours(img_gray, contours, idx, cv::Scalar(0, 0, 0), 4, 8, hierarchy, 0,
                         cv::Point());
        }
        cv_bridge::CvImage cvImage;
        img_gray.copyTo(cvImage.image);
        sensor_msgs::Image msg;
        cvImage.toImageMsg(msg);
        msg.encoding = "mono8";
       	msg.header = markerPosition.header;
        video_pub->publish(msg);
   }
}
std::vector<int> LightplaneCalibrator::AddLightImage(
    std::vector<cv::Mat>& srcs_light) {

  std::vector<int> return_value;
  std::vector<cv::Point>::iterator begin_100, end_900, itr;
  ims_points_.clear();
  for (int i = 0; i < srcs_light.size(); i++) {
    std::vector<cv::Point> pts; std::vector<cv::Point2f> ptfs;
    cv::Mat im = srcs_light[i], gray;
    if (im.channels() == 3) {
      cvtColor(im, gray, CV_BGR2GRAY);
    }
    else {
      gray = im;
    }
    cam_->UndistorImage(gray, gray);
    medianBlur(gray, gray, 11);
    cv::Mat threshold_out;
    cv::threshold(gray, threshold_out, 25, 255, CV_THRESH_BINARY);
    cv::Mat dialateStructure = cv::getStructuringElement(
      cv::MorphShapes::MORPH_RECT, cv::Size(15, 15));

    dilate(threshold_out, threshold_out, dialateStructure, cv::Point(-1, -1));
#ifdef _DEBUG_JIANG_  // for debug
    cv::namedWindow("threshold_medianBlur_out");
    cv::imshow("threshold_medianBlur_out", threshold_out);
    /*imwrite("threshold_medianBlur_out.bmp",threshold_out);*/
    cv::waitKey(200);
#endif
    std::vector<std::vector<cv::Point> > contours;
    std::vector<cv::Vec4i> hierarchy;
    findContours(threshold_out, contours, hierarchy, CV_RETR_EXTERNAL,
      CV_CHAIN_APPROX_NONE, cv::Point(0, 0));

    /// Draw contours
    cv::Mat drawing = cv::Mat::zeros(threshold_out.size(), CV_8U);
    for (size_t i = 0; i < contours.size(); i++) {
      if (contours[i].size() > 200) {
        //Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
        drawContours(drawing, contours, (int)i, cv::Scalar(255),
          CV_FILLED, 8, hierarchy, 0, cv::Point());

      }
    }
    cv::Mat  thining_output;
    Thinning(drawing, thining_output);
#ifdef _DEBUG_JIANG_
    cv::imshow("thining_output", thining_output);
    cv::waitKey(200);
#endif
    findNonZero(thining_output, pts);
    for (itr = pts.begin(); itr != pts.end(); ++itr) {
      if ((*itr).y <= 100) {
        begin_100 = itr;
      }
      if ((*itr).y <= 900) {
        end_900 = itr;
      }
    }
    ptfs.assign(begin_100, end_900);
    ims_points_.push_back(ptfs);
  }
  //std::ofstream log;
  //log.open("ims_points.txt");
  //for (int i = 0; i < ims_points_.size(); i++) {
  //  for (int j = 0; j < ims_points_[i].size(); j++) {
  //    log << ims_points_[i][j].x << " " << ims_points_[i][j].y << " " << i + 1 
  //        << std::endl;

  //  }
  //  log << std::endl;
  //}
  return return_value;
}
Exemple #16
0
//! 字符分割与排序
int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec) {

  if (!input.data) return 0x01;

  int w = input.cols;
  int h = input.rows;

  Mat tmpMat = input(Rect_<double>(w * 0.1, h * 0.1, w * 0.8, h * 0.8));

  // 判断车牌颜色以此确认threshold方法
  Color plateType = getPlateType(tmpMat, true);

  Mat input_grey;
  cvtColor(input, input_grey, CV_BGR2GRAY);

  Mat img_threshold;

  // 二值化
  // 根据车牌的不同颜色使用不同的阈值判断方法
  // TODO:使用MSER来提取这些轮廓
  if (BLUE == plateType) {
    // cout << "BLUE" << endl;
    img_threshold = input_grey.clone();

    int w = input_grey.cols;
    int h = input_grey.rows;
    Mat tmp = input_grey(Rect_<double>(w * 0.1, h * 0.1, w * 0.8, h * 0.8));
    int threadHoldV = ThresholdOtsu(tmp);
    // utils::imwrite("E:/img_inputgray2.jpg", input_grey);

    threshold(input_grey, img_threshold, threadHoldV, 255, CV_THRESH_BINARY);
    // utils::imwrite("E:/img_threshold.jpg", img_threshold);

    // threshold(input_grey, img_threshold, 5, 255, CV_THRESH_OTSU +
    // CV_THRESH_BINARY);

  } else if (YELLOW == plateType) {
    // cout << "YELLOW" << endl;
    img_threshold = input_grey.clone();
    int w = input_grey.cols;
    int h = input_grey.rows;
    Mat tmp = input_grey(Rect_<double>(w * 0.1, h * 0.1, w * 0.8, h * 0.8));
    int threadHoldV = ThresholdOtsu(tmp);
    utils::imwrite("resources/image/tmp/inputgray2.jpg", input_grey);

    threshold(input_grey, img_threshold, threadHoldV, 255,
              CV_THRESH_BINARY_INV);

    // threshold(input_grey, img_threshold, 10, 255, CV_THRESH_OTSU +
    // CV_THRESH_BINARY_INV);
  } else if (WHITE == plateType) {
    // cout << "WHITE" << endl;
    /*img_threshold = input_grey.clone();
    int w = input_grey.cols;
    int h = input_grey.rows;
    Mat tmp = input_grey(Rect(w*0.1, h*0.1, w*0.8, h*0.8));
    int threadHoldV = ThresholdOtsu(tmp);
    utils::imwrite("resources/image/tmp/inputgray2.jpg", input_grey);*/

    threshold(input_grey, img_threshold, 10, 255,
              CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
  } else {
    // cout << "UNKNOWN" << endl;
    threshold(input_grey, img_threshold, 10, 255,
              CV_THRESH_OTSU + CV_THRESH_BINARY);
  }

  if (0) {
    imshow("threshold", img_threshold);
    waitKey(0);
    destroyWindow("threshold");
  }

  if (m_debug) {
    stringstream ss(stringstream::in | stringstream::out);
    ss << "resources/image/tmp/debug_char_threshold" << iTag << ".jpg";
    utils::imwrite(ss.str(), img_threshold);
  }

  // 去除车牌上方的柳钉以及下方的横线等干扰
  // 并且也判断了是否是车牌
  // 并且在此对字符的跳变次数以及字符颜色所占的比重做了是否是车牌的判别条件
  // 如果不是车牌,返回ErrorCode=0x02
  if (!clearLiuDing(img_threshold)) return 0x02;

  if (m_debug) {
    stringstream ss(stringstream::in | stringstream::out);
    ss << "resources/image/tmp/debug_char_clearLiuDing" << iTag << ".jpg";
    utils::imwrite(ss.str(), img_threshold);
  }
  iTag++;

  // 在二值化图像中提取轮廓
  Mat img_contours;
  img_threshold.copyTo(img_contours);

  vector<vector<Point> > contours;
  findContours(img_contours,
               contours,               // a vector of contours
               CV_RETR_EXTERNAL,       // retrieve the external contours
               CV_CHAIN_APPROX_NONE);  // all pixels of each contours

  vector<vector<Point> >::iterator itc = contours.begin();
  vector<Rect> vecRect;

  // 将不符合特定尺寸的字符块排除出去
  while (itc != contours.end()) {
    Rect mr = boundingRect(Mat(*itc));
    Mat auxRoi(img_threshold, mr);

    if (verifyCharSizes(auxRoi)) vecRect.push_back(mr);
    ++itc;
  }

  // 如果找不到任何字符块,则返回ErrorCode=0x03
  if (vecRect.size() == 0) return 0x03;

  // 对符合尺寸的图块按照从左到右进行排序;
  // 直接使用stl的sort方法,更有效率
  vector<Rect> sortedRect(vecRect);
  std::sort(sortedRect.begin(), sortedRect.end(),[](const Rect& r1, const Rect& r2) { return r1.x < r2.x; });

  size_t specIndex = 0;

  //获得特殊字符对应的Rectt,如苏A的"A"
  specIndex = GetSpecificRect(sortedRect);

  if (m_debug) {
    if (specIndex < sortedRect.size()) {
      Mat specMat(img_threshold, sortedRect[specIndex]);
      stringstream ss(stringstream::in | stringstream::out);
      ss << "resources/image/tmp/debug_specMat"
         << ".jpg";
      utils::imwrite(ss.str(), specMat);
    }
  }

  //根据特定Rect向左反推出中文字符
  //这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect,因此仅能
  //退过特定算法来指定
  Rect chineseRect;
  if (specIndex < sortedRect.size())
    chineseRect = GetChineseRect(sortedRect[specIndex]);
  else
    return -3;

  if (m_debug) {
    Mat chineseMat(img_threshold, chineseRect);
    stringstream ss(stringstream::in | stringstream::out);
    ss << "resources/image/tmp/debug_chineseMat"
       << ".jpg";
    utils::imwrite(ss.str(), chineseMat);
  }

  //新建一个全新的排序Rect
  //将中文字符Rect第一个加进来,因为它肯定是最左边的
  //其余的Rect只按照顺序去6个,车牌只可能是7个字符!这样可以避免阴影导致的“1”字符
  vector<Rect> newSortedRect;
  newSortedRect.push_back(chineseRect);
  RebuildRect(sortedRect, newSortedRect, specIndex);

  if (newSortedRect.size() == 0) return -3;

  for (size_t i = 0; i < newSortedRect.size(); i++) {
    Rect mr = newSortedRect[i];
    Mat auxRoi(img_threshold, mr);

    if (1) {
      auxRoi = preprocessChar(auxRoi);
      if (m_debug) {
        stringstream ss(stringstream::in | stringstream::out);
        ss << "resources/image/tmp/debug_char_auxRoi_" << (i + staticIndex)
           << ".jpg";
        utils::imwrite(ss.str(), auxRoi);
      }
      resultVec.push_back(auxRoi);
    }
  }
  staticIndex += newSortedRect.size();

  return 0;
}
	std::vector<std::vector<std::vector<cv::Point>>> MultiContourObjectDetector::findApproxContours(
		cv::Mat image,
		bool performOpening,
		bool findBaseShape)
	{

		// CREATE ACTIVE ZONE 80% AND 50% ---------------------

		Point centre(image.size().width / 2, image.size().height / 2);

		int deleteHeight = image.size().height * _deleteFocus;
		int deleteWidth = image.size().width * _deleteFocus;
		int deleteX = centre.x - deleteWidth / 2;
		int deleteY = centre.y - deleteHeight / 2;

		int attenuationHeight = image.size().height * _attenuationFocus;
		int attenuationWidth = image.size().width * _attenuationFocus;
		int attenuationX = centre.x - attenuationWidth / 2;
		int attenuationY = centre.y - attenuationHeight / 2;

		Rect erase(deleteX, deleteY, deleteWidth, deleteHeight);
		_deleteRect = erase;

		Rect ease(attenuationX, attenuationY, attenuationWidth, attenuationHeight);
		_attenuationRect = ease;
		// ----------------------------------------

		bool imageTooBig = false;

		Mat newImage;

		if (image.size().height <= 400 || image.size().width <= 400)
		{
			Mat pickColor = image(Rect((image.size().width / 2) - 1, image.size().height - 2, 2, 2));
			Scalar color = mean(pickColor);

			int increment = 2;
			newImage = Mat(Size(image.size().width + increment, image.size().height + increment), image.type());
			newImage = color;

			Point nc(newImage.size().width / 2, newImage.size().height / 2);
			int incH = image.size().height;
			int incW = image.size().width;
			int incX = nc.x - incW / 2;
			int incY = nc.y - incH / 2;

			image.copyTo(newImage(Rect(incX, incY, incW, incH)));
		}
		else
		{
			imageTooBig = true;
			newImage = image;
		}

		Size imgSize = newImage.size();
		Mat gray(imgSize, CV_8UC1);
		Mat thresh(imgSize, CV_8UC1);

		if (newImage.channels() >= 3)
			cvtColor(newImage, gray, CV_BGR2GRAY);
		else
			newImage.copyTo(gray);

		int minThreshold;

		if (performOpening)
		{
			// PERFORM OPENING (Erosion --> Dilation)

			int erosion_size = 3;
			int dilation_size = 3;

			if (imageTooBig)
			{
				erosion_size = 5;
				dilation_size = 5;
			}

			Mat element = getStructuringElement(0, Size(2 * erosion_size, 2 * erosion_size), Point(erosion_size, erosion_size));
			erode(gray, gray, element);
			dilate(gray, gray, element);

			minThreshold = mean(gray)[0];

			if (minThreshold < 90)
				minThreshold = 60;
			else if (minThreshold >= 90 && minThreshold < 125)
				minThreshold = 100;
		}


		threshold(gray, thresh, minThreshold, 255, THRESH_BINARY);

#ifdef DEBUG_MODE
		imshow("Threshold", thresh);
#endif

		vector<vector<Point>> contours;
		vector<Vec4i> hierarchy;
		vector<Point> hull, approx;

		map<int, vector<vector<Point>>> hierachedContours;
		map<int, vector<vector<Point>>> approxHContours;

		findContours(thresh, contours, hierarchy, CV_RETR_TREE, CHAIN_APPROX_NONE);


#ifdef DEBUG_MODE
		Mat tempI(image.size(), CV_8UC1);
		tempI = Scalar(0);
		drawContours(tempI, contours, -1, cv::Scalar(255), 1, CV_AA);

		imshow("Contours", tempI);
#endif


		vector<vector<Point>> temp;

		// CATALOG BY HIERARCHY LOOP
		for (int i = 0; i < contours.size(); i++)
		{

#ifdef DEBUG_MODE
			tempI = Scalar(0);
			temp.clear();
			temp.push_back(contours[i]);
			drawContours(tempI, temp, -1, cv::Scalar(255), 1, CV_AA);
#endif
			int parent = hierarchy[i][3];
			if (parent == -1)
			{
				if (hierachedContours.count(i) == 0)
				{
					// me not found

					hierachedContours.insert(pair<int, vector<vector<Point>>>(i, vector<vector<Point>>()));
					hierachedContours[i].push_back(contours[i]);
				}
				else
				{
					// me found
					continue;
				}
			}
			else
			{
				if (hierachedContours.count(parent) == 0)
				{
					// dad not found
					hierachedContours.insert(pair<int, vector<vector<Point>>>(parent, vector<vector<Point>>()));
					hierachedContours[parent].push_back(contours[parent]);
				}
				hierachedContours[parent].push_back(contours[i]);
			}
		}


		int minPoint, maxPoint;
		minPoint = _minContourPoints - _minContourPoints / 2.1;
		maxPoint = _minContourPoints + _minContourPoints / 1.5;


		// APPROX LOOP

		for (map<int, vector<vector<Point>>>::iterator it = hierachedContours.begin(); it != hierachedContours.end(); it++)
		{

			if (it->second[0].size() < 400)
				continue;

#ifdef DEBUG_MODE
			tempI = Scalar(0);
			drawContours(tempI, it->second, -1, cv::Scalar(255), 1, CV_AA);
#endif

			if (it == hierachedContours.begin() && it->second.size() < _aspectedContours)
				continue;

			for (int k = 0; k < it->second.size(); k++)
			{
				if (it->second[k].size() < _minContourPoints)
				{
					if (k == 0) // padre
						break;
					else        // figlio
						continue;
				}

				convexHull(it->second[k], hull, false);

				double epsilon = it->second[k].size() * 0.003;
				approxPolyDP(it->second[k], approx, epsilon, true);

#ifdef DEBUG_MODE			
				tempI = Scalar(0);
				vector<vector<Point>> temp;
				temp.push_back(approx);
				drawContours(tempI, temp, -1, cv::Scalar(255), 1, CV_AA);
#endif

				// REMOVE TOO EXTERNAL SHAPES -------------

				if (imageTooBig)
				{
					Rect bounding = boundingRect(it->second[k]);

#ifdef DEBUG_MODE
					rectangle(tempI, _deleteRect, Scalar(255));
					rectangle(tempI, bounding, Scalar(255));
#endif

					bool isInternal = bounding.x > _deleteRect.x &&
						bounding.y > _deleteRect.y &&
						bounding.x + bounding.width < _deleteRect.x + _deleteRect.width &&
						bounding.y + bounding.height < _deleteRect.y + _deleteRect.height;


					if (!isInternal)
					{
						if (k == 0)
							break;
					}
				}

				// --------------------------------------------------

				if (!findBaseShape)
				{
					if (hull.size() < minPoint || hull.size() > maxPoint)
					{
						if (k == 0) // padre
							break;
						else        // figlio
							continue;
					}

				}


				if (k == 0)
				{
					approxHContours.insert(pair<int, vector<vector<Point>>>(it->first, vector<vector<Point>>()));
					approxHContours.at(it->first).push_back(approx);
				}
				else
				{
					approxHContours[it->first].push_back(approx);
				}
			}
		}

		int maxSize = 0,
			maxID = 0;

		vector<vector<vector<Point>>> lookupVector;
		for (map<int, vector<vector<Point>>>::iterator it = approxHContours.begin(); it != approxHContours.end(); it++)
		{
			if (it->second.size() <= 1)
				continue;

			if (findBaseShape)
			{
				int totSize = 0;
				for (int k = 0; k < it->second.size(); k++)
				{
					totSize += it->second[k].size();
				}

				if (totSize > maxSize)
				{
					maxSize = totSize;
					maxID = it->first;
				}
			}
			else
			{
				lookupVector.push_back(it->second);
			}

		}

		if (findBaseShape)
		{
			lookupVector.push_back(approxHContours.at(maxID));
		}

		return lookupVector;
	}
Exemple #18
0
vector<Rect> visionUtils::segmentLineBoxFit(Mat img0, int minPixelSize, int maxSegments, Mat *returnMask, std::vector<std::vector<cv::Point> > *returnContours, vector<RotatedRect> *rotatedBoundingBox, bool displayFaces)
{
    // Segments items in gray image (img0)
    // minPixelSize= pixels, threshold for removing smaller regions, with less than minPixelSize pixels
    // 0, returns all detected segments
    // maxSegments = max no segments to return, 0 = all
    RNG rng(12345);


    int padPixels=15;
    // Rect border added at start...
    Rect tempRect;
    tempRect.x=padPixels;
    tempRect.y=padPixels;
    tempRect.width=img0.cols;
    tempRect.height=img0.rows;
    Mat img1 = Mat::zeros(img0.rows+(padPixels*2), img0.cols+(padPixels*2), CV_8UC1);
    img0.copyTo(img1(tempRect));

    // find the contours
    std::vector<std::vector<cv::Point> > contours;
    vector<Vec4i> hierarchy;

    findContours(img1, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

    // Mask for segmented region
    Mat mask = Mat::zeros(img1.rows, img1.cols, CV_8UC3);

    vector<double> areas(contours.size());

    // Case for using minimum pixel size
    Vec4f lines;
    Scalar color;

    // sort contours
    std::sort(contours.begin(), contours.end(), compareContourAreas);

    // grab contours
    vector<Rect> boundingBox;

    // LB testing
    vector<RotatedRect> tempRotatedBoundingBox;

    std::vector<std::vector<cv::Point> > tempReturnContours;
    int maxIterations = 0;

    if( contours.size() > 0 )
    {
        if (maxSegments==0)// return all contours..
            maxIterations = contours.size();
        else if((int)contours.size() >= maxSegments)
            maxIterations = maxSegments;
        else
            maxIterations = 1;    // LB: need to check this is correct!
        int contourCount=0;

        for (int j = 1; j < maxIterations+1; j++)
        {
            int i = contours.size()-j;
            if (contourArea(Mat(contours[i]))>minPixelSize)
            {
                // Fit rotated rect to contour
                tempRotatedBoundingBox.push_back(minAreaRect( Mat(contours[i]) ));

                Point2f rectCentre=tempRotatedBoundingBox[contourCount].center;
                rectCentre.x=rectCentre.x-padPixels;
                rectCentre.y=rectCentre.y-padPixels;
                tempRotatedBoundingBox[contourCount].center=rectCentre;

                // Find line limits....
                boundingBox.push_back(boundingRect(Mat(contours[i])));

                // Remove edge padding effects....
                boundingBox[contourCount].x=boundingBox[contourCount].x-padPixels;
                boundingBox[contourCount].y=boundingBox[contourCount].y-padPixels;
                boundingBox[contourCount]=checkRoiInImage(img0, boundingBox[contourCount]);

                contourCount++;

                tempReturnContours.push_back(contours[i]);
            }
        }
        // Return contours
        returnContours->resize(tempReturnContours.size());
        *returnContours = tempReturnContours;
        // Return rotated rects
        rotatedBoundingBox->resize(tempRotatedBoundingBox.size());
        *rotatedBoundingBox = tempRotatedBoundingBox;

        // normalize so imwrite(...)/imshow(...) shows the mask correctly!
        cv::normalize(mask.clone(), mask, 0.0, 255.0, CV_MINMAX, CV_8UC1);
        // To Remove border added at start...
        *returnMask=mask(tempRect);
        // show the images
        if (displayFaces)   imshow("Seg line utils: Img in", img0);
        if (displayFaces)   imshow("Seg line utils: Mask", *returnMask);
        if (displayFaces)   imshow("Seg line utils: Output", img1);
    }
    return boundingBox;
}
Exemple #19
0
// Gets the hue/sat/val for areas that we believe are license plate characters
// Then uses that to filter the whole image and provide a mask.
void ColorFilter::findCharColors()
{
  int MINIMUM_SATURATION = 45;
  
  if (this->debug)
    cout << "ColorFilter::findCharColors" << endl;
  
  //charMask.copyTo(this->colorMask);
  this->colorMask = Mat::zeros(charMask.size(), CV_8U);
  bitwise_not(this->colorMask, this->colorMask);
  
  Mat erodedCharMask(charMask.size(), CV_8U);
  Mat element = getStructuringElement( 1,
				  Size( 2 + 1, 2+1 ),
				  Point( 1, 1 ) );
  erode(charMask, erodedCharMask, element);

  vector<vector<Point> > contours;
  vector<Vec4i> hierarchy;
  findContours(erodedCharMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

    
  
  vector<float> hMeans, sMeans, vMeans;
  vector<float> hStdDevs, sStdDevs, vStdDevs;
      
  for (int i = 0; i < contours.size(); i++)
  {
    if (hierarchy[i][3] != -1)
      continue;
      
      Mat singleCharMask = Mat::zeros(hsv.size(), CV_8U);
      
      drawContours(singleCharMask, contours,
	  i, // draw this contour
	  cv::Scalar(255,255,255), // in 
	  CV_FILLED, 
	  8, 
	  hierarchy
      ); 
      
      // get rid of the outline by drawing a 1 pixel width black line
      drawContours(singleCharMask, contours,
	  i, // draw this contour
	  cv::Scalar(0,0,0), // in 
	  1, 
	  8, 
	  hierarchy
      ); 
      
      
	  
      
      //drawAndWait(&singleCharMask);

      Scalar mean;
      Scalar stddev;
      meanStdDev(hsv, mean, stddev, singleCharMask);
      
      if (this->debug)
      {
	cout << "ColorFilter " << setw(3) << i << ". Mean:  h: " << setw(7) << mean[0] << " s: " << setw(7) <<mean[1] << " v: " << setw(7) << mean[2] 
			      << " | Std: h: " << setw(7) <<stddev[0] << " s: " << setw(7) <<stddev[1] << " v: " << stddev[2] << endl;
      }

      if (mean[0] == 0 && mean[1] == 0 && mean[2] == 0)
	continue;
			    
      hMeans.push_back(mean[0]);
      sMeans.push_back(mean[1]);
      vMeans.push_back(mean[2]);
      hStdDevs.push_back(stddev[0]);
      sStdDevs.push_back(stddev[1]);
      vStdDevs.push_back(stddev[2]);
      

  }
  
  if (hMeans.size() == 0)
    return;
  
  int bestHueIndex = this->getMajorityOpinion(hMeans, .65, 30);
  int bestSatIndex = this->getMajorityOpinion(sMeans, .65, 35);
  int bestValIndex = this->getMajorityOpinion(vMeans, .65, 30);
  
  
  if (sMeans[bestSatIndex] < MINIMUM_SATURATION)
    return;
  
  
  bool doHueFilter = false, doSatFilter = false, doValFilter = false;
  float hueMin, hueMax;
  float satMin, satMax;
  float valMin, valMax;
  
  if (this->debug)
    cout << "ColorFilter Winning indices:" << endl;
  if (bestHueIndex != -1)
  {
    doHueFilter = true;
    hueMin = hMeans[bestHueIndex] - (2 * hStdDevs[bestHueIndex]);
    hueMax = hMeans[bestHueIndex] + (2 * hStdDevs[bestHueIndex]);
    
    if (abs(hueMin - hueMax) < 20)
    {
      hueMin = hMeans[bestHueIndex] - 20;
      hueMax = hMeans[bestHueIndex] + 20;
    }
    
    if (hueMin < 0)
      hueMin = 0;
    if (hueMax > 180)
      hueMax = 180;
    
    if (this->debug)
      cout << "ColorFilter Hue: " << bestHueIndex << " : " << setw(7) << hMeans[bestHueIndex] << " -- " << hueMin << "-" << hueMax << endl;
  }
  if (bestSatIndex != -1)
  {
    doSatFilter = true;
    
    satMin = sMeans[bestSatIndex] - (2 * sStdDevs[bestSatIndex]);
    satMax = sMeans[bestSatIndex] + (2 * sStdDevs[bestSatIndex]);
    
    if (abs(satMin - satMax) < 20)
    {
      satMin = sMeans[bestSatIndex] - 20;
      satMax = sMeans[bestSatIndex] + 20;
    }
    
    if (satMin < 0)
      satMin = 0;
    if (satMax > 255)
      satMax = 255;
    
    if (this->debug)
      cout << "ColorFilter Sat: " << bestSatIndex << " : " << setw(7) << sMeans[bestSatIndex] << " -- " << satMin << "-" << satMax << endl;
  }
  if (bestValIndex != -1)
  {
    doValFilter = true;
    
    valMin = vMeans[bestValIndex] - (1.5 * vStdDevs[bestValIndex]);
    valMax = vMeans[bestValIndex] + (1.5 * vStdDevs[bestValIndex]);
    
    if (abs(valMin - valMax) < 20)
    {
      valMin = vMeans[bestValIndex] - 20;
      valMax = vMeans[bestValIndex] + 20;
    }
    
    if (valMin < 0)
      valMin = 0;
    if (valMax > 255)
      valMax = 255;
    
    if (this->debug)
      cout << "ColorFilter Val: " << bestValIndex << " : " << setw(7) << vMeans[bestValIndex] << " -- " << valMin << "-" << valMax  << endl;
  }
  


  Mat imgDebugHueOnly = Mat::zeros(hsv.size(), hsv.type());
  Mat imgDebug = Mat::zeros(hsv.size(), hsv.type());
  Mat imgDistanceFromCenter = Mat::zeros(hsv.size(), CV_8U);
  Mat debugMask = Mat::zeros(hsv.size(), CV_8U);
  bitwise_not(debugMask, debugMask);
  
  for (int row = 0; row < charMask.rows; row++)
  {
    for (int col = 0; col < charMask.cols; col++)
    {
      int h = (int) hsv.at<Vec3b>(row, col)[0];
      int s = (int) hsv.at<Vec3b>(row, col)[1];
      int v = (int) hsv.at<Vec3b>(row, col)[2];
      
      bool hPasses = true;
      bool sPasses = true;
      bool vPasses = true;

      int vDistance = abs(v - vMeans[bestValIndex]);
      
      imgDebugHueOnly.at<Vec3b>(row, col)[0] = h;
      imgDebugHueOnly.at<Vec3b>(row, col)[1] = 255;
      imgDebugHueOnly.at<Vec3b>(row, col)[2] = 255;
      
      imgDebug.at<Vec3b>(row, col)[0] = 255;
      imgDebug.at<Vec3b>(row, col)[1] = 255;
      imgDebug.at<Vec3b>(row, col)[2] = 255;
      
      if (doHueFilter && (h < hueMin || h > hueMax))
      {
	hPasses = false;
	imgDebug.at<Vec3b>(row, col)[0] = 0;
	debugMask.at<uchar>(row, col) = 0;
      }
      if (doSatFilter && (s < satMin || s > satMax))
      {
	sPasses = false;
	imgDebug.at<Vec3b>(row, col)[1] = 0;
      }
      if (doValFilter && (v < valMin || v > valMax))
      {
	vPasses = false;
	imgDebug.at<Vec3b>(row, col)[2] = 0;
      }
      
      //if (pixelPasses)
      //  colorMask.at<uchar>(row, col) = 255;
      //else
      //imgDebug.at<Vec3b>(row, col)[0] = hPasses & 255;
      //imgDebug.at<Vec3b>(row, col)[1] = sPasses & 255;
      //imgDebug.at<Vec3b>(row, col)[2] = vPasses & 255;
      
      if ((hPasses) ||  (hPasses && sPasses))//(hPasses && vPasses) || (sPasses && vPasses) ||
	this->colorMask.at<uchar>(row, col) = 255;
      else
	this->colorMask.at<uchar>(row, col) = 0;
      
      
      if ((hPasses && sPasses) || (hPasses && vPasses) || (sPasses && vPasses))
      {
	vDistance = pow(vDistance, 0.9);
      }
      else
      {
	vDistance = pow(vDistance, 1.1);
      }
      if (vDistance > 255)
	vDistance = 255;
      imgDistanceFromCenter.at<uchar>(row, col) = vDistance;
    }
  }
  

  
  vector<Mat> debugImagesSet;
  
  if (this->debug)
  {
    debugImagesSet.push_back(addLabel(charMask, "Charecter mask"));
    //debugImagesSet1.push_back(erodedCharMask);
    Mat maskCopy(colorMask.size(), colorMask.type());
    colorMask.copyTo(maskCopy);
    debugImagesSet.push_back(addLabel(maskCopy, "color Mask Before"));
  }
  
  
  Mat bigElement = getStructuringElement( 1,
				  Size( 3 + 1, 3+1 ),
				  Point( 1, 1 ) );
  
  Mat smallElement = getStructuringElement( 1,
				Size( 1 + 1, 1+1 ),
				Point( 1, 1 ) );
  
  morphologyEx(this->colorMask, this->colorMask, MORPH_CLOSE, bigElement);
  //dilate(this->colorMask, this->colorMask, bigElement);
  
  Mat combined(charMask.size(), charMask.type());
  bitwise_and(charMask, colorMask, combined);
  
  if (this->debug)
  {
    debugImagesSet.push_back(addLabel(colorMask, "Color Mask After"));

    debugImagesSet.push_back(addLabel(combined, "Combined"));
    
    //displayImage(config, "COLOR filter Mask", colorMask);
    debugImagesSet.push_back(addLabel(imgDebug, "Color filter Debug"));
    
    cvtColor(imgDebugHueOnly, imgDebugHueOnly, CV_HSV2BGR);
    debugImagesSet.push_back(addLabel(imgDebugHueOnly, "Color Filter Hue"));
    
    equalizeHist(imgDistanceFromCenter, imgDistanceFromCenter);
    debugImagesSet.push_back(addLabel(imgDistanceFromCenter, "COLOR filter Distance"));
    
    debugImagesSet.push_back(addLabel(debugMask, "COLOR Hues off"));
  
  
    Mat dashboard = drawImageDashboard(debugImagesSet, imgDebugHueOnly.type(), 3);
    displayImage(config, "Color Filter Images", dashboard);
  }

}
Exemple #20
0
Mat visionUtils::cannySegmentation(Mat img0, int minPixelSize, bool displayFaces)
{
    // Segments items in gray image (img0)
    // minPixelSize=
    // -1, returns largest region only
    // pixels, threshold for removing smaller regions, with less than minPixelSize pixels
    // 0, returns all detected segments


    // LB: Zero pad image to remove edge effects when getting regions....
    int padPixels=20;
    // Rect border added at start...
    Rect tempRect;
    tempRect.x=padPixels;
    tempRect.y=padPixels;
    tempRect.width=img0.cols;
    tempRect.height=img0.rows;

    Mat img1 = Mat::zeros(img0.rows+(padPixels*2), img0.cols+(padPixels*2), CV_8UC1);
    img0.copyTo(img1(tempRect));


    if (useGPU)// converted to GPU -> NOT tested to speed up here!
    {
        GpuMat imgGPU;
        imgGPU.upload(img1);
#if CV_MAJOR_VERSION == 2
        gpu::Canny(imgGPU, imgGPU, 100, 200, 3); //100, 200, 3);
#elif CV_MAJOR_VERSION == 3
        cv::Ptr<cv::cuda::CannyEdgeDetector> canny = cv::cuda::createCannyEdgeDetector(100, 200, 3);
        canny->detect(imgGPU, imgGPU);
#endif
        imgGPU.download(img1);
    }
    else
    {
        Canny(img1, img1, 100, 200, 3); //100, 200, 3);
    }


    // find the contours
    vector< vector<Point> > contours;
    findContours(img1, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

    // Mask for segmented regiond
    Mat mask = Mat::zeros(img1.rows, img1.cols, CV_8UC1);

    vector<double> areas(contours.size());

    if (minPixelSize==-1)
    {   // Case of taking largest region
        for(int i = 0; i < (int)contours.size(); i++)
            areas[i] = contourArea(Mat(contours[i]));
        double max;
        Point maxPosition;
        cv::minMaxLoc(Mat(areas),0,&max,0,&maxPosition);
        drawContours(mask, contours, maxPosition.y, Scalar(1), CV_FILLED);
    }
    else
    {   // Case for using minimum pixel size
        for (int i = 0; i < (int)contours.size(); i++)
        {
            if (contourArea(Mat(contours[i]))>minPixelSize)
                drawContours(mask, contours, i, Scalar(1), CV_FILLED);
        }
    }
    // normalize so imwrite(...)/imshow(...) shows the mask correctly!
    cv::normalize(mask.clone(), mask, 0.0, 255.0, CV_MINMAX, CV_8UC1);

    Mat returnMask;
    returnMask=mask(tempRect);

    // show the images
    if (displayFaces)   imshow("Canny: Img in", img0);
    if (displayFaces)   imshow("Canny: Mask", returnMask);
    if (displayFaces)   imshow("Canny: Output", img1);

    return returnMask;
}
Exemple #21
0
//Segment the chars from plate
vector<CharSegment> OCR::segment(Plate plate){
    Mat input=plate.plateImg;
    vector<CharSegment> output;

    //Threshold input image
    Mat img_threshold;
    //To make char image clearly
//    threshold(input, img_threshold, 60, 255, CV_THRESH_BINARY_INV);	//Spain
//    threshold(input, img_threshold, 150~160, 255, CV_THRESH_BINARY);	//China
    // TODO: IMPORTANT
    threshold(input, img_threshold, 175, 255, CV_THRESH_BINARY);	//China
    if(debug) {
        imshow("OCR_Threshold_Binary", img_threshold);
    }

    Mat img_contours;
    img_threshold.copyTo(img_contours);
    //Find contours of possibles characters
    vector< vector< Point> > contours;
    findContours(img_contours,
            contours, // a vector of contours
            CV_RETR_EXTERNAL, // retrieve the external contours
            CV_CHAIN_APPROX_NONE); // all pixels of each contours
    
    // Draw blue contours on a white image
    cv::Mat result;
    img_threshold.copyTo(result);
    cvtColor(result, result, CV_GRAY2RGB);
    cv::drawContours(result,
    		contours,
            -1, // draw all contours
            cv::Scalar(255,0,0), // in BLUE
            1); // with a thickness of 1

    //Start to iterate to each contour founded
    vector<vector<Point> >::iterator itc = contours.begin();
    //Remove patch that are no inside limits of aspect ratio and area.    
    while (itc!=contours.end()) {
        //Create bounding rect of object
        Rect mr = boundingRect(Mat(*itc));
        rectangle(result, mr, Scalar(0,255,0));	//Possible chars in GREEN

        //Crop image
        Mat auxRoi(img_threshold, mr);
        if(verifySizes(auxRoi)){
            auxRoi=preprocessChar(auxRoi);
            output.push_back(CharSegment(auxRoi, mr));
            rectangle(result, mr, Scalar(0,0,255));	//Possible chars in RED
        }
        ++itc;
    }

    if(debug)
    {
        cout << "OCR number of chars: " << output.size() << "\n";
        imshow("OCR Chars", result);
        cvWaitKey(0);
    }

    return output;
}
Exemple #22
0
Mat visionUtils::segmentFace(Mat srcImage, Mat maskImage, bool displayFaces, Mat *skinSegMaskInv)
{

    // Check mask and original image are the same size
    Size srcS = srcImage.size();
    int heightS = srcS.height;
    int widthS = srcS.width;

    Size maskS = maskImage.size();
    int heightM = maskS.height;
    int widthM = maskS.width;

    if (heightS!=heightM || widthS!=widthM)
    {
        cout << "hS:" << heightS << " wS:" << widthS << " hM:" << heightM << " wM" << widthM << endl;
        cout << "Source and mask images are not the same size... aborting" << endl;
        Mat ttt;
        return (ttt);
    }

    /// Convert image to gray and blur it
    cv::cvtColor( maskImage, src_gray, CV_BGR2GRAY );
    cv::blur( src_gray, src_gray, Size(3,3) );
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    /// Detect edges using Threshold
    /// Find contours
    findContours( src_gray, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

    // ########## Remove contour indents (defects), by finding the convex
    /// Find the convex hull object for each contour
    vector<vector<Point> >hull( contours.size() );

    for( int i = 0; i < (int)contours.size(); i++ )
    {
        convexHull( Mat(contours[i]), hull[i], false );
    }

    /// Draw contours + hull results
    Mat drawingHull = Mat::zeros( src_gray.size(), CV_8UC3 );

    //Check minimum contour size and find largest....
    int largest_area=-1;
    int largest_contour_index=0;
    for( int i = 0; i< (int)contours.size(); i++ )
    {
        if( (int)contours[i].size() > minContourSize )
        {
            double a=contourArea( contours[i],false);  //  Find the area of contour
            if(a>largest_area)
            {
                largest_area=a;
                largest_contour_index=i;
            }
        }
    }

    if (displayFaces)
    {
        RNG rng(12345); // for colour generation

        for( int i = 0; i< (int)contours.size(); i++ )
        {
            Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
            drawContours( drawingHull, contours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
            drawContours( drawingHull, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
        }
        imshow( "Contour Convex Hull", drawingHull );
    }

    //// ############### Selected Hull contour to use -> ignoring ellipse etc
    // Check if hull found successfully... if not ABORT
    if (hull.empty() )
    {
        cout << "Hull region not found > returning...." << endl;
        Mat ttt;
        return (ttt);
    }

    // Check area of hull and abort if neded
    vector<Point> approx;
    approxPolyDP(hull[largest_contour_index], approx, 5, true);
    double area1 = contourArea(approx);
    if  (area1<4000)
    {
        cout << "Hull area too small > returning...." << endl;
        Mat ttt;
        return (ttt);
    }

    // Cut down rect around convex contour hull
    Rect boundRect;
    boundRect=boundingRect(Mat(hull[largest_contour_index]));
    // Check bounding box fits inside image.... resize if needed
    boundRect=checkRoiInImage(srcImage, boundRect);

    // Check bounding box has greater dimensions than 5x5pix
    if (boundRect.height<=5 || boundRect.width<=5)
    {
        cout << "Region selected too small... exiting" << endl;
        Mat ttt;
        return (ttt);
    }
    else
    {
        /// Repeat boxing but for masked skin data (Hull)
        // Make binary mask using hull largest contour
        Mat srcSegSkin = Mat::zeros( srcImage.size(), CV_8UC3 );
        Mat skinSegMask = Mat::zeros( srcImage.size(), CV_8UC1 );
        drawContours( skinSegMask, hull, largest_contour_index, Scalar(255), -1, 8, vector<Vec4i>(), 0, Point() );
        srcImage.copyTo(srcSegSkin,skinSegMask);  // Copy using mask from skinSegMask
        srcSegSkin=srcSegSkin(boundRect);

        // Make face blocking mask (face pix = 0)
        Mat skinSegMaskInvTemp = Mat::zeros( srcImage.size(), CV_8UC1 );
        cv::bitwise_not(skinSegMaskInvTemp,*skinSegMaskInv,skinSegMask);

        if (displayFaces)
        {   // Take boxed region of face from original image data
            // Copy inital image and section with bounding box
            Mat srcSegmented = srcImage.clone();
            srcSegmented=srcSegmented(boundRect);
            imshow("Rect region orig",srcSegmented);
            Mat maskSegmented = maskImage.clone();
            maskSegmented=maskSegmented(boundRect);
            imshow("Rect region, with SkinSeg",maskSegmented);
            imshow("Rect region, with hull region SkinSeg",srcSegSkin);
        }

        return(srcSegSkin);
    }
}
int main(int argc, char** argv) {
	cv::VideoCapture stream(0); // open video stream from any video source
	int count = 0;   
int frame_width = stream.get(CV_CAP_PROP_FRAME_WIDTH);
int frame_height = stream.get(CV_CAP_PROP_FRAME_HEIGHT);

VideoWriter outputVideo("salient_video.avi", CV_FOURCC('M', 'J', 'P', 'G'), 20 , Size(frame_width, frame_height), true); 
while(stream.isOpened())
{
  cv::Mat inputImage;
   if ( ! stream.read(inputImage) ) // try to read a frame
            break;
   
   Mat finalImage;
	Mat * ptr = NULL;
	pthread_t intensityThread, colorThread;
   long totaltime = timestamp();
	
	//long intTime = timestamp();
	IntensityImg = Get_Intensity_Image(inputImage);
	pthread_create(&intensityThread, NULL, intensity_processing, (void *) ptr);
	//pthread_join(intensityThread, NULL);
	//long intFinal = timestamp() - intTime;
	//cout << "Intensity Map Time: " << intFinal << "\n";
	
	ptr = &inputImage;
	//long colTime = timestamp();
	pthread_create(&colorThread, NULL, color_processing, (void *) ptr);
	//pthread_join(colorThread, NULL);
	//long colFinal = timestamp() - colTime;
	//cout << "Color Map Time: " << colFinal << "\n";
	
	//long orTime = timestamp();
	Mat AggOr = getGaborImage();
	normalize(AggOr, AggOr, 0, 255, NORM_MINMAX, -1);
	//long orFinal = timestamp() - orTime;
	//cout << "Orientation Map Time: " << orFinal << "\n";

        pthread_join(intensityThread, NULL);
        pthread_join(colorThread, NULL);

	
	finalImage = (AggInt + AggColor + AggOr) / 3;
	normalize(finalImage, finalImage, 0, 255, NORM_MINMAX, -1);

	for (int bCtr = 0; bCtr < 4; bCtr++) {
		pyrUp(finalImage, finalImage);
	}
	
	long finaltime = timestamp() - totaltime;
	cout << "Total Time: " << finaltime << "\n";
	Mat contImg;
	inRange(finalImage, 130, 255, contImg);
	vector < vector<Point> > contours;
	vector < Vec4i > hierarchy;

	findContours(contImg, contours, hierarchy, CV_RETR_CCOMP,
			CV_CHAIN_APPROX_SIMPLE);
	for (int i = 0; i >= 0; i = hierarchy[i][0]) {
		Scalar color(rand() & 255, rand() & 255, rand() & 255);
		drawContours(inputImage, contours, i, color, 3, 8, hierarchy);
	}


   
   outputVideo.write(inputImage);
  
}
	return 0;
}
Leap::Vector GetTrackedPoint(Leap::Image image)
{
	Mat img = Mat(image.height(), image.width(), CV_8UC1);
	img.data = (unsigned char*)image.data();

	Mat cimg = img.clone();
	CvSize size = img.size();

	//binary threshold, val = 235
	threshold(img, cimg, 235, 255, 0);
	medianBlur(cimg, cimg, 5);

	//circle detection with contours	
	bool enableRadiusCulling = false;
	int minTargetRadius = 5;
	vector<vector<Point> > contours;
	vector<Vec4i> heirarchy;

	findContours(cimg, contours, heirarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

	size_t count = contours.size();

	//get circle with largest radius
	float radius = 0;
	Point2i center;

	for (int i = 0; i < count; i++)
	{
		Point2f c;
		float r;
		minEnclosingCircle(contours[i], c, r);

		if (!enableRadiusCulling || r >= minTargetRadius)
		{
			if (r > radius) {
				radius = r;
				center = (Point2i)c;
			}
		}
	}

	Leap::Vector res;
	res.x = center.x;
	res.y = center.y;
	res.z = 0;

	/*
	cvtColor(cimg, cimg, CV_GRAY2BGR);

	Scalar red(0, 0, 255);
	Scalar blue(255, 0, 0);

	if (radius > 0) { //circle was found
		circle(cimg, center, radius, red, 1);
		circle(cimg, center, 1, blue, 2);
		//cout << "Center: " << center.x << "; " << center.y << "\n";
	}
	imshow("detected circles", cimg);
	*/
	return res;
}
void RecognitionDemos( Mat& full_image, Mat& template1, Mat& template2, Mat& template1locations, Mat& template2locations, VideoCapture& bicycle_video, Mat& bicycle_background, Mat& bicycle_model, VideoCapture& people_video, CascadeClassifier& cascade, Mat& numbers, Mat& good_orings, Mat& bad_orings, Mat& unknown_orings )
{
	Timestamper* timer = new Timestamper();

	// Principal Components Analysis
	PCASimpleExample();
    char ch = cvWaitKey();
	cvDestroyAllWindows();

	PCAFaceRecognition();
    ch = cvWaitKey();
	cvDestroyAllWindows();

	// Statistical Pattern Recognition
	Mat gray_numbers,binary_numbers;
	cvtColor(numbers, gray_numbers, CV_BGR2GRAY);
	threshold(gray_numbers,binary_numbers,128,255,THRESH_BINARY_INV);
    vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	findContours(binary_numbers,contours,hierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);
	Mat contours_image = Mat::zeros(binary_numbers.size(), CV_8UC3);
	contours_image = Scalar(255,255,255);
	// Do some processing on all contours (objects and holes!)
	vector<RotatedRect> min_bounding_rectangle(contours.size());
	vector<vector<Point>> hulls(contours.size());
	vector<vector<int>> hull_indices(contours.size());
	vector<vector<Vec4i>> convexity_defects(contours.size());
	vector<Moments> contour_moments(contours.size());
	for (int contour_number=0; (contour_number<(int)contours.size()); contour_number++)
	{
		if (contours[contour_number].size() > 10)
		{
			min_bounding_rectangle[contour_number] = minAreaRect(contours[contour_number]);
			convexHull(contours[contour_number], hulls[contour_number]);
			convexHull(contours[contour_number], hull_indices[contour_number]);
			convexityDefects( contours[contour_number], hull_indices[contour_number], convexity_defects[contour_number]);
			contour_moments[contour_number] = moments( contours[contour_number] );
		}
	}
	for (int contour_number=0; (contour_number>=0); contour_number=hierarchy[contour_number][0])
	{
		if (contours[contour_number].size() > 10)
		{
        Scalar colour( rand()&0x7F, rand()&0x7F, rand()&0x7F );
        drawContours( contours_image, contours, contour_number, colour, CV_FILLED, 8, hierarchy );
		char output[500];
		double area = contourArea(contours[contour_number])+contours[contour_number].size()/2+1;
		// Process any holes (removing the area from the are of the enclosing contour)
		for (int hole_number=hierarchy[contour_number][2]; (hole_number>=0); hole_number=hierarchy[hole_number][0])
		{
			area -= (contourArea(contours[hole_number])-contours[hole_number].size()/2+1);
			Scalar colour( rand()&0x7F, rand()&0x7F, rand()&0x7F );
 			drawContours( contours_image, contours, hole_number, colour, CV_FILLED, 8, hierarchy );
			sprintf(output,"Area=%.0f", contourArea(contours[hole_number])-contours[hole_number].size()/2+1);
			Point location( contours[hole_number][0].x +20, contours[hole_number][0].y +5 );
			putText( contours_image, output, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
		}
		// Draw the minimum bounding rectangle
		Point2f bounding_rect_points[4];
		min_bounding_rectangle[contour_number].points(bounding_rect_points);
		line( contours_image, bounding_rect_points[0], bounding_rect_points[1], Scalar(0, 0, 127));
		line( contours_image, bounding_rect_points[1], bounding_rect_points[2], Scalar(0, 0, 127));
		line( contours_image, bounding_rect_points[2], bounding_rect_points[3], Scalar(0, 0, 127));
		line( contours_image, bounding_rect_points[3], bounding_rect_points[0], Scalar(0, 0, 127));
		float bounding_rectangle_area = min_bounding_rectangle[contour_number].size.area();
		// Draw the convex hull
        drawContours( contours_image, hulls, contour_number, Scalar(127,0,127) );
		// Highlight any convexities
		int largest_convexity_depth=0;
		for (int convexity_index=0; convexity_index < (int)convexity_defects[contour_number].size(); convexity_index++)
		{
			if (convexity_defects[contour_number][convexity_index][3] > largest_convexity_depth)
				largest_convexity_depth = convexity_defects[contour_number][convexity_index][3];
			if (convexity_defects[contour_number][convexity_index][3] > 256*2)
			{
				line( contours_image, contours[contour_number][convexity_defects[contour_number][convexity_index][0]], contours[contour_number][convexity_defects[contour_number][convexity_index][2]], Scalar(0,0, 255));
				line( contours_image, contours[contour_number][convexity_defects[contour_number][convexity_index][1]], contours[contour_number][convexity_defects[contour_number][convexity_index][2]], Scalar(0,0, 255));
			}
		}
		double hu_moments[7];
		HuMoments( contour_moments[contour_number], hu_moments );
		sprintf(output,"Perimeter=%d, Area=%.0f, BArea=%.0f, CArea=%.0f", contours[contour_number].size(),area,min_bounding_rectangle[contour_number].size.area(),contourArea(hulls[contour_number]));
		Point location( contours[contour_number][0].x, contours[contour_number][0].y-3 );
		putText( contours_image, output, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
		sprintf(output,"HuMoments = %.2f, %.2f, %.2f", hu_moments[0],hu_moments[1],hu_moments[2]);
		Point location2( contours[contour_number][0].x+100, contours[contour_number][0].y-3+15 );
		putText( contours_image, output, location2, FONT_HERSHEY_SIMPLEX, 0.4, colour );
		}
	}
	imshow("Shape Statistics", contours_image );
	char c = cvWaitKey();
	cvDestroyAllWindows();

	// Support Vector Machine
	imshow("Good - original",good_orings);
	imshow("Defective - original",bad_orings);
	imshow("Unknown - original",unknown_orings);
	SupportVectorMachineDemo(good_orings,"Good",bad_orings,"Defective",unknown_orings);
	c = cvWaitKey();
	cvDestroyAllWindows();

	// Template Matching
	Mat display_image, correlation_image;
	full_image.copyTo( display_image );
	double min_correlation, max_correlation;
	Mat matched_template_map;
	int result_columns =  full_image.cols - template1.cols + 1;
	int result_rows = full_image.rows - template1.rows + 1;
	correlation_image.create( result_columns, result_rows, CV_32FC1 );
	timer->reset();
	double before_tick_count = static_cast<double>(getTickCount());
	matchTemplate( full_image, template1, correlation_image, CV_TM_CCORR_NORMED );
	double after_tick_count = static_cast<double>(getTickCount());
	double duration_in_ms = 1000.0*(after_tick_count-before_tick_count)/getTickFrequency();
	minMaxLoc( correlation_image, &min_correlation, &max_correlation );
	FindLocalMaxima( correlation_image, matched_template_map, max_correlation*0.99 );
	timer->recordTime("Template Matching (1)");
	Mat matched_template_display1;
	cvtColor(matched_template_map, matched_template_display1, CV_GRAY2BGR);
	Mat correlation_window1 = convert_32bit_image_for_display( correlation_image, 0.0 );
	DrawMatchingTemplateRectangles( display_image, matched_template_map, template1, Scalar(0,0,255) );
	double precision, recall, accuracy, specificity, f1;
	Mat template1locations_gray;
	cvtColor(template1locations, template1locations_gray, CV_BGR2GRAY);
	CompareRecognitionResults( matched_template_map, template1locations_gray, precision, recall, accuracy, specificity, f1 );
	char results[400];
	Scalar colour( 255, 255, 255);
	sprintf( results, "precision=%.2f", precision);
	Point location( 7, 213 );
	putText( display_image, "Results (1)", location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	sprintf( results, "recall=%.2f", recall);
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	sprintf( results, "accuracy=%.2f", accuracy);
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	sprintf( results, "specificity=%.2f", specificity);
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	sprintf( results, "f1=%.2f", f1);
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
  
	result_columns =  full_image.cols - template2.cols + 1;
	result_rows = full_image.rows - template2.rows + 1;
	correlation_image.create( result_columns, result_rows, CV_32FC1 );
	timer->ignoreTimeSinceLastRecorded();
	matchTemplate( full_image, template2, correlation_image, CV_TM_CCORR_NORMED );
	minMaxLoc( correlation_image, &min_correlation, &max_correlation );
	FindLocalMaxima( correlation_image, matched_template_map, max_correlation*0.99 );
	timer->recordTime("Template Matching (2)");
	Mat matched_template_display2;
	cvtColor(matched_template_map, matched_template_display2, CV_GRAY2BGR);
	Mat correlation_window2 = convert_32bit_image_for_display( correlation_image, 0.0 );
	DrawMatchingTemplateRectangles( display_image, matched_template_map, template2, Scalar(0,0,255) );
	timer->putTimes(display_image);
	Mat template2locations_gray;
	cvtColor(template2locations, template2locations_gray, CV_BGR2GRAY);
	CompareRecognitionResults( matched_template_map, template2locations_gray, precision, recall, accuracy, specificity, f1 );
	sprintf( results, "precision=%.2f", precision);
	location.x = 123;
	location.y = 213;
	putText( display_image, "Results (2)", location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	sprintf( results, "recall=%.2f", recall);
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	sprintf( results, "accuracy=%.2f", accuracy);
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	sprintf( results, "specificity=%.2f", specificity);
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	sprintf( results, "f1=%.2f", f1);
	location.y += 13;
	putText( display_image, results, location, FONT_HERSHEY_SIMPLEX, 0.4, colour );
	Mat correlation_display1, correlation_display2;
	cvtColor(correlation_window1, correlation_display1, CV_GRAY2BGR);
	cvtColor(correlation_window2, correlation_display2, CV_GRAY2BGR);

	Mat output1 = JoinImagesVertically(template1,"Template (1)",correlation_display1,"Correlation (1)",4);
	Mat output2 = JoinImagesVertically(output1,"",matched_template_display1,"Local maxima (1)",4);
	Mat output3 = JoinImagesVertically(template2,"Template (2)",correlation_display2,"Correlation (2)",4);
	Mat output4 = JoinImagesVertically(output3,"",matched_template_display2,"Local maxima (2)",4);
	Mat output5 = JoinImagesHorizontally( full_image, "Original Image", output2, "", 4 );
	Mat output6 = JoinImagesHorizontally( output5, "", output4, "", 4 );
	Mat output7 = JoinImagesHorizontally( output6, "", display_image, "", 4 );
	imshow( "Template matching result", output7 );
	c = cvWaitKey();
	cvDestroyAllWindows();

	// Chamfer Matching
    Mat model_gray,model_edges,model_edges2;
	cvtColor(bicycle_model, model_gray, CV_BGR2GRAY);
	threshold(model_gray,model_edges,127,255,THRESH_BINARY);
	Mat current_frame;
	bicycle_video.set(CV_CAP_PROP_POS_FRAMES,400);  // Just in case the video has already been used.
	bicycle_video >> current_frame;
	bicycle_background = current_frame.clone();
	bicycle_video.set(CV_CAP_PROP_POS_FRAMES,500); 
	timer->reset();
	int count = 0;
	while (!current_frame.empty() && (count < 8))
    {
		Mat result_image = current_frame.clone();
		count++;
		Mat difference_frame, difference_gray, current_edges;
		absdiff(current_frame,bicycle_background,difference_frame);
		cvtColor(difference_frame, difference_gray, CV_BGR2GRAY);
		Canny(difference_frame, current_edges, 100, 200, 3);

		vector<vector<Point> > results;
		vector<float> costs;
		threshold(model_gray,model_edges,127,255,THRESH_BINARY);
		Mat matching_image, chamfer_image, local_minima;
		timer->ignoreTimeSinceLastRecorded();
		threshold(current_edges,current_edges,127,255,THRESH_BINARY_INV);
		distanceTransform( current_edges, chamfer_image, CV_DIST_L2 , 3);
		timer->recordTime("Chamfer Image");
		ChamferMatching( chamfer_image, model_edges, matching_image );
		timer->recordTime("Matching");
		FindLocalMinima( matching_image, local_minima, 500.0 );
		timer->recordTime("Find Minima");
		DrawMatchingTemplateRectangles( result_image, local_minima, model_edges, Scalar( 255, 0, 0 ) );
		Mat chamfer_display_image = convert_32bit_image_for_display( chamfer_image );
		Mat matching_display_image = convert_32bit_image_for_display( matching_image );
		//timer->putTimes(result_image);
		Mat current_edges_display, local_minima_display, model_edges_display, colour_matching_display_image, colour_chamfer_display_image;
		cvtColor(current_edges, current_edges_display, CV_GRAY2BGR);
		cvtColor(local_minima, local_minima_display, CV_GRAY2BGR);
		cvtColor(model_edges, model_edges_display, CV_GRAY2BGR);
		cvtColor(matching_display_image, colour_matching_display_image, CV_GRAY2BGR);
		cvtColor(chamfer_display_image, colour_chamfer_display_image, CV_GRAY2BGR);

		Mat output1 = JoinImagesVertically(current_frame,"Video Input",current_edges_display,"Edges from difference", 4);
		Mat output2 = JoinImagesVertically(output1,"",model_edges_display,"Model", 4);
		Mat output3 = JoinImagesVertically(bicycle_background,"Static Background",colour_chamfer_display_image,"Chamfer image", 4);
		Mat output4 = JoinImagesVertically(output3,"",colour_matching_display_image,"Degree of fit", 4);
		Mat output5 = JoinImagesVertically(difference_frame,"Difference",result_image,"Result", 4);
		Mat output6 = JoinImagesVertically(output5,"",local_minima_display,"Local minima", 4);
		Mat output7 = JoinImagesHorizontally( output2, "", output4, "", 4 );
		Mat output8 = JoinImagesHorizontally( output7, "", output6, "", 4 );
		imshow("Chamfer matching", output8);
		c = waitKey(1000);  // This makes the image appear on screen
		bicycle_video >> current_frame;
	}
	c = cvWaitKey();
	cvDestroyAllWindows();

	// Cascade of Haar classifiers (most often shown for face detection).
    VideoCapture camera;
	camera.open(1);
	camera.set(CV_CAP_PROP_FRAME_WIDTH, 320);
	camera.set(CV_CAP_PROP_FRAME_HEIGHT, 240);
    if( camera.isOpened() )
	{
		timer->reset();
		Mat current_frame;
		do {
			camera >> current_frame;
			if( current_frame.empty() )
				break;
			vector<Rect> faces;
			timer->ignoreTimeSinceLastRecorded();
			Mat gray;
			cvtColor( current_frame, gray, CV_BGR2GRAY );
			equalizeHist( gray, gray );
			cascade.detectMultiScale( gray, faces, 1.1, 2, CV_HAAR_SCALE_IMAGE, Size(30, 30) );
			timer->recordTime("Haar Classifier");
			for( int count = 0; count < (int)faces.size(); count++ )
				rectangle(current_frame, faces[count], cv::Scalar(255,0,0), 2);
			//timer->putTimes(current_frame);
			imshow( "Cascade of Haar Classifiers", current_frame );
			c = waitKey(10);  // This makes the image appear on screen
        } while (c == -1);
	}
static cv::Mat signalDetect_inROI(const cv::Mat& roi,
                                  const cv::Mat&     src_img,
                                  const double       estimatedRadius,
                                  const cv::Point roi_topLeft
                                  )
{
  /* reduce noise */
  cv::Mat noiseReduced(roi.rows, roi.cols, CV_8UC3);
  GaussianBlur(roi, noiseReduced, cv::Size(3, 3), 0, 0);

  /* extract color information */
  cv::Mat red_mask(roi.rows, roi.cols, CV_8UC1);
  colorExtraction(noiseReduced       ,
                  &red_mask          ,
                  thSet.Red.Hue.lower, thSet.Red.Hue.upper,
                  thSet.Red.Sat.lower, thSet.Red.Sat.upper,
                  thSet.Red.Val.lower, thSet.Red.Val.upper);

  cv::Mat yellow_mask(roi.rows, roi.cols, CV_8UC1);
  colorExtraction(noiseReduced          ,
                  &yellow_mask          ,
                  thSet.Yellow.Hue.lower, thSet.Yellow.Hue.upper,
                  thSet.Yellow.Sat.lower, thSet.Yellow.Sat.upper,
                  thSet.Yellow.Val.lower, thSet.Yellow.Val.upper);

  cv::Mat green_mask(roi.rows, roi.cols, CV_8UC1);
  colorExtraction(noiseReduced         ,
                  &green_mask          ,
                  thSet.Green.Hue.lower, thSet.Green.Hue.upper,
                  thSet.Green.Sat.lower, thSet.Green.Sat.upper,
                  thSet.Green.Val.lower, thSet.Green.Val.upper);

  /* combine all color mask and create binarized image */
  cv::Mat binarized = cv::Mat::zeros(roi.rows, roi.cols, CV_8UC1);
  bitwise_or(red_mask, yellow_mask, binarized);
  bitwise_or(binarized, green_mask, binarized);
  threshold(binarized, binarized, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

  /* filter by its shape and index each bright region */
  std::vector< std::vector<cv::Point> > bright_contours;
  std::vector<cv::Vec4i> bright_hierarchy;
  findContours(binarized,
               bright_contours,
               bright_hierarchy,
               CV_RETR_CCOMP,
               CV_CHAIN_APPROX_NONE);


  cv::Mat bright_mask = cv::Mat::zeros(roi.rows, roi.cols, CV_8UC1);

  int contours_idx = 0;
  std::vector<regionCandidate> candidates;
  for (unsigned int i=0; i<bright_contours.size(); i++)
    {
      cv::Rect bound = boundingRect(bright_contours.at(contours_idx));
      cv::Scalar rangeColor = BLACK;
      struct regionCandidate cnd;
      double area = contourArea(bright_contours.at(contours_idx));
      double perimeter = arcLength(bright_contours.at(contours_idx), true);
      double circleLevel = (IsNearlyZero(perimeter)) ? 0.0f : (4.0f * CV_PI * area / pow(perimeter, 2));

      if (std::max(bound.width, bound.height) < 2*std::min(bound.width, bound.height) && /* dimension ratio */
          CIRCLE_LEVEL_THRESHOLD <= circleLevel                                       &&
          CIRCLE_AREA_THRESHOLD  <= area)
        {
          // std::cerr << "circleLevel: " << circleLevel << std::endl;
          rangeColor    = WHITE;
          cnd.center.x  = bound.x + bound.width/2;
          cnd.center.y  = bound.y + bound.height/2;
          cnd.idx       = contours_idx;
          cnd.circleLevel = (IsNearlyZero(perimeter)) ? 0.0f : (4.0 * CV_PI * area / pow(perimeter, 2));
          cnd.isBlacked = false;
          candidates.push_back(cnd);
        }

      drawContours(bright_mask,
                   bright_contours,
                   contours_idx,
                   rangeColor,
                   CV_FILLED,
                   8,
                   bright_hierarchy,
                   0);

      /* only contours on toplevel are considered */
      contours_idx = bright_hierarchy[contours_idx][0];
      if (contours_idx < 0)
        break;
    }

  // imshow("bright_mask", bright_mask);
  // waitKey(10);

  unsigned int candidates_num = candidates.size();

  // std::cerr << "before checkExtrinctionLight. candidates: " << candidates_num << std::endl;

  /* decrease candidates by checking existence of turned off light in their neighborhood */
  if (candidates_num > 1)    /* if there are multipule candidates */
    {
      for (unsigned int i=0; i<candidates.size(); i++)
        {
          /* check wheter this candidate seems to be green lamp */
          cv::Point check_roi_topLeft  = cv::Point(candidates.at(i).center.x - 2*estimatedRadius + roi_topLeft.x,
                                                   candidates.at(i).center.y - 2*estimatedRadius + roi_topLeft.y);
          cv::Point check_roi_botRight = cv::Point(candidates.at(i).center.x + 6*estimatedRadius + roi_topLeft.x,
                                                   candidates.at(i).center.y + 2*estimatedRadius + roi_topLeft.y);
          bool likeGreen = checkExtinctionLight(src_img, check_roi_topLeft, check_roi_botRight, candidates.at(i).center);

          /* check wheter this candidate seems to be yellow lamp */
          check_roi_topLeft  = cv::Point(candidates.at(i).center.x - 4*estimatedRadius + roi_topLeft.x,
                                     candidates.at(i).center.y - 2*estimatedRadius + roi_topLeft.y);
          check_roi_botRight = cv::Point(candidates.at(i).center.x + 4*estimatedRadius + roi_topLeft.x,
                                     candidates.at(i).center.y + 2*estimatedRadius + roi_topLeft.y);
          bool likeYellow = checkExtinctionLight(src_img, check_roi_topLeft, check_roi_botRight, candidates.at(i).center);

          /* check wheter this candidate seems to be red lamp */
          check_roi_topLeft  = cv::Point(candidates.at(i).center.x - 6*estimatedRadius + roi_topLeft.x,
                                     candidates.at(i).center.y - 2*estimatedRadius + roi_topLeft.y);
          check_roi_botRight = cv::Point(candidates.at(i).center.x + 2*estimatedRadius + roi_topLeft.x,
                                     candidates.at(i).center.y + 2*estimatedRadius + roi_topLeft.y);
          bool likeRed = checkExtinctionLight(src_img, check_roi_topLeft, check_roi_botRight, candidates.at(i).center);


          if (!likeGreen && !likeYellow && !likeRed) /* this region may not be traffic light */
            {
              candidates_num--;
              drawContours(bright_mask,
                           bright_contours,
                           candidates.at(i).idx,
                           BLACK,
                           CV_FILLED,
                           8,
                           bright_hierarchy,
                           0);
              candidates.at(i).isBlacked = true;
            }
        }
    }

  // std::cerr << "after checkExtrinctionLight. candidates: " << candidates_num << std::endl;

  /* choose one candidate by comparing degree of circularity */
  if (candidates_num > 1)       /* if there are still multiple candidates */
    {
      double min_diff = DBL_MAX;
      unsigned int min_idx = 0;

      /* search the region that has nearest degree of circularity to 1 */
      for (unsigned int i=0; i<candidates.size(); i++)
        {
          if(candidates.at(i).isBlacked)
            continue;

          double diff = fabs(1 - candidates.at(i).circleLevel);
          if (min_diff > diff)
            {
              min_diff = diff;
              min_idx = i;
            }
        }

      /* fill region of non-candidate */
      for (unsigned int i=0; i<candidates.size(); i++)
        {

          if(candidates.at(i).isBlacked)
            continue;

          cv::Scalar regionColor = BLACK;
          candidates.at(i).isBlacked = true;
          if (i == min_idx)
            {
              regionColor = WHITE;
              candidates.at(i).isBlacked = false;
            }

          drawContours(bright_mask,
                       bright_contours,
                       candidates.at(i).idx,
                       regionColor,
                       CV_FILLED,
                       8,
                       bright_hierarchy,
                       0);
        }
    }

  return bright_mask;

} /* static void signalDetect_inROI() */
Exemple #27
0
void cannyEdgeMethod(const cv::Mat& image, cv::Mat& output) {
  // Step 2: get the edges.

  cv::Mat shrunk;

  float scaleFactor = 1;
  if (image.rows > 640 || image.cols > 640) {
    if (image.cols > image.rows) {
      scaleFactor = 640. / ((float) image.cols);
    } else {
      scaleFactor = 640. / ((float) image.rows);
    }
  }

  std::cout << scaleFactor << std::endl;

  cv::resize(image, shrunk, cv::Size(image.cols * scaleFactor, image.rows * scaleFactor));

  // Step 2.1: get a blurred image.
  cv::Mat blurred = shrunk.clone();
  cv::blur( blurred, blurred, cv::Size(3,3) );

  // Step 2.2: get the edges
  cv::Mat edges;
  cv::Canny(blurred, edges, 100, 255);

  auto contours = findContours(edges);

  cv::Mat contourMap = cv::Mat::zeros(edges.size(), CV_8U);
  cv::drawContours(contourMap, contours, -1, cv::Scalar(255));

  std::vector<std::vector<cv::Point>> quads;
  for (auto contour : contours) {
    std::vector<cv::Point> approx;
    cv::approxPolyDP(cv::Mat(contour), approx, cv::arcLength(cv::Mat(contour), true)*0.02, true);

    if (approx.size() == 4 && cv::isContourConvex(cv::Mat(approx))) {
      quads.push_back(approx);
    }
  }

  auto centered = findCentered(image, quads);

  sortQuadCorners(centered);
  for (auto &point : centered) {
    point *= 1. / scaleFactor;
  }

  auto destDimensions = getDimensions(centered);
  cv::Mat target(destDimensions.x, destDimensions.y, image.type());
  std::vector<cv::Point2f> targetPoints {
    {0., 0.},
    {(float) (target.cols - 1), 0.},
    {(float) (target.cols - 1), (float) (target.rows - 1)},
    {0., (float) (target.rows - 1)}
  };
  std::vector<cv::Point2f> points;
  convertPoints(centered, points);
  const cv::Mat transMat = cv::getPerspectiveTransform(points, targetPoints);
  cv::warpPerspective(image, output, transMat, target.size());
}
static bool checkExtinctionLight(const cv::Mat&  src_img,
                                 const cv::Point top_left,
                                 const cv::Point bot_right,
                                 const cv::Point bright_center)
{

  /* check whether new roi is included by source image */
  cv::Point roi_top_left;
  roi_top_left.x = (top_left.x < 0) ? 0 :
    (src_img.cols < top_left.x) ? src_img.cols : top_left.x;
  roi_top_left.y = (top_left.y < 0) ? 0 :
    (src_img.rows < top_left.y) ? src_img.rows : top_left.y;

  cv::Point roi_bot_right;
  roi_bot_right.x = (bot_right.x < 0) ? 0 :
    (src_img.cols < bot_right.x) ? src_img.cols : bot_right.x;
  roi_bot_right.y = (bot_right.y < 0) ? 0 :
    (src_img.rows < bot_right.y) ? src_img.rows : bot_right.y;

  cv::Mat roi = src_img(cv::Rect(roi_top_left, roi_bot_right));

  cv::Mat roi_HSV;
  cvtColor(roi, roi_HSV, CV_BGR2HSV);

  cv::Mat hsv_channel[3];
  split(roi_HSV, hsv_channel);

  int anchor = 3;
  cv::Mat kernel = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(2*anchor + 1, 2*anchor + 1), cv::Point(anchor, anchor));

  cv::Mat topHat_dark;
  morphologyEx(hsv_channel[2], topHat_dark, cv::MORPH_TOPHAT, kernel, cv::Point(anchor, anchor), 5);

  /* sharpening */
  cv::Mat tmp;
  threshold(topHat_dark, tmp, 0.1*255, 255, cv::THRESH_BINARY_INV);
  tmp.copyTo(topHat_dark);

  /* filter by its shape and search dark region */
  std::vector< std::vector<cv::Point> > dark_contours;
  std::vector<cv::Vec4i> dark_hierarchy;
  findContours(topHat_dark,
               dark_contours,
               dark_hierarchy,
               CV_RETR_CCOMP,
               CV_CHAIN_APPROX_NONE);

  int contours_idx = 0;
  bool isThere_dark = false;

  /* check whether "turned off light" like region are in this roi */
  for (unsigned int i=0; i<dark_contours.size(); i++)
    {
      cv::Rect bound = boundingRect(dark_contours.at(contours_idx));
      double area = contourArea(dark_contours.at(contours_idx));
      double perimeter = arcLength(dark_contours.at(contours_idx), true);
      double circleLevel = (IsNearlyZero(perimeter)) ? 0.0f : (4.0f * CV_PI * area / pow(perimeter, 2));

      if (std::max(bound.width, bound.height) < 2*std::min(bound.width, bound.height) && // dimension ratio
          CIRCLE_LEVEL_THRESHOLD <= circleLevel)                                         // round enough

        {
          isThere_dark = true;
          // std::cerr << "there is dark region" << std::endl;
        }

      contours_idx = dark_hierarchy[contours_idx][0];
      if (contours_idx < 0)
        break;
    }

  return isThere_dark;

} /* static bool checkExtinctionLight() */
// 计算标记点数量
vector<cv::Rect> CAnswerCardApp::GetMarkersNum(Mat srcroi)
 {
	 Mat roi;
	 srcroi.copyTo(roi);
	 Mat se = getStructuringElement(MORPH_ELLIPSE,Size(5,5));
	 morphologyEx(roi,roi,cv::MORPH_CLOSE,se);
	vector<cv::Rect> mks;
	vector<vector<cv::Point> > contours;
//  	imshow("test",roi);
//  	cvWaitKey(0);
	findContours(roi,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE );
	if (contours.size()!=0)
	{
		vector<int> markArea;
		for( int i = contours.size()-1; i>=0 ; i-- )
		{
			int area =(int) contourArea(contours.at(i));
			markArea.push_back(area);
		}
		sort(markArea.begin(),markArea.end());
		min_markers_area=markArea.at(markArea.size()/2)/2;

		vector<int> width;
		vector<int> height;

		for( int i = contours.size()-1; i>=0 ; i-- )
		{
			int area =(int) contourArea(contours.at(i));
			if (area<min_markers_area)
			{
				continue;
			}
			mks.push_back(boundingRect(contours.at(i)));
			width.push_back(boundingRect(contours.at(i)).width);
			height.push_back(boundingRect(contours.at(i)).height);
		}

		int midWidth = width.at(width.size()/2);
		int midHeight = height.at(height.size()/2);
		int anchorWidth = theApp.anchorPoints[0].width;
		int anchorHight = theApp.anchorPoints[0].height;
		//允许的误差大小
		int tolerance = 10;

		for(vector<cv::Rect>::iterator it  = mks.begin(); it != mks.end(); )  
		{  
			if (MIN(abs(it->width - midWidth) , abs(it->width-anchorWidth)) > tolerance)
			{
				it = mks.erase(it);
			}
			else if (MIN(abs(it->height - midHeight),abs(it->height-anchorHight)) > tolerance)
			{
				it = mks.erase(it);
			}
			else
				it++;			
		} 

	}
	return mks;
}
Exemple #30
0
// display function should be good enough
void OpenRadar::DrawRadarData()
{
	int usualColor[15] = {16777215,255,128,65280,32768,
		      16711680,16711935,8421376,65535,32896 }; /*<usual color*/
	CvPoint pt1, pt2;

	cvZero(RadarImage);
	cvCircle(RadarImage, cvPoint(DisplayDx,DisplayDy),3, CV_RGB(0,255,255), -1, 8,0);
	int x,y;
	unsigned char * pPixel = 0;
	int colorIndex = 0, colorRGB;
	int R = 255, G = 0, B = 0;
    
	for (int i = 0; i < RadarDataCnt;i++)
	{  
		if (RadarRho[i] < 0)
		{
			
			//change color
			colorRGB = usualColor[colorIndex];
			R = colorRGB/65536;
			G = (colorRGB%65536)/256;
			B = colorRGB%256;
			colorIndex = (colorIndex + 1)%10;
			
		}
		else 
		{
			x = (int)(RadarRho[i]*cos(RadarTheta[i])/DisplayRatio) + DisplayDx;
			y = (int)(-RadarRho[i]*sin(RadarTheta[i])/DisplayRatio)+ DisplayDy;
	
			if (x >= 0 && x < RadarImageWdith && y >= 0 && y < RadarImageHeight)
			{
				pPixel = (unsigned char*)RadarImage->imageData + y*RadarImage->widthStep + 3*x;
				pPixel[0] = B;
				pPixel[1] = G;
				pPixel[2] = R;
			}
		}     
	}
	
	pt1.x = DisplayDx; pt1.y = DisplayDy;
	pt2.x = DisplayDx+line_length*v_scale*sin(v_angle + 0.5*M_PI); 
	pt2.y = DisplayDy+line_length*v_scale*cos(v_angle + 0.5*M_PI);
	cvLine(RadarImage, pt1, pt2, CV_RGB(255,255,255),2,8,0);

	pt2.x = DisplayDx+line_length*cos(-(-120 + skip_bin_idx * polarH_resolution)* M_PI/180 ); 	
	pt2.y = DisplayDy+line_length*sin(-(-120 + skip_bin_idx * polarH_resolution)* M_PI/180 ); 
	cvLine(RadarImage, pt1, pt2, CV_RGB(0,255,0),1,8,0);

	pt2.x = DisplayDx+line_length*cos(-(-120 + (polarH_length-skip_bin_idx) * polarH_resolution)* M_PI/180 ); 
	pt2.y = DisplayDy+line_length*sin(-(-120 + (polarH_length-skip_bin_idx) * polarH_resolution)* M_PI/180 ); 
	//pt2.x = DisplayDx+line_length*cos(0.25*M_PI); 
	//pt2.y = DisplayDy+line_length*sin(0.25*M_PI);
	//cout<< line_length <<endl; 
	//cout<< pt1.x <<" , " << pt1.y <<endl;
	//cout<< pt2.x <<" , " << pt2.y <<endl;
	cvLine(RadarImage, pt1, pt2, CV_RGB(0,255,0),1,8,0);

	float angle;
	int line_length2;
	for (int i=0; i<polarH_length;i++)
	{
		angle = (-30+i*polarH_resolution)*M_PI/180;
		line_length2 = H[i]/10;
		pt2.x = DisplayDx+line_length2*sin(angle); 
		pt2.y = DisplayDy+line_length2*cos(angle);
		cvCircle(RadarImage, pt2, 2, CV_RGB(255,255,255),1,8,0);
	}

	////////////////////////////////////////////////////////////////////////////////////
	// mine
	////////////////////////////////////////////////////////////////////////////////////
	Mat binImg = Mat::zeros(RadarImageHeight,RadarImageWdith,CV_8UC1);
	vector< Point> centerRaw;
	centerRaw.clear();
	for (int i = 0; i < RadarDataCnt;i++)
	{  
		if (RadarRho[i] > 200)
		{
			x = (int)(RadarRho[i]*cos(RadarTheta[i])/DisplayRatio) + DisplayDx;
			y = (int)(-RadarRho[i]*sin(RadarTheta[i])/DisplayRatio)+ DisplayDy;
			//centerRaw.push_back(Point(x,y));
			//cout<<"P:" <<centerRaw[i].x<<","<<centerRaw[i].y<<endl;
			if (x >= 0 && x < RadarImageWdith && y >= 0 && y < RadarImageHeight)
			{
				 circle( binImg,Point(x,y),1,Scalar(255),-1);
			}
		}     
	}
	imshow("binImg",binImg);
	Mat element = getStructuringElement(MORPH_RECT, Size(1,2));
	Mat element2 = getStructuringElement(MORPH_RECT, Size(10,10));
	erode(binImg, binImg, element);
	morphologyEx(binImg, binImg, MORPH_OPEN, element);
	dilate(binImg, binImg, element2);
	morphologyEx(binImg, binImg, MORPH_CLOSE, element2);
	imshow("dilate",binImg);

	vector< vector<Point> > contours;	
	vector< vector<Point> > filterContours;	
	vector< Vec4i > hierarchy;	
	vector< Point2f> center;
	vector< float > radius;
	vector<Point2f> realPoint;
	

	findContours(binImg, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
	center.resize(contours.size());
	radius.resize(contours.size());
	//realPoint.resize(contours.size());
	for(int i = 0; i< contours.size(); i++)
	{
		minEnclosingCircle(Mat(contours[i]),center[i],radius[i]);//对轮廓进行多变形逼近
		circle(binImg,center[i],650/DisplayRatio,Scalar(255),1); 
		//cout<<"No."<<i<<" | P: "<< center[i].x<<","<<center[i].y<<endl;
		float realX = (center[i].x - DisplayDx) * DisplayRatio;
		float realY = (center[i].y - DisplayDy) * DisplayRatio;

		realPoint.push_back(Point2f(realX,realY));
		//cout<<"No."<<i<<" | P: "<< realPoint[i].x<<","<<realPoint[i].y<<endl;
	}
	imshow("findContours",binImg);
	// colar map
	Mat mapImg = Mat::zeros(RadarImageHeight,RadarImageWdith,CV_8UC3);
	circle(mapImg, Point(DisplayDx,DisplayDy),3, CV_RGB(255,255,255),-1);
	line(mapImg, Point(DisplayDx,DisplayDy), Point(DisplayDx+40,DisplayDy), Scalar(0,0,255),1);
	line(mapImg, Point(DisplayDx,DisplayDy), Point(DisplayDx,DisplayDy+40), Scalar(0,255,0),1);
	for(int i = 0; i< center.size(); i++)
	{
		circle(mapImg,center[i],650/DisplayRatio,Scalar(255,255,0),1,CV_AA); 
		circle(mapImg,center[i],100/DisplayRatio,Scalar(0,255,255),-1); 
	}
	imshow("Map",mapImg);
	////////////////////////////////////
	ukftest::laserPoint msg;
	vector <float> xvec;
	vector <float> yvec;
	for(int i = 0 ; i < realPoint.size(); i++)
	{
		// cm
		xvec.push_back(realPoint[i].x/10.0f);
		yvec.push_back(realPoint[i].y/10.0f);
	}

	// msg
	msg.header.stamp = ros::Time::now();
	msg.header.frame_id = "hokuyo_laser";
	msg.x =xvec;
	msg.y =yvec;
	if(realPoint.size() >0) msg.isBlocking = 1;
	else msg.isBlocking = 0;
	pub_xy. publish(msg);
	
}