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); }
void VideoDemos( VideoCapture& surveillance_video, int starting_frame, bool clean_binary_images ) { Mat previous_gray_frame, optical_flow, optical_flow_display; Mat current_frame, thresholded_image, closed_image, first_frame; Mat current_frame_gray, running_average_background; Mat temp_running_average_background, running_average_difference; Mat running_average_foreground_mask, running_average_foreground_image; Mat selective_running_average_background; Mat temp_selective_running_average_background, selective_running_average_difference; Mat selective_running_average_foreground_mask, selective_running_average_background_mask, selective_running_average_foreground_image; double running_average_learning_rate = 0.01; surveillance_video.set(CV_CAP_PROP_POS_FRAMES,starting_frame); surveillance_video >> current_frame; first_frame = current_frame.clone(); cvtColor(current_frame, current_frame_gray, CV_BGR2GRAY); current_frame.convertTo(running_average_background, CV_32F); selective_running_average_background = running_average_background.clone(); int rad = running_average_background.depth(); MedianBackground median_background( current_frame, (float) 1.005, 1 ); Mat median_background_image, median_foreground_image; int codec = static_cast<int>(surveillance_video.get(CV_CAP_PROP_FOURCC)); // V3.0.0 update on next line. OLD CODE was BackgroundSubtractorMOG2 gmm; //(50,16,true); Ptr<BackgroundSubtractorMOG2> gmm = createBackgroundSubtractorMOG2(); Mat foreground_mask, foreground_image = Mat::zeros(current_frame.size(), CV_8UC3); double frame_rate = surveillance_video.get(CV_CAP_PROP_FPS); double time_between_frames = 1000.0/frame_rate; Timestamper* timer = new Timestamper(); int frame_count = 0; while ((!current_frame.empty()) && (frame_count++ < 1000))//1800)) { double duration = static_cast<double>(getTickCount()); vector<Mat> input_planes(3); split(current_frame,input_planes); cvtColor(current_frame, current_frame_gray, CV_BGR2GRAY); if (frame_count%2 == 0) // Skip every second frame so the flow is greater. { if ( previous_gray_frame.data ) { Mat lucas_kanade_flow; timer->ignoreTimeSinceLastRecorded(); LucasKanadeOpticalFlow(previous_gray_frame, current_frame_gray, lucas_kanade_flow); timer->recordTime("Lucas Kanade Optical Flow"); calcOpticalFlowFarneback(previous_gray_frame, current_frame_gray, optical_flow, 0.5, 3, 15, 3, 5, 1.2, 0); cvtColor(previous_gray_frame, optical_flow_display, CV_GRAY2BGR); drawOpticalFlow(optical_flow, optical_flow_display, 8, Scalar(0, 255, 0), Scalar(0, 0, 255)); timer->recordTime("Farneback Optical Flow"); char frame_str[100]; sprintf( frame_str, "Frame = %d", frame_count); Mat temp_output = JoinImagesHorizontally( current_frame, frame_str, optical_flow_display, "Farneback Optical Flow", 4 ); Mat optical_flow_output = JoinImagesHorizontally( temp_output, "", lucas_kanade_flow, "Lucas Kanade Optical Flow", 4 ); imshow("Optical Flow", optical_flow_output ); } std::swap(previous_gray_frame, current_frame_gray); } // Static background image Mat difference_frame, binary_difference; Mat structuring_element(3,3,CV_8U,Scalar(1)); timer->ignoreTimeSinceLastRecorded(); absdiff(current_frame,first_frame,difference_frame); cvtColor(difference_frame, thresholded_image, CV_BGR2GRAY); threshold(thresholded_image,thresholded_image,30,255,THRESH_BINARY); if (clean_binary_images) { morphologyEx(thresholded_image,closed_image,MORPH_CLOSE,structuring_element); morphologyEx(closed_image,binary_difference,MORPH_OPEN,structuring_element); current_frame.copyTo(binary_difference, thresholded_image); } else { binary_difference.setTo(Scalar(0,0,0)); current_frame.copyTo(binary_difference, thresholded_image); } timer->recordTime("Static difference"); // Running Average (three channel version) vector<Mat> running_average_planes(3); split(running_average_background,running_average_planes); accumulateWeighted(input_planes[0], running_average_planes[0], running_average_learning_rate); accumulateWeighted(input_planes[1], running_average_planes[1], running_average_learning_rate); accumulateWeighted(input_planes[2], running_average_planes[2], running_average_learning_rate); merge(running_average_planes,running_average_background); running_average_background.convertTo(temp_running_average_background,CV_8U); absdiff(temp_running_average_background,current_frame,running_average_difference); split(running_average_difference,running_average_planes); // Determine foreground points as any point with a difference of more than 30 on any one channel: threshold(running_average_difference,running_average_foreground_mask,30,255,THRESH_BINARY); split(running_average_foreground_mask,running_average_planes); bitwise_or( running_average_planes[0], running_average_planes[1], running_average_foreground_mask ); bitwise_or( running_average_planes[2], running_average_foreground_mask, running_average_foreground_mask ); if (clean_binary_images) { morphologyEx(running_average_foreground_mask,closed_image,MORPH_CLOSE,structuring_element); morphologyEx(closed_image,running_average_foreground_mask,MORPH_OPEN,structuring_element); } running_average_foreground_image.setTo(Scalar(0,0,0)); current_frame.copyTo(running_average_foreground_image, running_average_foreground_mask); timer->recordTime("Running Average"); // Running Average with selective update vector<Mat> selective_running_average_planes(3); // Find Foreground mask selective_running_average_background.convertTo(temp_selective_running_average_background,CV_8U); absdiff(temp_selective_running_average_background,current_frame,selective_running_average_difference); split(selective_running_average_difference,selective_running_average_planes); // Determine foreground points as any point with an average difference of more than 30 over all channels: Mat temp_sum = (selective_running_average_planes[0]/3 + selective_running_average_planes[1]/3 + selective_running_average_planes[2]/3); threshold(temp_sum,selective_running_average_foreground_mask,30,255,THRESH_BINARY_INV); // Update background split(selective_running_average_background,selective_running_average_planes); accumulateWeighted(input_planes[0], selective_running_average_planes[0], running_average_learning_rate,selective_running_average_foreground_mask); accumulateWeighted(input_planes[1], selective_running_average_planes[1], running_average_learning_rate,selective_running_average_foreground_mask); accumulateWeighted(input_planes[2], selective_running_average_planes[2], running_average_learning_rate,selective_running_average_foreground_mask); invertImage(selective_running_average_foreground_mask,selective_running_average_foreground_mask); accumulateWeighted(input_planes[0], selective_running_average_planes[0], running_average_learning_rate/3.0,selective_running_average_foreground_mask); accumulateWeighted(input_planes[1], selective_running_average_planes[1], running_average_learning_rate/3.0,selective_running_average_foreground_mask); accumulateWeighted(input_planes[2], selective_running_average_planes[2], running_average_learning_rate/3.0,selective_running_average_foreground_mask); merge(selective_running_average_planes,selective_running_average_background); if (clean_binary_images) { morphologyEx(selective_running_average_foreground_mask,closed_image,MORPH_CLOSE,structuring_element); morphologyEx(closed_image,selective_running_average_foreground_mask,MORPH_OPEN,structuring_element); } selective_running_average_foreground_image.setTo(Scalar(0,0,0)); current_frame.copyTo(selective_running_average_foreground_image, selective_running_average_foreground_mask); timer->recordTime("Selective Running Average"); // Median background timer->ignoreTimeSinceLastRecorded(); median_background.UpdateBackground( current_frame ); timer->recordTime("Median"); median_background_image = median_background.GetBackgroundImage(); Mat median_difference; absdiff(median_background_image,current_frame,median_difference); cvtColor(median_difference, median_difference, CV_BGR2GRAY); threshold(median_difference,median_difference,30,255,THRESH_BINARY); median_foreground_image.setTo(Scalar(0,0,0)); current_frame.copyTo(median_foreground_image, median_difference); // Update the Gaussian Mixture Model // V3.0.0 update on next line. OLD CODE was gmm(current_frame, foreground_mask); gmm->apply(current_frame, foreground_mask); // Clean the resultant binary (moving pixel) mask using an opening. threshold(foreground_mask,thresholded_image,150,255,THRESH_BINARY); Mat moving_incl_shadows, shadow_points; threshold(foreground_mask,moving_incl_shadows,50,255,THRESH_BINARY); absdiff( thresholded_image, moving_incl_shadows, shadow_points ); Mat cleaned_foreground_mask; if (clean_binary_images) { morphologyEx(thresholded_image,closed_image,MORPH_CLOSE,structuring_element); morphologyEx(closed_image,cleaned_foreground_mask,MORPH_OPEN,structuring_element); } else cleaned_foreground_mask = thresholded_image.clone(); foreground_image.setTo(Scalar(0,0,0)); current_frame.copyTo(foreground_image, cleaned_foreground_mask); timer->recordTime("Gaussian Mixture Model"); // Create an average background image (just for information) Mat mean_background_image; timer->ignoreTimeSinceLastRecorded(); // V3.0.0 update on next line. OLD CODE was gmm.getBackgroundImage(mean_background_image); gmm->getBackgroundImage(mean_background_image); duration = static_cast<double>(getTickCount())-duration; duration /= getTickFrequency()/1000.0; int delay = (time_between_frames>duration) ? ((int) (time_between_frames-duration)) : 1; char c = cvWaitKey(delay); char frame_str[100]; sprintf( frame_str, "Frame = %d", frame_count); Mat temp_static_output = JoinImagesHorizontally( current_frame, frame_str, first_frame, "Static Background", 4 ); Mat static_output = JoinImagesHorizontally( temp_static_output, "", binary_difference, "Foreground", 4 ); imshow("Static Background Model", static_output ); Mat temp_running_output = JoinImagesHorizontally( current_frame, frame_str, temp_running_average_background, "Running Average Background", 4 ); Mat running_output = JoinImagesHorizontally( temp_running_output, "", running_average_foreground_image, "Foreground", 4 ); imshow("Running Average Background Model", running_output ); Mat temp_selective_output = JoinImagesHorizontally( current_frame, frame_str, temp_selective_running_average_background, "Selective Running Average Background", 4 ); Mat selective_output = JoinImagesHorizontally( temp_selective_output, "", selective_running_average_foreground_image, "Foreground", 4 ); imshow("Selective Running Average Background Model", selective_output ); Mat temp_median_output = JoinImagesHorizontally( current_frame, frame_str, median_background_image, "Median Background", 4 ); Mat median_output = JoinImagesHorizontally( temp_median_output, "", median_foreground_image, "Foreground", 4 ); imshow("Median Background Model", median_output ); Mat temp_gaussian_output = JoinImagesHorizontally( current_frame, frame_str, mean_background_image, "GMM Background", 4 ); Mat gaussian_output = JoinImagesHorizontally( temp_gaussian_output, "", foreground_image, "Foreground", 4 ); imshow("Gaussian Mixture Model", gaussian_output ); timer->putTimes( current_frame ); imshow( "Computation Times", current_frame ); surveillance_video >> current_frame; } cvDestroyAllWindows(); }