static void onMouse(int event, int x, int y, int flags, void *param) { Mat im_draw; im_select.copyTo(im_draw); if(event == CV_EVENT_LBUTTONUP && !tl_set) { tl = Point(x,y); tl_set = true; } else if(event == CV_EVENT_LBUTTONUP && tl_set) { br = Point(x,y); br_set = true; screenLog(im_draw, "Initializing..."); } if (!tl_set) screenLog(im_draw, "Click on the top left corner of the object"); else { rectangle(im_draw, tl, Point(x, y), Scalar(255,0,0)); if (!br_set) screenLog(im_draw, "Click on the bottom right corner of the object"); } imshow(win_name_, im_draw); }
void callback(int, void *) { vector<Vec4i> lines; HoughLinesP(sent_to_callback, lines, 1, CV_PI / 180, lineThresh, minLineLength, maxLineGap); frame.copyTo(imgLines); imgLines = Scalar(0, 0, 0); vector<double> angles(lines.size()); lineCount = lines.size(); int j = 0; for (size_t i = 0; i < lines.size(); i++) { Vec4i l = lines[i]; line(imgLines, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 255, 0), 1, CV_AA); if ((l[2] == l[0]) || (l[1] == l[3])) continue; angles[j] = atan(static_cast<double>(l[2] - l[0]) / (l[1] - l[3])); j++; } imshow("LINES", imgLines + frame); // if num of lines are large than one or two stray lines won't affect the mean // much // but if they are small in number than mode has to be taken to save the error // due to those stray line if (lines.size() > 0 && lines.size() < 10) finalAngle = computeMode(angles); else if (lines.size() > 0) finalAngle = computeMean(angles); }
Point FingerTracker::GetFingerTopPosition(Mat thresholdedFingerFrame) const { uchar* ptr = thresholdedFingerFrame.data; for (int i = 0; i < thresholdedFingerFrame.rows * thresholdedFingerFrame.cols; i++) { if (*ptr++ == 255) { int y = i / thresholdedFingerFrame.cols; int x = i % thresholdedFingerFrame.cols; return Point(x,y); } } return Point(0,0); }
TEST(hole_filling_test, one_pixel_hole_on_random_image_should_produce_correct_target_rect) { // Make some random image data. Mat img = Mat(100, 100, CV_32FC1); randu(img, 0.f, 1.f); // Put a hole in middle. Mat hole = Mat::zeros(100, 100, CV_8U); // Set one pixel as hole hole(Rect(50, 50, 1, 1)) = 1; int patch_size = 7; HoleFilling hf(img, hole, patch_size); Rect expected_target_rect(Point(50 - 6, 50 - 6), Point(50 + 7, 50 + 7)); ASSERT_EQ(expected_target_rect, hf._target_rect_pyr[0]); }
void DeepPyramid::processFeatureMap(int filterIdx, const FeatureMap &map, vector<BoundingBox> &detectedObjects) const { Size mapSize = map.size(); Size filterSize = rootFilter[filterIdx]->getMapSize(); cout << "size: "<<map.size()<<endl; for (int width = 0; width < mapSize.width-filterSize.width; width+=stride) { for (int height = 0; height < mapSize.height-filterSize.height; height+=stride) { FeatureMap extractedMap; map.extractFeatureMap(Rect(Point(width, height), filterSize), extractedMap); if (rootFilter[filterIdx]->predict(extractedMap) == OBJECT) { BoundingBox box; box.norm5Box = Rect(Point(width, height), filterSize); box.confidence = std::fabs(rootFilter[filterIdx]->predict(extractedMap, true)); box.map = extractedMap; detectedObjects.push_back(box); } } } }
void DeepPyramid::constructImagePyramid(const Mat& img, vector<Mat>& imgPyramid) const { Size imgSize(img.cols, img.rows); cout << "Create image pyramid..." << endl; for (int level = 0; level < levelCount; level++) { Mat imgAtLevel(net->inputLayerSize(), CV_8UC3, Scalar::all(0)); Mat resizedImg; Size resizedImgSize = embeddedImageSize(imgSize, level); resize(img, resizedImg, resizedImgSize); resizedImg.copyTo(imgAtLevel(Rect(Point(0, 0), resizedImgSize))); imgPyramid.push_back(imgAtLevel); } cout << "Status: Success!" << endl; }
void DeepPyramid::extractFeatureMap(const Mat &img, vector<Rect> &objects, Size size, vector<FeatureMap> &omaps, vector<FeatureMap>& nmaps) { Size imgSize(img.cols, img.rows); vector<FeatureMap> featureMaps; constructFeatureMapPyramid(img, featureMaps); for (int i = 0; i < levelCount; i++) { vector<Rect> objectsAtLevel; for (size_t obj = 0; obj < objects.size(); obj++) { objectsAtLevel.push_back(originalRect2Norm5(objects[obj], i, imgSize)); } Size mapSize = featureMaps[i].size(); for (int w = 0; w < mapSize.width-size.width; w+=stride) for (int h = 0; h < mapSize.height-size.height; h+=stride) { bool isNegative = true; bool isPositive = false; for (size_t obj = 0; obj < objects.size(); obj++) { if (IOU(Rect(Point(w, h), size), objectsAtLevel[obj]) > 0.3) isNegative = false; if (IOU(Rect(Point(w, h), size), objectsAtLevel[obj]) > 0.7) isPositive = true; } FeatureMap map; if (isNegative) { featureMaps[i].extractFeatureMap(Rect(Point(w, h), size), map); nmaps.push_back(map); } if (isPositive) { featureMaps[i].extractFeatureMap(Rect(Point(w, h), size), map); omaps.push_back(map); } } } }
void DeepPyramid::detect(const vector<FeatureMap>& maps, vector<BoundingBox>& detectedObjects) const { for (size_t i = 0; i < rootFilter.size(); i++) for (size_t j = 0; j < levelCount; j++) { vector<BoundingBox> detectedObjectsAtLevel; Size size = maps[j].size(); double scale = 1 / pow(2.0, (levelCount - j -1)/2.0); size.width = size.width * scale; size.height = size.height * scale; FeatureMap map; maps[j].extractFeatureMap(Rect(Point(0, 0), size), map); processFeatureMap(i, map, detectedObjectsAtLevel); for (size_t k = 0; k < detectedObjectsAtLevel.size(); k++) { detectedObjectsAtLevel[k].level = j; detectedObjects.push_back(detectedObjectsAtLevel[k]); } } }
void FingerTracker::Display(Mat frame, Candidate candidate) const { if (candidate.m_found) { rectangle(frame, candidate.m_windowRect.tl(), candidate.m_windowRect.br(), Scalar(0, 255, 255)); rectangle(frame, candidate.m_fingerPosition - Point(2,2), candidate.m_fingerPosition + Point(2,2), Scalar(255, 0, 0), 2); } #if ENABLE_LINE_DRAWING Point prev(-1,-1); for (auto point : m_points) { if (prev.x != -1) { line(frame, prev, point, Scalar(0, 255, 0)); } prev = point; } #endif imshow("Camera", frame); }
void screenLog(Mat im_draw, const string text) { int font = cv::FONT_HERSHEY_SIMPLEX; float font_scale = 0.5; int thickness = 1; int baseline; Size text_size = cv::getTextSize(text, font, font_scale, thickness, &baseline); Point bl_text = Point(0,text_size.height); Point bl_rect = bl_text; bl_rect.y += baseline; Point tr_rect = bl_rect; tr_rect.x = im_draw.cols; //+= text_size.width; tr_rect.y -= text_size.height + baseline; rectangle(im_draw, bl_rect, tr_rect, Scalar(0,0,0), -1); putText(im_draw, text, bl_text, font, font_scale, Scalar(255,255,255)); }
void FingerTracker::Setup() { VideoCapture capture(0); if (!capture.isOpened()) { throw std::runtime_error("Could not start camera capture"); } int windowSize = 25; int Xpos = 200; int Ypos = 50; int update = 0; int buttonClicked = 0; namedWindow("RGB", CV_WINDOW_AUTOSIZE); createTrackbar("X", "RGB", &Xpos, 320, TrackBarCallback, (void*)&update); createTrackbar("Y", "RGB", &Ypos, 240, TrackBarCallback, (void*)&update); createTrackbar("Size", "RGB", &windowSize, 100, TrackBarCallback, (void*)&update); setMouseCallback("RGB", MouseCallback, (void*)&buttonClicked); Mat fingerWindowBackground, fingerWindowBackgroundGray; m_calibrationData.reset(new CalibrationData()); bool ticking = false; std::chrono::system_clock::time_point start = std::chrono::system_clock::now(); while (true) { Mat frame, frameHSV; if (capture.read(frame)) { flip(frame, frame, 1); pyrDown(frame, frame, Size(frame.cols / 2, frame.rows / 2)); Rect fingerWindow(Point(Xpos, Ypos), Size(windowSize, windowSize*3)); if (Xpos + windowSize >= frame.cols || Ypos + windowSize*3 >= frame.rows) { windowSize = 20; Xpos = 200; Ypos = 50; update = 0; } else if (buttonClicked == 1) { frame(fingerWindow).copyTo(fingerWindowBackground); cvtColor(fingerWindowBackground, fingerWindowBackgroundGray, CV_BGR2GRAY); buttonClicked = 0; update = 0; cvDestroyAllWindows(); } if (fingerWindowBackgroundGray.rows && !m_calibrationData->m_ready) { Mat diff, thd; absdiff(frame(fingerWindow), fingerWindowBackground, diff); std::vector<Mat> ch; split(diff, ch); threshold(ch[0], ch[0], m_calibrationDiffThreshold, 255, 0); threshold(ch[1], ch[1], m_calibrationDiffThreshold, 255, 0); threshold(ch[2], ch[2], m_calibrationDiffThreshold, 255, 0); thd = ch[0]; add(thd, ch[1], thd); add(thd, ch[2], thd); medianBlur(thd, thd, 5); Mat top, middle, bottom; Rect r1 = Rect(0, 0, thd.cols, thd.rows/3); Rect r2 = Rect(0, thd.rows / 3 + 1, thd.cols, thd.rows/3); Rect r3 = Rect(0, thd.rows * 2 / 3 + 1, thd.cols, thd.rows - thd.rows * 2 / 3 - 1); top = thd(r1); middle = thd(r2); bottom = thd(r3); auto percentageTop = countNonZero(top) * 100.0 / top.size().area(); auto percentageMiddle = countNonZero(middle) * 100.0 / middle.size().area(); auto percentageBottom = countNonZero(bottom) * 100.0 / bottom.size().area(); bool topReady = false; bool middleReady = false; bool bottomReady = false; Scalar c1, c2, c3; if (percentageTop > m_calibrationTopLowerThd && percentageTop < m_calibrationTopUpperThd) { topReady = true; c1 = Scalar(0, 255, 255); } else { c1 = Scalar(0, 0, 255); } if (percentageMiddle > m_calibrationMiddleLowerThd && percentageMiddle < m_calibrationMiddleUppperThd) { middleReady = true; c2 = Scalar(0, 255, 255); } else { c2 = Scalar(0, 0, 255); } if (percentageBottom > m_calibrationBottomLowerThd && percentageBottom < m_calibrationBottomUpperThd) { bottomReady = true; c3 = Scalar(0, 255, 255); } else { c3 = Scalar(0, 0, 255); } bool readyToGo = false; if (middleReady && topReady && bottomReady) { c1 = Scalar(0, 255, 0); c2 = Scalar(0, 255, 0); c3 = Scalar(0, 255, 0); if (!ticking) { start = std::chrono::system_clock::now(); ticking = true; } if (std::chrono::system_clock::now() - start > std::chrono::seconds(1)) { readyToGo = true; } } else { ticking = false; } #if ENABLE_DEBUG_WINDOWS std::stringstream ss; ss << percentageTop << ", " << percentageMiddle << ", " << percentageBottom; putText(frame, ss.str(), Point(0, getTextSize(ss.str(), 0, 0.5, 1, nullptr).height), 0, 0.5, Scalar::all(255), 1); cv::imshow("Thresholded", thd); #endif if (percentageTop >= m_calibrationTopUpperThd && percentageBottom >= m_calibrationBottomUpperThd && percentageMiddle >= m_calibrationMiddleUppperThd) { putText(frame, "Move finger away from camera", Point(0, getTextSize("Move finger away from camera", 0, 0.5, 1, nullptr).height), 0, 0.5, Scalar::all(255), 1); } else if (percentageTop <= m_calibrationTopLowerThd && percentageBottom <= m_calibrationBottomLowerThd && percentageMiddle <= m_calibrationMiddleLowerThd) { putText(frame, "Move finger closer to camera", Point(0, getTextSize("Move finger closer to camera", 0, 0.5, 1, nullptr).height), 0, 0.5, Scalar::all(255), 1); } if (readyToGo) { Mat framePatchHSV; cvtColor(frame(fingerWindow), framePatchHSV, CV_BGR2HSV); cvtColor(frame, frameHSV, CV_BGR2HSV); MatND hist; calcHist(&framePatchHSV, 1, m_calibrationData->m_channels, thd, hist, 2, m_calibrationData->m_histSize, (const float**)m_calibrationData->m_ranges, true, false); m_calibrationData->m_hist = hist; normalize(m_calibrationData->m_hist, m_calibrationData->m_hist, 0, 255, NORM_MINMAX, -1, Mat()); #if ENABLE_DEBUG_WINDOWS double maxVal=0; minMaxLoc(m_calibrationData->m_hist, 0, &maxVal, 0, 0); int scale = 10; Mat histImg = Mat::zeros(m_calibrationData->m_sbins*scale, m_calibrationData->m_hbins*10, CV_8UC3); for( int h = 0; h < m_calibrationData->m_hbins; h++) { for( int s = 0; s < m_calibrationData->m_sbins; s++ ) { float binVal = m_calibrationData->m_hist.at<float>(h, s); int intensity = cvRound(binVal*255/maxVal); rectangle( histImg, Point(h*scale, s*scale), Point( (h+1)*scale - 1, (s+1)*scale - 1), Scalar::all(intensity), CV_FILLED ); } } imshow("H-S Histogram", histImg); #endif m_calibrationData->m_ready = true; frame(fingerWindow).copyTo(m_calibrationData->m_fingerPatch); m_calibrationData->m_fingerRect = fingerWindow; m_currentCandidate.m_windowRect = fingerWindow; m_currentCandidate.m_fingerPosition = fingerWindow.tl(); return; } rectangle(frame, r1.tl() + fingerWindow.tl(), r1.br() + fingerWindow.tl(), c1); rectangle(frame, r2.tl() + fingerWindow.tl(), r2.br() + fingerWindow.tl(), c2); rectangle(frame, r3.tl() + fingerWindow.tl(), r3.br() + fingerWindow.tl(), c3); imshow("Calibration", frame); } else { int baseline = 0; putText(frame, "Adjust calibration window, click when ready", Point(0, getTextSize("Adjust calibration window", 0, 0.4, 2, &baseline).height), 0, 0.4, Scalar::all(255), 1); rectangle(frame, fingerWindow.tl(), fingerWindow.br(), Scalar(0, 0, 255)); imshow("RGB", frame); } auto key = cvWaitKey(10); if (char(key) == 27) { break; } } } capture.release(); }
void FingerTracker::Process(Mat frame) { #if ENABLE_DEBUG_WINDOWS Mat img_display; frame.copyTo(img_display); #endif // Process only Region of Interest i.e. region around current finger position Rect roi = Rect( Point(std::max(m_currentCandidate.m_windowRect.tl().x - m_roiSpanX, 0), std::max(m_currentCandidate.m_windowRect.tl().y - m_roiSpanY, 0)), Point(std::min(m_currentCandidate.m_windowRect.tl().x + m_roiSpanX + m_calibrationData->m_fingerPatch.cols, frame.cols), std::min(m_currentCandidate.m_windowRect.tl().y + m_roiSpanY + m_calibrationData->m_fingerPatch.rows, frame.rows))); Mat frameRoi; frame(roi).copyTo(frameRoi); //================TEMPLATE MATCHING int result_cols = frameRoi.cols - m_calibrationData->m_fingerPatch.cols + 1; int result_rows = frameRoi.rows - m_calibrationData->m_fingerPatch.rows + 1; assert(result_cols > 0 && result_rows > 0); Mat scoreMap; scoreMap.create(result_cols, result_rows, CV_32FC1); // Compare current frame roi region to known candidate // Using OpenCV matchTemplate function with correlation coefficient matching method matchTemplate(frameRoi, m_calibrationData->m_fingerPatch, scoreMap, 3); //================HISTOGRAM BACK PROJECTION MatND backProjection; Mat frameHSV; cvtColor(frameRoi, frameHSV, CV_BGR2HSV); calcBackProject(&frameHSV, 1, m_calibrationData->m_channels, m_calibrationData->m_hist, backProjection, (const float**)(m_calibrationData->m_ranges), 1, true); Mat backProjectionThresholded; threshold(backProjection, backProjectionThresholded, m_backProjectionThreshold, 255, 0); erode(backProjectionThresholded, backProjectionThresholded, getStructuringElement(MORPH_RECT, Size(2 * m_erosionSize + 1, 2 * m_erosionSize + 1), Point(m_erosionSize, m_erosionSize))); dilate(backProjectionThresholded, backProjectionThresholded, getStructuringElement(MORPH_RECT, Size(2 * m_dilationSize + 1, 2 * m_dilationSize + 1), Point(m_dilationSize, m_dilationSize))); Mat backProjectionThresholdedShifted; Rect shifted(Rect(m_calibrationData->m_fingerPatch.cols - 1, m_calibrationData->m_fingerPatch.rows - 1, scoreMap.cols, scoreMap.rows)); backProjectionThresholded(shifted).copyTo(backProjectionThresholdedShifted); Mat maskedOutScoreMap(scoreMap.size(), CV_8U); scoreMap.copyTo(maskedOutScoreMap, backProjectionThresholdedShifted); //====================Localizing the best match with minMaxLoc double minVal; double maxVal; Point minLoc; Point maxLoc; Point matchLoc; minMaxLoc(maskedOutScoreMap, &minVal, &maxVal, &minLoc, &maxLoc, Mat()); matchLoc = maxLoc + roi.tl(); m_currentCandidate.m_confidence = static_cast<float>(maxVal); if (maxVal > m_candidateDetecionConfidenceThreshold) { m_currentCandidate.m_found = true; m_currentCandidate.m_windowRect = Rect(matchLoc, Point(matchLoc.x + m_calibrationData->m_fingerPatch.cols , matchLoc.y + m_calibrationData->m_fingerPatch.rows)); //================Find finger position Mat fingerWindowThresholded; backProjectionThresholded(Rect(maxLoc, Point(maxLoc.x + m_calibrationData->m_fingerPatch.cols , maxLoc.y + m_calibrationData->m_fingerPatch.rows))).copyTo(fingerWindowThresholded); m_currentCandidate.m_fingerPosition = GetFingerTopPosition(fingerWindowThresholded) + matchLoc; #if ENABLE_DEBUG_WINDOWS rectangle(img_display, m_currentCandidate.m_windowRect.tl(), m_currentCandidate.m_windowRect.br(), Scalar(255,0,0), 2, 8, 0 ); rectangle(scoreMap, m_currentCandidate.m_windowRect.tl(), m_currentCandidate.m_windowRect.br(), Scalar::all(0), 2, 8, 0 ); rectangle(img_display, m_currentCandidate.m_fingerPosition, m_currentCandidate.m_fingerPosition + Point(5,5), Scalar(255,0,0)); #endif } else { m_currentCandidate.m_found = false; } #if ENABLE_DEBUG_WINDOWS std::stringstream ss; ss << maxVal; putText(img_display, ss.str(), Point(50, 50), 0, 0.5, Scalar(255,255,255), 1); imshow("Overlays", img_display); imshow("Results", scoreMap); imshow("ResultMasked", maskedOutScoreMap); #endif }
int main(int argc, char **argv) { if (argc != 4) { printUsage(argv[0]); return 1; } vector<Point2f> tlPoints; vector<Point2f> brPoints; string species = string(argv[1]); string video_filename = string(argv[2]); string feature_filename = string(argv[3]); int remove_rect_1_x1, remove_rect_1_x2; int remove_rect_1_y1, remove_rect_1_y2; int remove_rect_2_x1, remove_rect_2_x2; int remove_rect_2_y1, remove_rect_2_y2; if (0 == species.compare("plover")) { remove_rect_1_x1 = 15; remove_rect_1_x2 = 85; remove_rect_1_y1 = 15; remove_rect_1_y2 = 55; remove_rect_2_x1 = 525; remove_rect_2_x2 = 675; remove_rect_2_y1 = 420; remove_rect_2_y2 = 465; } else if (0 == species.compare("tern")) { remove_rect_1_x1 = 15; remove_rect_1_x2 = 85; remove_rect_1_y1 = 15; remove_rect_1_y2 = 55; remove_rect_2_x1 = 245; remove_rect_2_x2 = 330; remove_rect_2_y1 = 195; remove_rect_2_y2 = 225; } else if (0 == species.compare("grouse")) { } else if (0 == species.compare("robot")) { remove_rect_1_x1 = 0; remove_rect_1_x2 = 0; remove_rect_1_y1 = 0; remove_rect_1_y2 = 0; remove_rect_2_x1 = 0; remove_rect_2_x2 = 0; remove_rect_2_y1 = 0; remove_rect_2_y2 = 0; } else { cerr << "Error, unknown species '" << species << "'" << endl; exit(1); } CvCapture *capture = cvCaptureFromFile(video_filename.c_str()); int current_frame = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES); int total_frames = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT); int frame_width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH); int frame_height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT); double fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); cerr << "Video File Name: " << video_filename << endl; cerr << "Frames Per Second: " << fps << endl; cerr << "Frame Count: " << total_frames << endl; cerr << "Video Dimensions: " << frame_width << "x" << frame_height << endl; long start_time = time(NULL); vector<KeyPoint> target_keypoints; Mat target_descriptors; read_descriptors_and_keypoints(feature_filename, target_descriptors, target_keypoints); cout << "target_keypoints.size(): " << target_keypoints.size() << endl; current_frame = 0; while (current_frame < total_frames) { if (current_frame % 100 == 0) { cout << "FPS: " << current_frame/((double)time(NULL) - (double)start_time) << ", " << current_frame << "/" << total_frames << " frames. " << endl; // break; } Mat frame(cvarrToMat(cvQueryFrame(capture))); current_frame = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES); vector<KeyPoint> frame_keypoints, matched_keypoints; Mat frame_descriptors, matched_descriptors; get_keypoints_and_descriptors(frame, frame_descriptors, frame_keypoints); float min_min_distance = 128.0; float max_min_distance = 0.0; float min_max_distance = 128.0; float max_max_distance = 0.0; for (int i = 0; i < target_descriptors.rows; i++) { //get the minimum euclidian distance of each descriptor in the current frame from each common_descriptor float min_euclidian_distance = 128.0; float max_euclidian_distance = 0.0; for (int j = 0; j < frame_descriptors.rows; j++) { float euclidian_distance = 0; for (int k = 0; k < target_descriptors.cols; k++) { float tmp = target_descriptors.at<float>(i,k) - frame_descriptors.at<float>(j,k); min_euclidian_distance += tmp * tmp; } euclidian_distance = sqrt(min_euclidian_distance); if (euclidian_distance < min_euclidian_distance) min_euclidian_distance = euclidian_distance; if (euclidian_distance > max_euclidian_distance) max_euclidian_distance = euclidian_distance; } cout << "\tmin_euclidian_distance[" << i << "]: " << min_euclidian_distance << ", max_euclidian_distance: " << max_euclidian_distance << endl; if (min_min_distance > min_euclidian_distance) min_min_distance = min_euclidian_distance; if (max_min_distance < min_euclidian_distance) max_min_distance = min_euclidian_distance; if (min_max_distance > max_euclidian_distance) min_max_distance = max_euclidian_distance; if (max_max_distance < max_euclidian_distance) max_max_distance = max_euclidian_distance; if (min_euclidian_distance <= 1.6) { int x = target_keypoints[i].pt.x; int y = target_keypoints[i].pt.y; matched_keypoints.push_back( target_keypoints[i] ); matched_descriptors.push_back( target_descriptors.row(i) ); cout << "matched keypoint with x: " << x << ", y: " << y << endl; } } // Code to draw the points. Mat frame_with_target_keypoints; drawKeypoints(frame, matched_keypoints, frame_with_target_keypoints, Scalar::all(-1), DrawMatchesFlags::DEFAULT); rectangle(frame_with_target_keypoints, Point(remove_rect_1_x1, remove_rect_1_y1), Point(remove_rect_1_x2, remove_rect_1_y2), Scalar(0, 0, 255), 1, 8, 0); rectangle(frame_with_target_keypoints, Point(remove_rect_2_x1, remove_rect_2_y1), Point(remove_rect_2_x2, remove_rect_2_y2), Scalar(0, 0, 255), 1, 8, 0); imshow("SURF - Frame", frame_with_target_keypoints); if(cvWaitKey(15) == 27) break; } cvDestroyWindow("SURF"); cvReleaseCapture(&capture); return 0; }