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; }
/** * 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; } }
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; }
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; }
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; }
//! 字符分割与排序 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; }
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; }
// 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); } }
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; }
//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; }
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() */
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; }
// 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); }