/* * objective : get the gray level map of the input image and rescale it to the range [0-255] */ static void rescaleGrayLevelMat(const cv::Mat &inputMat, cv::Mat &outputMat, const float histogramClippingLimit) { // adjust output matrix wrt the input size but single channel std::cout<<"Input image rescaling with histogram edges cutting (in order to eliminate bad pixels created during the HDR image creation) :"<<std::endl; //std::cout<<"=> image size (h,w,channels) = "<<inputMat.size().height<<", "<<inputMat.size().width<<", "<<inputMat.channels()<<std::endl; //std::cout<<"=> pixel coding (nbchannel, bytes per channel) = "<<inputMat.elemSize()/inputMat.elemSize1()<<", "<<inputMat.elemSize1()<<std::endl; // rescale between 0-255, keeping floating point values cv::normalize(inputMat, outputMat, 0.0, 255.0, cv::NORM_MINMAX); // extract a 8bit image that will be used for histogram edge cut cv::Mat intGrayImage; if (inputMat.channels()==1) { outputMat.convertTo(intGrayImage, CV_8U); }else { cv::Mat rgbIntImg; outputMat.convertTo(rgbIntImg, CV_8UC3); cvtColor(rgbIntImg, intGrayImage, cv::COLOR_BGR2GRAY); } // get histogram density probability in order to cut values under above edges limits (here 5-95%)... usefull for HDR pixel errors cancellation cv::Mat dst, hist; int histSize = 256; calcHist(&intGrayImage, 1, 0, cv::Mat(), hist, 1, &histSize, 0); cv::Mat normalizedHist; normalize(hist, normalizedHist, 1, 0, cv::NORM_L1, CV_32F); // normalize histogram so that its sum equals 1 double min_val, max_val; minMaxLoc(normalizedHist, &min_val, &max_val); //std::cout<<"Hist max,min = "<<max_val<<", "<<min_val<<std::endl; // compute density probability cv::Mat denseProb=cv::Mat::zeros(normalizedHist.size(), CV_32F); denseProb.at<float>(0)=normalizedHist.at<float>(0); int histLowerLimit=0, histUpperLimit=0; for (int i=1;i<normalizedHist.size().height;++i) { denseProb.at<float>(i)=denseProb.at<float>(i-1)+normalizedHist.at<float>(i); //std::cout<<normalizedHist.at<float>(i)<<", "<<denseProb.at<float>(i)<<std::endl; if ( denseProb.at<float>(i)<histogramClippingLimit) histLowerLimit=i; if ( denseProb.at<float>(i)<1-histogramClippingLimit) histUpperLimit=i; } // deduce min and max admitted gray levels float minInputValue = (float)histLowerLimit/histSize*255; float maxInputValue = (float)histUpperLimit/histSize*255; std::cout<<"=> Histogram limits " <<"\n\t"<<histogramClippingLimit*100<<"% index = "<<histLowerLimit<<" => normalizedHist value = "<<denseProb.at<float>(histLowerLimit)<<" => input gray level = "<<minInputValue <<"\n\t"<<(1-histogramClippingLimit)*100<<"% index = "<<histUpperLimit<<" => normalizedHist value = "<<denseProb.at<float>(histUpperLimit)<<" => input gray level = "<<maxInputValue <<std::endl; //drawPlot(denseProb, "input histogram density probability", histLowerLimit, histUpperLimit); drawPlot(normalizedHist, "input histogram", histLowerLimit, histUpperLimit); // rescale image range [minInputValue-maxInputValue] to [0-255] outputMat-=minInputValue; outputMat*=255.0/(maxInputValue-minInputValue); // cut original histogram and back project to original image cv::threshold( outputMat, outputMat, 255.0, 255.0, 2 ); //THRESH_TRUNC, clips values above 255 cv::threshold( outputMat, outputMat, 0.0, 0.0, 3 ); //THRESH_TOZERO, clips values under 0 }
Mat TemplateMatching::run(Mat & src) { Mat img = src; // Source image to display Mat img_display; img.copyTo( img_display ); int result_cols; int result_rows; // Para minmaxLoc double minVal; double maxVal; Point minLoc; Point maxLoc; //guardar maximo global double MAX = 0; Point MAXLoc; int num; //cargar templates templ[0][0] = imread("Template/template/template11.jpg"); templ[0][1] = imread("Template/template/template12.jpg"); templ[0][2] = imread("Template/template/template13.jpg"); templ[0][3] = imread("Template/template/template14.jpg"); templ[1][0] = imread("Template/template/template21.jpg"); templ[1][1] = imread("Template/template/template22.jpg"); templ[1][2] = imread("Template/template/template23.jpg"); templ[1][3] = imread("Template/template/template24.jpg"); templ[2][0] = imread("Template/template/template31.jpg"); templ[2][1] = imread("Template/template/template32.jpg"); templ[2][2] = imread("Template/template/template33.jpg"); templ[2][3] = imread("Template/template/template34.jpg"); templ[3][0] = imread("Template/template/template41.jpg"); templ[3][1] = imread("Template/template/template42.jpg"); templ[3][2] = imread("Template/template/template43.jpg"); templ[3][3] = imread("Template/template/template44.jpg"); templ[4][0] = imread("Template/template/template51.jpg"); templ[4][1] = imread("Template/template/template52.jpg"); templ[4][2] = imread("Template/template/template53.jpg"); templ[4][3] = imread("Template/template/template54.jpg"); //FOR tamaños templates for (int i=0;i<5;i++) { // Matriz de resultados result_cols = img.cols - templ[i][0].cols + 1; result_rows = img.rows - templ[i][0].rows + 1; result[i].create( result_cols, result_rows, CV_32FC1 ); //FOR rotacion for (int j=0;j<4;j++) { // Matching y normalizacion matchTemplate( img, templ[i][j], result[i], CV_TM_CCOEFF_NORMED); //guardar maximo para esta rotacion de template minMaxLoc( result[i], &minVal, &maxVal, &minLoc, &maxLoc, Mat() ); //comparar con maximo global para este tamaño if (maxVal>MAX) { MAX = maxVal; num = j; MAXLoc = maxLoc; } normalize( result[i], result[i], 0, 1, NORM_MINMAX, -1, Mat() ); //buscar maximo minMaxLoc( result[i], &minVal, &maxVal, &minLoc, &maxLoc, Mat() ); } //termina FOR rotacion //buscar nuevamente aquella rotacion que arrojo mejor resultado matchTemplate( img, templ[i][num], result[i], CV_TM_CCOEFF_NORMED); minMaxLoc( result[i], &minVal, &maxVal, &minLoc, &maxLoc, Mat() ); // mostrar resultados rectangle( img_display, Point( maxLoc.x-10,maxLoc.y-10), Point( maxLoc.x+10 + templ[i][num].cols , maxLoc.y + templ[i][num].rows+10 ), Scalar::all(0), 2, 8, 0 ); rectangle( result[i], maxLoc, Point( maxLoc.x + templ[i][num].cols , maxLoc.y + templ[i][num].rows ), Scalar::all(0), 2, 150, 0 ); //termina FOR tamaños } // imshow( "result_window", result[4] ); //Mostrar mejor resultado de cada template imshow( "resultado MatchTemplate", img_display ); //comentar return img_display; //DEBIESE DEVOLVER EL RESULTADO? ( result[0] hasta [result[4] ) }
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); }
ofVec2f findMaxLocation(Mat& mat) { double minVal, maxVal; cv::Point minLoc, maxLoc; minMaxLoc(mat, &minVal, &maxVal, &minLoc, &maxLoc); return ofVec2f(maxLoc.x, maxLoc.y); }
//变角度线扫描法——改进后的线扫描法 void findCircleParameter::revisedScanLineMethod(Mat imgOrg, Point2i& center, int& radius, int threshold, int N) { Mat src, gray; src = imgOrg.clone(); cvtColor(src, gray, CV_BGR2GRAY); vector<Point> points; vector<double> distance; Size imgSize = src.size(); int x, y; double theta = 0; for (int n = 0; n < 2 * N; n++, theta = PI*n / (2 * N)) { //if (n == N||n==0) continue; int min1, min2; min1 = min2 = 255; int max1, max2; max1 = max2 = 0; int radius = 0; Point ptMax1(0, 0), ptMax2(0, 0); Point ptMin1(0, 0), ptMin2(0, 0); int flag = 0; double minVal, maxVal; if (0 == n) { for (int i = 0; i < imgSize.height; i++) { minMaxLoc(gray.row(i), &minVal, &maxVal, &ptMin1, &ptMax1); if ((maxVal - minVal)>threshold) { flag++; ptMax1.y = i; //cout << "horizontal top:" << endl; //cout << "ptMax1=(" << ptMax1.x << ", " << ptMax1.y << ")" << endl; points.push_back(ptMax1); goto top_label; } } top_label: #ifdef _SHOW_POINTS_ circle(src, ptMax1, 5, Scalar(0, 255, 255), -1); imshow("src", src); waitKey(); #endif for (int i = imgSize.height - 1; i >= 0; i--) { minMaxLoc(gray.row(i), &minVal, &maxVal, &ptMin2, &ptMax2); if ((maxVal - minVal) > threshold) { flag++; ptMax2.y = i; //cout << "horizontal bottom:" << endl; //cout << "ptMax2=(" << ptMax2.x << ", " << ptMax2.y << ")" << endl; //src.row(i) = Scalar(0, 0, 255); //src.row(i + 1) = Scalar(0, 0, 255); points.push_back(ptMax2); goto bottom_label; } } bottom_label: #ifdef _SHOW_POINTS_ circle(src, ptMax2, 5, Scalar(0, 255, 255), -1); line(src, ptMax1, ptMax2, Scalar(192, 192, 0), 2); imshow("src", src); waitKey(); #endif if (flag == 2) { distance.push_back(sqrt(pow(ptMax1.x - ptMax2.x, 2) + pow(ptMax1.y - ptMax2.y, 2))); } else if (flag == 1) { points.pop_back(); } } else if (0 < n&&n < N) { for (int i = 0; i < imgSize.width; i++) { for (int j = 0; j <= i; j++) { x = j; y = -tan(theta)*(x - i); Point ptCur(x, y); if (!ptCur.inside(Rect(0, 0, imgSize.width, imgSize.height))) { continue; } uchar I = gray.at<uchar>(ptCur); if (I > max1) { max1 = I; ptMax1 = ptCur; } if (I < min1) { min1 = I; } if (abs(max1 - min1) > threshold) { flag++; //cout << "jump outer1" << endl; //cout << "ptMax1=(" << ptMax1.x << ", " << ptMax1.y << ")" << endl; points.push_back(ptMax1); /* Point start, end; for (int k = 0; k <= i; k++) { x = k; y = -tan(theta)*(x - i); if (k == 0) { start = Point(x, y); } else if (k == i) { end = Point(x, y); } } line(src, start, end, Scalar(0, 0, 255), 2);*/ goto outer1; } } } outer1: #ifdef _SHOW_POINTS_ circle(src, ptMax1, 5, Scalar(0, 255, 255), -1); imshow("src", src); waitKey(); #endif for (int i = imgSize.width - 1; i >= 0; i--) { for (int j = i; j < imgSize.width; j++) { x = j; y = imgSize.height - 1 - tan(theta)*(x - i); Point ptCur(x, y); if (!ptCur.inside(Rect(0, 0, imgSize.width, imgSize.height))) { continue; } uchar I = gray.at<uchar>(ptCur); if (I > max2) { max2 = I; ptMax2 = ptCur; } if (I < min2) { min2 = I; } if (abs(max2 - min2) > threshold) { flag++; //cout << "jump outer2" << endl; //cout << "ptMax2=(" << ptMax2.x << ", " << ptMax2.y << ")" << endl; points.push_back(ptMax2); //Point start, end; //for (int k = i; k < imgSize.width; k++) //{ // x = k; // y = imgSize.height - 1 - tan(theta)*(x - i); // if (k == i) // { // start = Point(x, y); // } // else if (k == imgSize.width-1) // { // end = Point(x, y); // } //} //line(src, start, end, Scalar(0, 0, 255), 2); goto outer2; } } } outer2: ; #ifdef _SHOW_POINTS_ circle(src, ptMax2, 5, Scalar(0, 255, 255), -1); line(src, ptMax1, ptMax2, Scalar(192, 192, 0), 2); imshow("src", src); waitKey(); #endif if (flag == 2) { distance.push_back(sqrt(pow(ptMax1.x - ptMax2.x, 2) + pow(ptMax1.y - ptMax2.y, 2))); } else if (flag == 1) { points.pop_back(); } } else if (N == n) { for (int i = 0; i < imgSize.width; i++) { minMaxLoc(gray.col(i), &minVal, &maxVal, &ptMin1, &ptMax1); if ((maxVal - minVal)>threshold) { flag++; ptMax1.x = i; //cout << "vertical left:" << endl; //cout << "ptMax1=(" << ptMax1.x << ", " << ptMax1.y << ")" << endl; //src.col(i) = Scalar(0, 0, 255); //src.col(i - 1) = Scalar(0, 0, 255); points.push_back(ptMax1); goto left_label; } } left_label: #ifdef _SHOW_POINTS_ circle(src, ptMax1, 5, Scalar(0, 255, 255), -1); imshow("src", src); waitKey(); #endif for (int i = gray.cols - 1; i >= 0; i--) { minMaxLoc(gray.col(i), &minVal, &maxVal, &ptMin2, &ptMax2); if ((maxVal - minVal) > threshold) { flag++; ptMax2.x = i; //cout << "vertical right:" << endl; //cout << "ptMax1=(" << ptMax2.x << ", " << ptMax2.y << ")" << endl; points.push_back(ptMax2); //src.col(i) = Scalar(0, 0, 255); //src.col(i + 1) = Scalar(0, 0, 255); goto right_label; } } right_label: #ifdef _SHOW_POINTS_ circle(src, ptMax2, 5, Scalar(0, 255, 255), -1); line(src, ptMax1, ptMax2, Scalar(192, 192, 0), 2); imshow("src", src); waitKey(); #endif if (flag == 2) { distance.push_back(sqrt(pow(ptMax1.x - ptMax2.x, 2) + pow(ptMax1.y - ptMax2.y, 2))); } else if (flag == 1) { points.pop_back(); } } else if (N < n&&n < 2 * N) { for (int i = 0; i < imgSize.width; i++) { for (int j = 0; j <= i; j++) { x = j; y = imgSize.height - 1 - tan(theta)*(x - i); Point ptCur(x, y); if (!ptCur.inside(Rect(0, 0, imgSize.width, imgSize.height))) { continue; } uchar I = gray.at<uchar>(ptCur); if (I > max1) { max1 = I; ptMax1 = ptCur; } if (I < min1) { min1 = I; } if (abs(max1 - min1) > threshold) { flag++; //cout << "jump outer3" << endl; //cout << "ptMax1=(" << ptMax1.x << ", " << ptMax1.y << ")" << endl; points.push_back(ptMax1); //Point start, end; //for (int k = 0; k <= i; k++) //{ // x = k; // y = imgSize.height - 1 - tan(theta)*(x - i); // if (k == 0) // { // start = Point(x, y); // } // else if (k == i) // { // end = Point(x, y); // } //} //line(src, start, end, Scalar(0, 0, 255), 2); goto outer3; } } } outer3: #ifdef _SHOW_POINTS_ circle(src, ptMax1, 5, Scalar(0, 255, 255), -1); imshow("src", src); waitKey(); #endif for (int i = imgSize.width - 1 / 2; i >= 0; i--) { for (int j = i; j < imgSize.width; j++) { x = j; y = -tan(theta)*(x - i); Point ptCur(x, y); if (!ptCur.inside(Rect(0, 0, imgSize.width, imgSize.height))) { continue; } uchar I = gray.at<uchar>(ptCur); if (I > max2) { max2 = I; ptMax2 = ptCur; } if (I < min2) { min2 = I; } if (abs(max2 - min2) > threshold) { flag++; //cout << "jump outer4" << endl; //cout << "ptMax2=(" << ptMax2.x << ", " << ptMax2.y << ")" << endl; points.push_back(ptMax2); /* Point start, end; for (int k = i; k < imgSize.width; k++) { x = k; y = -tan(theta)*(x - i); if (k == i) { start = Point(x, y); } else if (k == imgSize.width - 1) { end = Point(x, y); } } line(src, start, end, Scalar(0, 0, 255), 2);*/ goto outer4; } } } outer4: ; #ifdef _SHOW_POINTS_ circle(src, ptMax2, 5, Scalar(0, 255, 255), -1); line(src, ptMax1, ptMax2, Scalar(192, 192, 0), 2); imshow("src", src); waitKey(); #endif if (flag == 2) { distance.push_back(sqrt(pow(ptMax1.x - ptMax2.x, 2) + pow(ptMax1.y - ptMax2.y, 2))); } else if (flag == 1) { points.pop_back(); } } else { cout << "The value of n is error!" << endl; break; } } //vector<Point>::iterator itero = points.begin(); //ofstream of("points.txt", ios::trunc | ios::out); //while (itero != points.end()) //{ // of << (*itero).x << ", " << (*itero).y << endl; // itero++; //} //of.close(); //find out validate points double mean = 0; vector<double>::iterator iter = distance.begin(); while (iter != distance.end()) { mean += *iter; iter++; } mean /= distance.size(); vector<Point> validPoints; for (int i = 0; i < distance.size(); i++) { if (distance.at(i) < mean) { validPoints.push_back(points.at(2 * i)); validPoints.push_back(points.at(2 * i + 1)); } } //figure out the center and radius of the circle with Kasa method if (!CircleFitByKasa(validPoints, center, radius)) { cout << "Revisied LineScan Method Failed, Because the Circle Fit Method failed!" << endl; return; } //#ifdef _DEBUG_ cout << "Use the Revised ScanLine Method:" << endl << "\tThe center is (" << center.x << ", " << center.y << ")" << endl << "\tThe radius is " << radius << endl; circle(src, center, radius, Scalar(0, 0, 255), src.cols / 300); circle(src, center, 5, Scalar(0, 255, 255), -1); //namedWindow("Revised ScanLine Method Result", CV_WINDOW_AUTOSIZE); //imshow("Revised ScanLine Method Result", src); imshow(win_name, src); //imwrite("Revised_Scan_ret.tiff", src); //waitKey(); //#endif }
bool Scraper::FindBestBMP(const searchType type, HBITMAP hBmp, const double threshold, MATCHPOINTS* match, char* matchedBMP) { // Convert HBITMAP to Mat unique_ptr<Gdiplus::Bitmap> pBitmap; pBitmap.reset(Gdiplus::Bitmap::FromHBITMAP(hBmp, NULL)); Mat img = CGdiPlus::CopyBmpToMat(pBitmap.get()); pBitmap.reset(); cvtColor( img, img, CV_BGRA2BGR ); // Find right image group imageType iType = type==searchTownHall ? townHall : type==searchLootCart ? lootCart : type==searchClashIcon ? clashIcon : type==searchPlayStoreOpenButton ? playStoreOpenButton : type==searchGoldStorage ? goldStorage : type==searchElixStorage ? elixStorage : type==searchDarkStorage ? darkStorage : (imageType) 0; int iTypeIndex = -1; for (int i = 0; i < (int) imageGroups.size(); i++) if (imageGroups[i].iType == iType) iTypeIndex = i; if (iTypeIndex == -1) return false; // Scan through each Mat in this image group double bestMaxVal = 0; Point bestMaxLoc(0, 0); string bestNeedlePath(""); for (int i = 0; i < (int) imageGroups[iTypeIndex].mats.size(); i++) { Mat result = FindMatch(img, imageGroups[iTypeIndex].mats[i]); // Localize the best match with minMaxLoc double minVal, maxVal; Point minLoc, maxLoc; minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc); bool beachSideOfSWLine = BeachSideOfSWLine((westPoint.x+maxLoc.x), (northPoint.y-10+maxLoc.y)); if (maxVal >= threshold && maxVal > bestMaxVal && (type!=searchTownHall || !beachSideOfSWLine)) { bestMaxVal = maxVal; bestMaxLoc = maxLoc; bestNeedlePath = imageGroups[iTypeIndex].imagePaths[i]; } } if (bestMaxVal > 0) { match->val = bestMaxVal; match->x = bestMaxLoc.x; match->y = bestMaxLoc.y; sprintf_s(matchedBMP, MAXSTRING, "%s", bestNeedlePath.c_str()); return true; } return false; }
void *image_show( void *) /*analiza imagem*/ { Mat frameCopy; Mat frameAnalize; Mat result; mouseInfo.event=-1; while(1) { pthread_mutex_lock(&in_frame); frameCopy=frame; pthread_mutex_unlock(&in_frame); pthread_mutex_lock(&in_mouseInfo); if(mouseInfo.x > 100 && mouseInfo.y >100 && mouseInfo.event==EVENT_LBUTTONDOWN) { Cerro; printf("Change! \n"); Rect myDim(mouseInfo.x-25,mouseInfo.y-25, 50, 50); frameAnalize = frameCopy(myDim).clone(); frameAnalize.copyTo(frameAnalize); } else if(mouseInfo.event == -1) { Rect myDim(100,100, 50, 50); frameAnalize = frameCopy(myDim); frameAnalize.copyTo(frameAnalize); mouseInfo.event=-2; } pthread_mutex_unlock(&in_mouseInfo); /// Create the result matrix int result_cols = frameCopy.cols - frameAnalize.cols + 1; int result_rows = frameCopy.rows - frameAnalize.rows + 1; result.create( result_cols, result_rows, CV_32FC1 ); /// Do the Matching and Normalize int match_method=1; //1-5 matchTemplate( frameCopy, frameAnalize, result, match_method ); normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() ); /// Localizing the best match with minMaxLoc double minVal; double maxVal; Point minLoc; Point maxLoc; Point matchLoc; minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() ); /// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED ) { matchLoc = minLoc; } else { matchLoc = maxLoc; } /// Show me what you got rectangle( frameCopy, matchLoc, Point( matchLoc.x + frameAnalize.cols , matchLoc.y + frameAnalize.rows ), Scalar::all(0), 2, 8, 0 ); rectangle( result, matchLoc, Point( matchLoc.x + frameAnalize.cols , matchLoc.y + frameAnalize.rows ), Scalar::all(0), 2, 8, 0 ); /// make a dif with the original and the matched Rect myDim2(matchLoc.x,matchLoc.y,50 , 50); Mat frameAnalizado = frameCopy(myDim2).clone(); Mat subt = frameAnalize - frameAnalizado; /// Make a simple text to debug char str[256]; sprintf(str, "x:%d/y:%d", matchLoc.x, matchLoc.y); putText(frameCopy, str, cvPoint(30,30), FONT_HERSHEY_COMPLEX_SMALL, 0.8, cvScalar(200,200,250), 1, CV_AA); sprintf(str, "maxVal:%.8f/minVal:%.8f", maxVal, minVal); putText(frameCopy, str, cvPoint(30,60), FONT_HERSHEY_COMPLEX_SMALL, 0.6, cvScalar(200,200,250), 1, CV_AA); /// Show de imgs imshow("image_show",frameCopy); namedWindow("image_show", CV_WINDOW_NORMAL); waitKey(30); imshow("analize",frameAnalize); namedWindow("analize", CV_WINDOW_NORMAL); waitKey(30); imshow("result",result); namedWindow("result", CV_WINDOW_NORMAL); waitKey(30); imshow("analizado",frameAnalizado); namedWindow("analizado", CV_WINDOW_NORMAL); waitKey(30); imshow("sub",subt); namedWindow("sub", CV_WINDOW_NORMAL); waitKey(30); usleep(10); } Cerro; printf("Image_show Down !\n"); return NULL; }
void CV_BilateralFilterTest::reference_bilateral_filter(const Mat &src, Mat &dst, int d, double sigma_color, double sigma_space, int borderType) { int cn = src.channels(); int i, j, k, maxk, radius; double minValSrc = -1, maxValSrc = 1; const int kExpNumBinsPerChannel = 1 << 12; int kExpNumBins = 0; float lastExpVal = 1.f; float len, scale_index; Size size = src.size(); dst.create(size, src.type()); CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) && src.type() == dst.type() && src.size() == dst.size() && src.data != dst.data ); if( sigma_color <= 0 ) sigma_color = 1; if( sigma_space <= 0 ) sigma_space = 1; double gauss_color_coeff = -0.5/(sigma_color*sigma_color); double gauss_space_coeff = -0.5/(sigma_space*sigma_space); if( d <= 0 ) radius = cvRound(sigma_space*1.5); else radius = d/2; radius = MAX(radius, 1); d = radius*2 + 1; // compute the min/max range for the input image (even if multichannel) minMaxLoc( src.reshape(1), &minValSrc, &maxValSrc ); if(std::abs(minValSrc - maxValSrc) < FLT_EPSILON) { src.copyTo(dst); return; } // temporary copy of the image with borders for easy processing Mat temp; copyMakeBorder( src, temp, radius, radius, radius, radius, borderType ); patchNaNs(temp); // allocate lookup tables vector<float> _space_weight(d*d); vector<int> _space_ofs(d*d); float* space_weight = &_space_weight[0]; int* space_ofs = &_space_ofs[0]; // assign a length which is slightly more than needed len = (float)(maxValSrc - minValSrc) * cn; kExpNumBins = kExpNumBinsPerChannel * cn; vector<float> _expLUT(kExpNumBins+2); float* expLUT = &_expLUT[0]; scale_index = kExpNumBins/len; // initialize the exp LUT for( i = 0; i < kExpNumBins+2; i++ ) { if( lastExpVal > 0.f ) { double val = i / scale_index; expLUT[i] = (float)std::exp(val * val * gauss_color_coeff); lastExpVal = expLUT[i]; } else expLUT[i] = 0.f; } // initialize space-related bilateral filter coefficients for( i = -radius, maxk = 0; i <= radius; i++ ) for( j = -radius; j <= radius; j++ ) { double r = std::sqrt((double)i*i + (double)j*j); if( r > radius ) continue; space_weight[maxk] = (float)std::exp(r*r*gauss_space_coeff); space_ofs[maxk++] = (int)(i*(temp.step/sizeof(float)) + j*cn); } for( i = 0; i < size.height; i++ ) { const float* sptr = (const float*)(temp.data + (i+radius)*temp.step) + radius*cn; float* dptr = (float*)(dst.data + i*dst.step); if( cn == 1 ) { for( j = 0; j < size.width; j++ ) { float sum = 0, wsum = 0; float val0 = sptr[j]; for( k = 0; k < maxk; k++ ) { float val = sptr[j + space_ofs[k]]; float alpha = (float)(std::abs(val - val0)*scale_index); int idx = cvFloor(alpha); alpha -= idx; float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx])); sum += val*w; wsum += w; } dptr[j] = (float)(sum/wsum); } } else { assert( cn == 3 ); for( j = 0; j < size.width*3; j += 3 ) { float sum_b = 0, sum_g = 0, sum_r = 0, wsum = 0; float b0 = sptr[j], g0 = sptr[j+1], r0 = sptr[j+2]; for( k = 0; k < maxk; k++ ) { const float* sptr_k = sptr + j + space_ofs[k]; float b = sptr_k[0], g = sptr_k[1], r = sptr_k[2]; float alpha = (float)((std::abs(b - b0) + std::abs(g - g0) + std::abs(r - r0))*scale_index); int idx = cvFloor(alpha); alpha -= idx; float w = space_weight[k]*(expLUT[idx] + alpha*(expLUT[idx+1] - expLUT[idx])); sum_b += b*w; sum_g += g*w; sum_r += r*w; wsum += w; } wsum = 1.f/wsum; b0 = sum_b*wsum; g0 = sum_g*wsum; r0 = sum_r*wsum; dptr[j] = b0; dptr[j+1] = g0; dptr[j+2] = r0; } } } }
bool ObjPatchMatcher::Match(const Mat& cimg, const Mat& dmap_raw, Mat& mask_map) { /* * precompute feature maps */ // gradient Mat gray_img, gray_img_float, edge_map; cvtColor(cimg, gray_img, CV_BGR2GRAY); gray_img.convertTo(gray_img_float, CV_32F, 1.f/255); Canny(gray_img, edge_map, 10, 50); cv::imshow("edge", edge_map); cv::imshow("color", cimg); cv::waitKey(10); Mat grad_x, grad_y, grad_mag; Sobel(gray_img_float, grad_x, CV_32F, 1, 0); Sobel(gray_img_float, grad_y, CV_32F, 0, 1); magnitude(grad_x, grad_y, grad_mag); // depth Mat dmap_float, pts3d, normal_map; if( use_depth ) { Feature3D feat3d; dmap_raw.convertTo(dmap_float, CV_32F); Mat cmp_mask; compare(dmap_float, 800, cmp_mask, CMP_LT); dmap_float.setTo(800, cmp_mask); compare(dmap_float, 7000, cmp_mask, CMP_GT); dmap_float.setTo(7000, cmp_mask); dmap_float = (dmap_float-800)/(7000-800); feat3d.ComputeKinect3DMap(dmap_float, pts3d, false); feat3d.ComputeNormalMap(pts3d, normal_map); } /* * start searching */ // init searcher //searcher.Build(patch_data, BruteForce_L2); // opencv bfmatcher has size limit: maximum 2^31 LSHCoder lsh_coder; if(use_code) { lsh_coder.Load(); } Mat score_map = Mat::zeros(edge_map.rows, edge_map.cols, CV_32F); Mat mask_vote_map = Mat::zeros(cimg.rows, cimg.cols, CV_32F); mask_map = Mat::zeros(cimg.rows, cimg.cols, CV_32F); Mat mask_count = Mat::zeros(cimg.rows, cimg.cols, CV_32S); // number of mask overlapped on each pixel Mat feat; int topK = 40; int total_cnt = countNonZero(edge_map); vector<VisualObject> query_patches; query_patches.reserve(total_cnt); cout<<"Start match..."<<endl; float max_dist = 0; int cnt = 0; char str[30]; double start_t = getTickCount(); //#pragma omp parallel for for(int r=patch_size.height/2; r<gray_img.rows-patch_size.height/2; r+=3) { for(int c=patch_size.width/2; c<gray_img.cols-patch_size.width/2; c+=3) { /*int rand_r = rand()%gray_img.rows; int rand_c = rand()%gray_img.cols; if(rand_r < patch_size.height/2 || rand_r > gray_img.rows-patch_size.height/2 || rand_c < patch_size.width/2 || rand_c > gray_img.cols-patch_size.width/2) continue;*/ int rand_r = r, rand_c = c; if(edge_map.at<uchar>(rand_r, rand_c) > 0) { cnt++; destroyAllWindows(); Rect box(rand_c-patch_size.width/2, rand_r-patch_size.height/2, patch_size.width, patch_size.height); MatFeatureSet featset; gray_img_float(box).copyTo(featset["gray"]); //grad_mag(box).copyTo(featset["gradient"]); if(use_depth) { normal_map(box).copyTo(featset["normal"]); dmap_float(box).copyTo(featset["depth"]); } ComputePatchFeat(featset, feat); vector<DMatch> matches; if(use_code) { BinaryCodes codes; HashKey key_val; lsh_coder.ComputeCodes(feat, codes); HashingTools<HashKeyType>::CodesToKey(codes, key_val); MatchCode(key_val, topK, matches); } else { MatchPatch(feat, topK, matches); } if(matches[0].distance < 0 || matches[0].distance > 1000) { cout<<"match dist: "<<matches[0].distance<<endl; double minv, maxv; cout<<norm(feat, patch_data.row(matches[0].trainIdx), NORM_L2)<<endl; minMaxLoc(feat, &minv, &maxv); cout<<minv<<" "<<maxv<<endl; cout<<feat<<endl<<endl; minMaxLoc(patch_data.row(matches[0].trainIdx), &minv, &maxv); cout<<minv<<" "<<maxv<<endl; cout<<patch_data.row(matches[0].trainIdx)<<endl; imshow("cimg", cimg); waitKey(0); } vector<vector<Mat>> pixel_mask_vals(patch_size.height, vector<Mat>(patch_size.width, Mat::zeros(1, topK, CV_32F))); VisualObject cur_query; cur_query.visual_data.bbox = box; cur_query.visual_data.mask = Mat::zeros(patch_size.height, patch_size.width, CV_32F); for(size_t i=0; i<topK; i++) { score_map.at<float>(rand_r,rand_c) += matches[i].distance; cur_query.visual_data.mask += patch_meta.objects[matches[i].trainIdx].visual_data.mask; for(int mr=0; mr<patch_size.height; mr++) for(int mc=0; mc<patch_size.width; mc++) { pixel_mask_vals[mr][mc].at<float>(i) = patch_meta.objects[matches[i].trainIdx].visual_data.mask.at<float>(mr, mc); } } score_map.at<float>(rand_r,rand_c) /= topK; cur_query.visual_data.mask /= topK; // average returned mask // compute mask quality Scalar mean_, std_; /*ofstream out("pixel_mask_std_100.txt", ios::app); for(int mr=0; mr<patch_size.height; mr++) for(int mc=0; mc<patch_size.width; mc++) { meanStdDev(pixel_mask_vals[mr][mc], mean_, std_); out<<std_.val[0]<<" "; } out<<endl;*/ meanStdDev(cur_query.visual_data.mask, mean_, std_); cur_query.visual_data.scores.push_back(mean_.val[0]); cur_query.visual_data.scores.push_back(std_.val[0]); Mat align_mask = Mat::zeros(cimg.rows, cimg.cols, CV_8U); int gt_mask_id = patch_meta.objects[matches[0].trainIdx].meta_data.category_id; if(gt_mask_id != -1) { Mat nn_mask = gt_obj_masks[gt_mask_id]; //imshow("gt mask", nn_mask*255); //waitKey(10); Rect gt_box = patch_meta.objects[matches[0].trainIdx].visual_data.bbox; Rect align_box = AlignBox(box, gt_box, cimg.cols, cimg.rows); vector<ImgWin> boxes; boxes.push_back(align_box); //ImgVisualizer::DrawWinsOnImg("alignbox", cimg, boxes); //waitKey(10); Rect target_box = Rect(box.x-(gt_box.x-align_box.x), box.y-(gt_box.y-align_box.y), align_box.width, align_box.height); cout<<target_box<<endl; nn_mask(align_box).copyTo(align_mask(target_box)); } align_mask.convertTo(align_mask, CV_32F); mask_map += align_mask * matches[0].distance; //*score_map.at<float>(r,c); //mask_count(box) = mask_count(box) + 1; //cout<<score_map.at<float>(r,c)<<endl; max_dist = MAX(max_dist, matches[0].distance); query_patches.push_back(cur_query); // vote object regions /*Point3f line_ori; int obj_pt_sign; ComputeDominantLine(cur_query.visual_desc.mask, box.tl(), line_ori, obj_pt_sign); for(int rr=0; rr<cimg.rows; rr++) for(int cc=0; cc<cimg.cols; cc++) { float line_val = line_ori.x*cc+line_ori.y*rr+line_ori.z; if((line_val>0?1:-1)==obj_pt_sign) mask_vote_map.at<float>(rr, cc)++; }*/ #ifdef VERBOSE // current patch Mat disp, patch_gray, patch_grad, patch_normal, patch_depth; disp = cimg.clone(); rectangle(disp, box, CV_RGB(255,0,0), 2); resize(gray_img(box), patch_gray, Size(50,50)); resize(grad_mag(box), patch_grad, Size(50,50)); Mat cur_mask; resize(cur_query.visual_desc.mask, cur_mask, Size(50,50)); if(use_depth) { resize(normal_map(box), patch_normal, Size(50,50)); normalize(dmap_float(box), patch_depth, 1, 0, NORM_MINMAX); patch_depth.convertTo(patch_depth, CV_8U, 255); //dmap_float(box).convertTo(patch_depth, CV_8U, 255); resize(patch_depth, patch_depth, Size(50,50)); } Mat onormal; sprintf_s(str, "query_gray_%d.jpg", cnt); imshow(str, patch_gray); imwrite(str, patch_gray); /*sprintf_s(str, "query_grad_%d.jpg", cnt); ImgVisualizer::DrawFloatImg(str, patch_grad, onormal, true); imwrite(str, onormal);*/ sprintf_s(str, "query_depth_%d.jpg", cnt); imshow(str, patch_depth); imwrite(str, patch_depth); sprintf_s(str, "query_normal_%d.jpg", cnt); ImgVisualizer::DrawNormals(str, patch_normal, onormal, true); imwrite(str, onormal); sprintf_s(str, "query_box_%d.jpg", cnt); imshow(str, disp); imwrite(str, disp); //imshow("align mask", align_mask*255); cur_mask.convertTo(cur_mask, CV_8U, 255); sprintf_s(str, "query_tmask_%d.jpg", cnt); imshow(str, cur_mask); imwrite(str, cur_mask); // show match results vector<Mat> res_imgs(topK); vector<Mat> res_gradients(topK); vector<Mat> res_normals(topK); vector<Mat> res_depth(topK); vector<Mat> db_boxes(topK); vector<Mat> res_masks(topK); for(size_t i=0; i<topK; i++) { VisualObject& cur_obj = patch_meta.objects[matches[i].trainIdx]; // mask cur_obj.visual_desc.mask.convertTo(res_masks[i], CV_8U, 255); // gray cur_obj.visual_desc.extra_features["gray"].convertTo(res_imgs[i], CV_8U, 255); // gradient //ImgVisualizer::DrawFloatImg("", cur_obj.visual_desc.extra_features["gradient"], res_gradients[i], false); // 3D if(use_depth) { // normal tools::ImgVisualizer::DrawNormals("", cur_obj.visual_desc.extra_features["normal"], res_normals[i]); // depth normalize(cur_obj.visual_desc.extra_features["depth"], res_depth[i], 1, 0, NORM_MINMAX); res_depth[i].convertTo(res_depth[i], CV_8U, 255); //cur_obj.visual_desc.extra_features["depth"].convertTo(res_depth[i], CV_8U, 255); } // box on image db_boxes[i] = imread(patch_meta.objects[matches[i].trainIdx].imgpath); resize(db_boxes[i], db_boxes[i], Size(cimg.cols, cimg.rows)); rectangle(db_boxes[i], patch_meta.objects[matches[i].trainIdx].visual_desc.box, CV_RGB(255,0,0), 2); } Mat out_img; sprintf_s(str, "res_gray_%d.jpg", cnt); ImgVisualizer::DrawImgCollection(str, res_imgs, topK, Size(50,50), out_img); imwrite(str, out_img); sprintf_s(str, "res_normal_%d.jpg", cnt); ImgVisualizer::DrawImgCollection(str, res_normals, topK, Size(50,50), out_img); imwrite(str, out_img); sprintf_s(str, "res_depth_%d.jpg", cnt); ImgVisualizer::DrawImgCollection(str, res_depth, topK, Size(50,50), out_img); imwrite(str, out_img); /*sprintf_s(str, "res_gradient_%d.jpg", cnt); tools::ImgVisualizer::DrawImgCollection(str, res_gradients, topK, Size(50,50), out_img); imwrite(str, out_img);*/ sprintf_s(str, "res_mask_%d.jpg", cnt); tools::ImgVisualizer::DrawImgCollection(str, res_masks, topK, Size(50,50), out_img); imwrite(str, out_img); sprintf_s(str, "res_box_%d.jpg", cnt); tools::ImgVisualizer::DrawImgCollection(str, db_boxes, topK/2, Size(200, 200), out_img); imwrite(str, out_img); waitKey(0); #endif cout<<total_cnt--<<endl; } } } cout<<"match done. Time cost: "<<(getTickCount()-start_t)/getTickFrequency()<<"s."<<endl; //score_map(Rect(patch_size.width/2, patch_size.height/2, score_map.cols-patch_size.width/2, score_map.rows-patch_size.height/2)).copyTo(score_map); //score_map.setTo(max_dist, 255-edge_map); normalize(score_map, score_map, 1, 0, NORM_MINMAX); score_map = 1-score_map; //tools::ImgVisualizer::DrawFloatImg("bmap", score_map); mask_map /= max_dist; cout<<max_dist<<endl; normalize(mask_map, mask_map, 1, 0, NORM_MINMAX); //tools::ImgVisualizer::DrawFloatImg("maskmap", mask_map); //normalize(mask_vote_map, mask_vote_map, 1, 0, NORM_MINMAX); //ImgVisualizer::DrawFloatImg("vote map", mask_vote_map); //waitKey(0); return true; // pick top weighted points to see if they are inside objects // try graph-cut for region proposal // among all retrieved mask patch, select most discriminative one and do graph-cut sort(query_patches.begin(), query_patches.end(), [](const VisualObject& a, const VisualObject& b) { return a.visual_data.scores[1] > b.visual_data.scores[1]; }); for(size_t i=0; i<query_patches.size(); i++) { Mat disp_img = cimg.clone(); rectangle(disp_img, query_patches[i].visual_data.bbox, CV_RGB(255,0,0)); imshow("max std box", disp_img); Mat big_mask; resize(query_patches[i].visual_data.mask, big_mask, Size(50,50)); ImgVisualizer::DrawFloatImg("max std mask", big_mask); waitKey(0); // use mask to do graph-cut Mat fg_mask(cimg.rows, cimg.cols, CV_8U); fg_mask.setTo(cv::GC_PR_FGD); Mat th_mask; threshold(query_patches[i].visual_data.mask, th_mask, query_patches[i].visual_data.scores[0], 1, CV_THRESH_BINARY); th_mask.convertTo(th_mask, CV_8U); fg_mask(query_patches[i].visual_data.bbox).setTo(cv::GC_FGD, th_mask); th_mask = 1-th_mask; fg_mask(query_patches[i].visual_data.bbox).setTo(cv::GC_BGD, th_mask); cv::grabCut(cimg, fg_mask, Rect(0,0,1,1), Mat(), Mat(), 3, cv::GC_INIT_WITH_MASK); fg_mask = fg_mask & 1; disp_img.setTo(Vec3b(0,0,0)); cimg.copyTo(disp_img, fg_mask); cv::imshow("cut", disp_img); cv::waitKey(0); } float ths[] = {0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f, 0.2f}; for(size_t i=0; i<8; i++) { Mat th_mask; threshold(mask_map, th_mask, ths[i], 1, CV_THRESH_BINARY); char str[30]; sprintf_s(str, "%f", ths[i]); ImgVisualizer::DrawFloatImg(str, th_mask); waitKey(0); } return true; }
void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, int maxCorners, double qualityLevel, double minDistance, InputArray _mask, int blockSize, bool useHarrisDetector, double harrisK ) { Mat image = _image.getMat(), mask = _mask.getMat(); CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 ); CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) ); Mat eig, tmp; if( useHarrisDetector ) cornerHarris( image, eig, blockSize, 3, harrisK ); else cornerMinEigenVal( image, eig, blockSize, 3 ); double maxVal = 0; minMaxLoc( eig, 0, &maxVal, 0, 0, mask ); threshold( eig, eig, maxVal*qualityLevel, 0, THRESH_TOZERO ); dilate( eig, tmp, Mat()); Size imgsize = image.size(); vector<const float*> tmpCorners; // collect list of pointers to features - put them into temporary image for( int y = 1; y < imgsize.height - 1; y++ ) { const float* eig_data = (const float*)eig.ptr(y); const float* tmp_data = (const float*)tmp.ptr(y); const uchar* mask_data = mask.data ? mask.ptr(y) : 0; for( int x = 1; x < imgsize.width - 1; x++ ) { float val = eig_data[x]; if( val != 0 && val == tmp_data[x] && (!mask_data || mask_data[x]) ) tmpCorners.push_back(eig_data + x); } } sort( tmpCorners, greaterThanPtr<float>() ); vector<Point2f> corners; size_t i, j, total = tmpCorners.size(), ncorners = 0; if(minDistance >= 1) { // Partition the image into larger grids int w = image.cols; int h = image.rows; const int cell_size = cvRound(minDistance); const int grid_width = (w + cell_size - 1) / cell_size; const int grid_height = (h + cell_size - 1) / cell_size; std::vector<std::vector<Point2f> > grid(grid_width*grid_height); minDistance *= minDistance; for( i = 0; i < total; i++ ) { int ofs = (int)((const uchar*)tmpCorners[i] - eig.data); int y = (int)(ofs / eig.step); int x = (int)((ofs - y*eig.step)/sizeof(float)); bool good = true; int x_cell = x / cell_size; int y_cell = y / cell_size; int x1 = x_cell - 1; int y1 = y_cell - 1; int x2 = x_cell + 1; int y2 = y_cell + 1; // boundary check x1 = std::max(0, x1); y1 = std::max(0, y1); x2 = std::min(grid_width-1, x2); y2 = std::min(grid_height-1, y2); for( int yy = y1; yy <= y2; yy++ ) { for( int xx = x1; xx <= x2; xx++ ) { vector <Point2f> &m = grid[yy*grid_width + xx]; if( m.size() ) { for(j = 0; j < m.size(); j++) { float dx = x - m[j].x; float dy = y - m[j].y; if( dx*dx + dy*dy < minDistance ) { good = false; goto break_out; } } } } } break_out: if(good) { // printf("%d: %d %d -> %d %d, %d, %d -- %d %d %d %d, %d %d, c=%d\n", // i,x, y, x_cell, y_cell, (int)minDistance, cell_size,x1,y1,x2,y2, grid_width,grid_height,c); grid[y_cell*grid_width + x_cell].push_back(Point2f((float)x, (float)y)); corners.push_back(Point2f((float)x, (float)y)); ++ncorners; if( maxCorners > 0 && (int)ncorners == maxCorners ) break; } } } else { for( i = 0; i < total; i++ ) { int ofs = (int)((const uchar*)tmpCorners[i] - eig.data); int y = (int)(ofs / eig.step); int x = (int)((ofs - y*eig.step)/sizeof(float)); corners.push_back(Point2f((float)x, (float)y)); ++ncorners; if( maxCorners > 0 && (int)ncorners == maxCorners ) break; } } Mat(corners).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F); /* for( i = 0; i < total; i++ ) { int ofs = (int)((const uchar*)tmpCorners[i] - eig.data); int y = (int)(ofs / eig.step); int x = (int)((ofs - y*eig.step)/sizeof(float)); if( minDistance > 0 ) { for( j = 0; j < ncorners; j++ ) { float dx = x - corners[j].x; float dy = y - corners[j].y; if( dx*dx + dy*dy < minDistance ) break; } if( j < ncorners ) continue; } corners.push_back(Point2f((float)x, (float)y)); ++ncorners; if( maxCorners > 0 && (int)ncorners == maxCorners ) break; } */ }
bool CameraGigeSdkIc::grabSingleImage(Frame &frame, int camID){ // Retrieve a list with the video capture devices connected to the computer. DShowLib::Grabber::tVidCapDevListPtr pVidCapDevList = m_pGrabber->getAvailableVideoCaptureDevices(); if(pVidCapDevList == 0 || pVidCapDevList->empty()){ cout << "No device available." << endl; return false; }else{ // Print available devices. int numCam = -1; for(int i = 0; i < pVidCapDevList->size(); i++){ cout << "(" << i << ") " << pVidCapDevList->at(i).c_str() << endl; if(camID == i){ numCam = i; break; } } if(numCam == -1){ return false; }else{ // Open the selected video capture device. m_pGrabber->openDev(pVidCapDevList->at(numCam)); /*cout << "Available video formats : " << endl; DShowLib::Grabber::tVidFmtDescListPtr DecriptionList; DecriptionList = m_pGrabber->getAvailableVideoFormatDescs(); for( DShowLib::Grabber::tVidFmtDescList::iterator pDescription = DecriptionList->begin(); pDescription != DecriptionList->end(); pDescription++ ) { printf("%s\n", (*pDescription)->toString().c_str()); }*/ DShowLib::tFrameHandlerSinkPtr pSink; cout << "Current bits per pixel : " << m_pGrabber->getVideoFormat().getBitsPerPixel() << endl; switch(frame.getBitDepth()){ case MONO_8 : m_pGrabber->setVideoFormat("Y8 (1280x960-1280x960)"); // Set the image buffer format to eY800. eY800 means monochrome, 8 bits (1 byte) per pixel. // Let the sink create a matching MemBufferCollection with 1 buffer. pSink = DShowLib::FrameHandlerSink::create( DShowLib::eY800, 1 ); break; case MONO_12 : m_pGrabber->setVideoFormat("Y16 (1280x960-1280x960)"); // Disable overlay. // http://www.theimagingsourceforums.com/archive/index.php/t-319880.html m_pGrabber->setOverlayBitmapPathPosition(DShowLib::ePP_NONE); // Set the image buffer format to eY16. eY16 means monochrome, 16 bits (2 byte) per pixel. // Let the sink create a matching MemBufferCollection with 1 buffer. pSink = DShowLib::FrameHandlerSink::create( DShowLib::eY16, 1 ); break; default: return false; break; } cout << "New video format : " << m_pGrabber->getVideoFormat().getBitsPerPixel() << endl; // Get properties. _DSHOWLIB_NAMESPACE::tIVCDPropertyItemsPtr pItems = m_pGrabber->getAvailableVCDProperties(); // Set Exposure time. int exposure = frame.getExposure(); long eMin = getPropertyRangeMin(DShowLib::VCDID_Exposure, pItems); long eMax = getPropertyRangeMax(DShowLib::VCDID_Exposure, pItems); long e = getPropertyValue(DShowLib::VCDID_Exposure, pItems); cout << "Previous exposure time value : " << e << endl; if(exposure <= eMax && exposure >= eMin){ setPropertyValue(DShowLib::VCDID_Exposure, (long)exposure, pItems); cout << "New exposure time value : " << getPropertyValue(DShowLib::VCDID_Exposure, pItems) << endl; }else{ cout << "Fail to set exposure. Available range value is " << eMin << " to " << eMax << endl; return false; } // Set Gain (db) int gain = frame.getGain(); long gMin = getPropertyRangeMin(DShowLib::VCDID_Gain, pItems); long gMax = getPropertyRangeMax(DShowLib::VCDID_Gain, pItems); long g = getPropertyValue(DShowLib::VCDID_Gain, pItems); cout << "Previous gain value : " << g << endl; if(gain <= gMax && gain >= gMin){ setPropertyValue(DShowLib::VCDID_Gain, (long)gain, pItems); cout << "New gain value : " << getPropertyValue(DShowLib::VCDID_Gain, pItems) << endl; }else{ cout << "Fail to set gain. Available range value is " << gMin << " to " << gMax << endl; return false; } // Set the sink. m_pGrabber->setSinkType(pSink); // We use snap mode. pSink->setSnapMode(true); // Prepare the live mode, to get the output size if the sink. if(!m_pGrabber->prepareLive(false)){ std::cerr << "Could not render the VideoFormat into a eY800 sink."; return false; } // Retrieve the output type and dimension of the handler sink. // The dimension of the sink could be different from the VideoFormat, when // you use filters. DShowLib::FrameTypeInfo info; pSink->getOutputFrameType(info); cout << info.getBitsPerPixel() << endl; Mat newImg; DShowLib::Grabber::tMemBufferCollectionPtr pCollection; switch(info.getBitsPerPixel()){ case 8 : { newImg = Mat(info.dim.cy, info.dim.cx, CV_8UC1, Scalar(0)); BYTE* pBuf[1]; // Allocate image buffers of the above calculate buffer size. pBuf[0] = new BYTE[info.buffersize]; // Create a new MemBuffer collection that uses our own image buffers. pCollection = DShowLib::MemBufferCollection::create( info, 1, pBuf ); if( pCollection == 0 || !pSink->setMemBufferCollection(pCollection)){ std::cerr << "Could not set the new MemBufferCollection, because types do not match."; return false; } m_pGrabber->startLive(false); pSink->snapImages(1); memcpy(newImg.ptr(), pBuf[0], info.buffersize); } break; case 16 : { newImg = Mat(info.dim.cy, info.dim.cx, CV_16UC1, Scalar(0)); BYTE * pBuf[1]; // Allocate image buffers of the above calculate buffer size. pBuf[0] = new BYTE[info.buffersize]; // Create a new MemBuffer collection that uses our own image buffers. pCollection = DShowLib::MemBufferCollection::create(info, 1, pBuf); if(pCollection == 0 || !pSink->setMemBufferCollection(pCollection)){ std::cerr << "Could not set the new MemBufferCollection, because types do not match."; return false; } m_pGrabber->startLive(false); pSink->snapImages(1); memcpy(newImg.ptr(), pBuf[0], info.buffersize); } break; default: return false; break; } m_pGrabber->stopLive(); m_pGrabber->closeDev(); //Timestamping. string acquisitionDate = TimeDate::localDateTime(microsec_clock::universal_time(),"%Y:%m:%d:%H:%M:%S"); boost::posix_time::ptime time = boost::posix_time::microsec_clock::universal_time(); string acqDateInMicrosec = to_iso_extended_string(time); frame = Frame(newImg, 0, 0, acquisitionDate); frame.setAcqDateMicro(acqDateInMicrosec); frame.setFPS(0); //cout << "save " << endl; //pCollection->save( "yio*.bmp" ); double minVal, maxVal; minMaxLoc(newImg, &minVal, &maxVal); cout << "minVal :" << minVal << endl; cout << "maxVal :" << maxVal << endl; unsigned short * ptr; double t = (double)getTickCount(); for(int i = 0; i < newImg.rows; i++){ ptr = newImg.ptr<unsigned short>(i); for(int j = 0; j < newImg.cols; j++){ ptr[j] = ptr[j] >> 4; } } t = (((double)getTickCount() - t )/getTickFrequency())*1000; cout << "time decalage : " << t << endl; minMaxLoc(newImg, &minVal, &maxVal); cout << "minVal :" << minVal << endl; cout << "maxVal :" << maxVal << endl; } } return true; }
static Mat inverseAndWiener(Mat& s, Mat& p, double snr, bool inverse) { const bool wiener = !inverse; // Pad input image to avoid ringing artifacts along image borders. int bH = p.cols; int bV = p.rows; Mat sBorder; copyMakeBorder(s, sBorder, bV, bV, bH, bH, BORDER_REPLICATE); // Allocate some memory like it is going out of style. Mat pBigShifted = Mat::zeros(sBorder.size(), CV_32F); Mat P = Mat::zeros(sBorder.size(), CV_32F); Mat S = Mat::zeros(sBorder.size(), CV_32F); Mat OApprox = Mat::zeros(sBorder.size(), CV_32F); Mat oApprox = Mat::zeros(sBorder.size(), CV_32F); // Shift kernel. const int pHalf = p.rows / 2; circShiftXXX(p, pBigShifted, -pHalf, -pHalf); // Transform shifted kernel and degrated input image into frequency domain. // Note: DFT_COMPLEX_OUTPUT means that we want the complex result to be stored // in a two-channel matrix as opposed to the default compressed output. dft(pBigShifted, P, DFT_COMPLEX_OUTPUT); dft(sBorder, S, DFT_COMPLEX_OUTPUT); if (inverse) { const double epsilon = 0.05f; // Remove frequencies whose magnitude is below epsilon * max(freqKernel magnitude). double maxMagnitude; minMaxLoc(abs(P), 0, &maxMagnitude); const double threshold = maxMagnitude * epsilon; for (int ri = 0; ri < P.rows; ri++) { for (int ci = 0; ci < P.cols; ci++) { if (norm(P.at<Vec2f>(ri, ci)) < threshold) { P.at<Vec2f>(ri, ci) = threshold; } } } } // OpenCV only provides a multiplication operation for complex matrices, so we need // to calculate the inverse (1/H) of our filter spectrum first. Since it is complex // we need to compute 1/H = H*/(HH*) = H*/(Re(H)^2+Im(H)^2), where H* -> complex conjugate of H. // Multiply spectrum of the degrated image with the complex conjugate of the frequency spectrum // of the filter. const bool conjFreqKernel = true; mulSpectrums(S, P, OApprox, DFT_COMPLEX_OUTPUT, conjFreqKernel); // I * H* // Split kernel spectrum into real and imaginary parts. Mat PChannels[] = {Mat::zeros(sBorder.size(), CV_32F), Mat::zeros(sBorder.size(), CV_32F)}; split(P, PChannels); // 0:real, 1:imaginary // Calculate squared magnitude (Re(H)^2 + Im(H)^2) of filter spectrum. Mat freqKernelSqMagnitude = Mat::zeros(sBorder.rows, sBorder.cols, CV_32F); magnitude(PChannels[0], PChannels[1], freqKernelSqMagnitude); // freqKernelSqMagnitude = magnitude pow(PChannels[0], 2, freqKernelSqMagnitude); // freqKernelSqMagnitude = magnitude^2 = Re(H)^2 + Im(H)^2 if (wiener) { // Add 1 / SNR^2 to the squared filter kernel magnitude. freqKernelSqMagnitude += 1 / pow(snr, 2.0); } // Split frequency spectrum of degradedPadded image into real and imaginary parts. Mat OApproxChannels[] = {Mat::zeros(sBorder.size(), CV_32FC1), Mat::zeros(sBorder.size(), CV_32F)}; split(OApprox, OApproxChannels); // Divide each plane by the squared magnitude of the kernel frequency spectrum. // What we have done up to this point: (I * H*) / (Re(H)^2 + Im(H)^2) = I/H divide(OApproxChannels[0], freqKernelSqMagnitude, OApproxChannels[0]); // Re(I) / (Re(H)^2 + Im(H)^2) divide(OApproxChannels[1], freqKernelSqMagnitude, OApproxChannels[1]); // Im(I) / (Re(H)^2 + Im(H)^2) // Merge real and imaginary parts of the image frequency spectrum. merge(OApproxChannels, 2, OApprox); // Inverse DFT. // Note: DFT_REAL_OUTPUT means that we want the output to be a one-channel matrix again. dft(OApprox, oApprox, DFT_INVERSE | DFT_SCALE | DFT_REAL_OUTPUT); // Crop output image to original size. oApprox = oApprox(Rect(bH, bV, oApprox.cols - (bH * 2), oApprox.rows - (bV * 2))); return oApprox; }
/** @function doHarris */ int Panorama::doHarris() { Mat R; Mat Rtemp; // Corner Response function Mat Ix, Iy, Ixy, Ix2, Iy2; // the second moment eigenvalues function double maxValtemp, minValtemp; double minVal; double maxVal; int sigma = 3; // Gaussian sigma float k = 0.04; // the alpha of Response function int aperture_size =3, block_size = 3; double scale = 1.0; // parameters of sobel first order derivative. char* window = "Harris."; // the name of Harris result ///////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////// cout << "Processing Harris Corner Detector..." << endl; /* Initialize the corner response function and the temp mat */ R = Mat::zeros( srcGray.size(), CV_32FC1 ); Rtemp = Mat::zeros( srcGray.size(), CV_32FC1 ); /* Use Sobel function to calculate the first order derivative of both x and y */ Sobel( srcGray, Ix, CV_32F, 1, 0, aperture_size, scale, 0, BORDER_DEFAULT ); Sobel( srcGray, Iy, CV_32F, 0, 1, aperture_size, scale, 0, BORDER_DEFAULT ); /* Calculate the Gaussian Derivative */ GaussianBlur(Iy, Iy, Size(block_size, block_size), sigma, 0 ,BORDER_DEFAULT); GaussianBlur(Ix, Ix, Size(block_size, block_size), sigma, 0 ,BORDER_DEFAULT); /* Calculate the square of each intensity */ pow(Ix,2,Ix2); pow(Iy,2,Iy2); /* Calculate the Gaussian Derivative */ GaussianBlur(Iy2, Iy2, Size(block_size, block_size), sigma, 0 ,BORDER_DEFAULT); GaussianBlur(Ix2, Ix2, Size(block_size, block_size), sigma, 0 ,BORDER_DEFAULT); /* Calculate the Corner Response function */ for( int j = 0; j < srcGray.rows; j++ ) { for( int i = 0; i < srcGray.cols; i++ ) { float lambda_1 = Ix2.at<float>( j, i, 0); float lambda_2 = Iy2.at<float>( j, i, 0); Rtemp.at<float>(j, i, 0) = lambda_1 * lambda_2 - k * pow( ( lambda_1 + lambda_2 ), 2 ); } } minMaxLoc( Rtemp, &minValtemp, &maxValtemp, 0, 0, Mat() ); /* Normalize Corner Response function as the maxium value is 1 */ for( int j = 0; j < srcGray.rows; j++ ) { for( int i = 0; i < srcGray.cols; i++ ) { R.at<float>(j, i) = 1 / maxValtemp * Rtemp.at<float>(j, i, 0); } } /* Find local maxima of response function (nonmaximum suppression)*/ minMaxLoc( R, &minVal, &maxVal, 0, 0, Mat() ); /* Create Window */ namedWindow( window, CV_WINDOW_AUTOSIZE ); int currentLevel = 5; int maxLevel = 100; double threshold = ( maxVal - minVal ) * currentLevel/maxLevel ; for( int j = 0; j < srcGray.rows; j++ ) { for( int i = 0; i < srcGray.cols; i++ ) { if( R.at<float>(j,i) > threshold) { circle( srcCopy, Point(i,j), 4, Scalar(255,255,255), 0, 0, 0 ); } } } imshow( window, srcCopy ); /* delete &minVal; delete &maxVal; delete &maxValtemp; delete &minValtemp; delete &R; delete &Rtemp; delete &Ix; delete &Iy; delete &Ix2; delete &Iy2; delete &Ixy; */ return(0); }
bool Scraper::FindAllBMPs(const searchType type, HBITMAP hBmp, const double threshold, const int maxMatch, vector<MATCHPOINTS> &matches) { // Convert HBITMAP to Mat unique_ptr<Gdiplus::Bitmap> pBitmap; pBitmap.reset(Gdiplus::Bitmap::FromHBITMAP(hBmp, NULL)); Mat img = CGdiPlus::CopyBmpToMat(pBitmap.get()); pBitmap.reset(); cvtColor( img, img, CV_BGRA2BGR ); // Find right image group imageType iType = type==searchGoldStorage ? goldStorage : type==searchElixStorage ? elixStorage : type==searchDarkStorage ? darkStorage : type==searchLootCollector ? collector : type==searchLootBubble ? lootBubble : type==searchDonateButton ? donateButton : (imageType) 0; int iTypeIndex = -1; for (int i = 0; i < (int) imageGroups.size(); i++) if (imageGroups[i].iType == iType) iTypeIndex = i; if (iTypeIndex == -1) return false; // Scan through each Mat in this image group int count = 0; for (int i = 0; i < (int) imageGroups[iTypeIndex].mats.size(); i++) { // Get matches for this image Mat result( FindMatch(img, imageGroups[iTypeIndex].mats[i]) ); // Parse through matches in result set while (count < maxMatch) { double minVal, maxVal; Point minLoc, maxLoc; minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc); // Fill haystack with pure green so we don't match this same location rectangle(img, maxLoc, cv::Point(maxLoc.x + imageGroups[iTypeIndex].mats[i].cols, maxLoc.y + imageGroups[iTypeIndex].mats[i].rows), CV_RGB(0,255,0), 2); // Fill results array with lo vals, so we don't match this same location floodFill(result, maxLoc, 0, 0, Scalar(0.1), Scalar(1.0)); if (maxVal >= threshold && maxVal > 0) { // Check if this point is within 10 pixels of an existing match to avoid dupes bool alreadyFound = false; for (int k=0; k<count; k++) { if (DistanceBetweenTwoPoints((double) maxLoc.x, (double) maxLoc.y, (double) matches.at(k).x, (double) matches.at(k).y) < 10.0) { alreadyFound = true; break; } } // Add matched location to the vector if (alreadyFound == false) { MATCHPOINTS match; match.val = maxVal; match.x = maxLoc.x; match.y = maxLoc.y; matches.push_back(match); count++; } } else { break; } } if (count >= maxMatch) break; } return true; }
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; }
/******** STCTracker: calculate the confidence map and find the max position *******/ void STCTracker::tracking(const Mat frame, Rect &trackBox,Rect &boxRegion,int FrameNum) { Mat gray; cvtColor(frame, gray, CV_RGB2GRAY); // normalized by subtracting the average intensity of that region Scalar average = mean(gray(cxtRegion)); Mat context; gray(cxtRegion).convertTo(context, CV_64FC1, 1.0, - average[0]); // multiplies a Hamming window to reduce the frequency effect of image boundary context = context.mul(hammingWin); // step 1: Get context prior probability //cout<<"context "<<context.rows<<" "<<context.cols<<endl; getCxtPriorPosteriorModel(context); // step 2-1: Execute 2D DFT for prior probability Mat priorFourier; Mat planes1[] = {cxtPriorPro, Mat::zeros(cxtPriorPro.size(), CV_64F)}; merge(planes1, 2, priorFourier); dft(priorFourier, priorFourier); // step 2-2: Execute 2D DFT for conditional probability Mat STCModelFourier; Mat planes2[] = {STCModel, Mat::zeros(STCModel.size(), CV_64F)}; merge(planes2, 2, STCModelFourier); dft(STCModelFourier, STCModelFourier); // step 3: Calculate the multiplication Mat postFourier; complexOperation(STCModelFourier, priorFourier, postFourier, 0); // step 4: Execute 2D inverse DFT for posterior probability namely confidence map Mat confidenceMap; dft(postFourier, confidenceMap, DFT_INVERSE | DFT_REAL_OUTPUT| DFT_SCALE); // step 5: Find the max position Point point; double maxVal; minMaxLoc(confidenceMap, 0, &maxVal, 0, &point); maxValue.push_back(maxVal); /***********update scale by Eq.(15)**********/ if (FrameNum%(num+2)==0) { double scale_curr=0.0; for (int k=0;k<num;k++) { scale_curr+=sqrt(maxValue[FrameNum-k-2]/maxValue[FrameNum-k-3]); } scale=(1-lambda)*scale+lambda*(scale_curr/num); sigma=sigma*scale; } // step 6-1: update center, trackBox and context region center.x = cxtRegion.x + point.x; center.y = cxtRegion.y + point.y; trackBox.x = center.x - 0.5 * trackBox.width; trackBox.y = center.y - 0.5 * trackBox.height; trackBox &= Rect(0, 0, frame.cols, frame.rows); //boundary cxtRegion.x = center.x - cxtRegion.width * 0.5; if (cxtRegion.x<0) { cxtRegion.x=0; } cxtRegion.y = center.y - cxtRegion.height * 0.5; if (cxtRegion.y<0) { cxtRegion.y=0; } if (cxtRegion.x+cxtRegion.width>frame.cols) { cxtRegion.x=frame.cols-cxtRegion.width; } if (cxtRegion.y+cxtRegion.height>frame.rows) { cxtRegion.y=frame.rows-cxtRegion.height; } //cout<<"cxtRegionXY"<<cxtRegion.x<<" "<<cxtRegion.y<<endl; //cout<<"cxtRegion"<<cxtRegion.height<<" "<<cxtRegion.width<<endl; //cout<<"frame"<<frame.rows<<" "<<frame.cols<<endl; //cxtRegion &= Rect(0, 0, frame.cols, frame.rows); //cout<<"cxtRegionXY"<<cxtRegion.x<<" "<<cxtRegion.y<<endl; //cout<<"cxtRegion"<<cxtRegion.height<<" "<<cxtRegion.width<<endl; boxRegion=cxtRegion; // step 7: learn Spatio-Temporal context model from this frame for tracking next frame average = mean(gray(cxtRegion)); //cout<<"cxtRegion"<<cxtRegion.height<<" "<<cxtRegion.width<<endl; gray(cxtRegion).convertTo(context, CV_64FC1, 1.0, - average[0]); //cout<<"hamm"<<hammingWin.rows<<" "<<hammingWin.cols<<endl; context = context.mul(hammingWin); learnSTCModel(context); }
/* Normalize values in vector between a and b. In-place. */ void normalize(vector<double>& vec, double a, double b) { double minv, maxv; minMaxLoc(vec, &minv, &maxv); transform(vec.begin(), vec.end(), vec.begin(), [=](double d){return a + ((d - minv) * (b - a) / (maxv - minv));}); }
void NiblackSauvolaWolfJolion (Mat &im, Mat &output, NiblackVersion version, int winx, int winy, double k, double dR) { double m, s, max_s; double th=0; double min_I, max_I; int wxh = winx/2; int wyh = winy/2; int x_firstth= wxh; int x_lastth = im.cols-wxh-1; int y_lastth = im.rows-wyh-1; int y_firstth= wyh; // Create local statistics and store them in a double matrices Mat map_m = Mat::zeros (im.rows, im.cols, CV_32F); Mat map_s = Mat::zeros (im.rows, im.cols, CV_32F); max_s = calcLocalStats (im, map_m, map_s, winx, winy); minMaxLoc(im, &min_I, &max_I); Mat thsurf (im.rows, im.cols, CV_32F); // Create the threshold surface, including border processing // ---------------------------------------------------- for (int j = y_firstth ; j<=y_lastth; j++) { // NORMAL, NON-BORDER AREA IN THE MIDDLE OF THE WINDOW: for (int i=0 ; i <= im.cols-winx; i++) { m = map_m.fget(i+wxh, j); s = map_s.fget(i+wxh, j); // Calculate the threshold switch (version) { case NIBLACK: th = m + k*s; break; case SAUVOLA: th = m * (1 + k*(s/dR-1)); break; case WOLFJOLION: th = m + k * (s/max_s-1) * (m-min_I); break; default: exit (1); } thsurf.fset(i+wxh,j,th); if (i==0) { // LEFT BORDER for (int i=0; i<=x_firstth; ++i) thsurf.fset(i,j,th); // LEFT-UPPER CORNER if (j==y_firstth) for (int u=0; u<y_firstth; ++u) for (int i=0; i<=x_firstth; ++i) thsurf.fset(i,u,th); // LEFT-LOWER CORNER if (j==y_lastth) for (int u=y_lastth+1; u<im.rows; ++u) for (int i=0; i<=x_firstth; ++i) thsurf.fset(i,u,th); } // UPPER BORDER if (j==y_firstth) for (int u=0; u<y_firstth; ++u) thsurf.fset(i+wxh,u,th); // LOWER BORDER if (j==y_lastth) for (int u=y_lastth+1; u<im.rows; ++u) thsurf.fset(i+wxh,u,th); } // RIGHT BORDER for (int i=x_lastth; i<im.cols; ++i) thsurf.fset(i,j,th); // RIGHT-UPPER CORNER if (j==y_firstth) for (int u=0; u<y_firstth; ++u) for (int i=x_lastth; i<im.cols; ++i) thsurf.fset(i,u,th); // RIGHT-LOWER CORNER if (j==y_lastth) for (int u=y_lastth+1; u<im.rows; ++u) for (int i=x_lastth; i<im.cols; ++i) thsurf.fset(i,u,th); } for (int y=0; y<im.rows; ++y) for (int x=0; x<im.cols; ++x) { if (im.uget(x,y) >= thsurf.fget(x,y)) { output.uset(x,y,255); } else { output.uset(x,y,0); } } }