Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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);
}
Esempio n. 4
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]);
            }
        }
}
Esempio n. 9
0
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);
}
Esempio n. 10
0
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));
}
Esempio n. 11
0
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();
}
Esempio n. 12
0
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;
}