
        
// Auto-generated C Code - S2i Mosaicode
/*
*	In order to compile this source code run, in a terminal window, the following command:
*	gcc sourceCodeName.c `pkg-config --libs --cflags opencv` -o outputProgramName
*
*	the `pkg-config ... opencv` parameter is a inline command that returns the path to both
*	the libraries and the headers necessary when using opencv. The command also returns other necessary compiler options.
*/

#ifdef _CH_
#pragma package <opencv>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/objdetect.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/features2d/features2d.hpp"

using namespace cv;
using namespace std;

#define FRAMERATE 1000.0 / 25.0


int main(int argc, char ** argv){
    char key = ' ';
            
    Mat image_file_14_output_image;

	Mat match_object_26_input_object;
	Mat match_object_26_input_image;
	Mat match_object_26_output_image;
	Ptr<xfeatures2d::SURF> surf = xfeatures2d::SURF::create(400);
        
    Mat show_image_4_input_image;
    if(strcmp("WINDOW_NORMAL", "WINDOW_AUTOSIZE") == 0)
        namedWindow("My Image", WINDOW_NORMAL);
    else
        namedWindow("My Image", WINDOW_AUTOSIZE);

    while((key = (char)waitKey(FRAMERATE)) != 27){
        
    image_file_14_output_image = imread("/usr/share/mosaicode/extensions/examples/c/opencv/lenna.png", IMREAD_COLOR);
        
        if(!image_file_14_output_image.empty()) 
        	match_object_26_input_object = image_file_14_output_image.clone();

	if(!match_object_26_input_object.empty() && !match_object_26_input_image.empty()){
		cvtColor(match_object_26_input_object, match_object_26_input_object, COLOR_BGR2GRAY);
		cvtColor(match_object_26_input_image, match_object_26_input_image, COLOR_BGR2GRAY);
		vector<KeyPoint> keypoints_object, keypoints_image;
		vector<DMatch> good_matches;
		vector<Point2f> obj, image_dtc, obj_corners(4), image_corners(4);
		surf->detect(match_object_26_input_object, keypoints_object);
		surf->detect(match_object_26_input_image, keypoints_image);
		Mat descriptors_object, descriptors_image;
		surf->compute(match_object_26_input_object, keypoints_object, descriptors_object);
		surf->compute(match_object_26_input_image, keypoints_image, descriptors_image);
		double max_dist = 0; double min_dist = 100;
		FlannBasedMatcher matcher;
		vector<DMatch> matches;
		matcher.match(descriptors_object, descriptors_image, matches);
		for(int i = 0; i < descriptors_object.rows; i++){
			double distance = matches[i].distance;
    		if(distance < min_dist) 
    			min_dist = distance;
    		if(distance > max_dist) 
    			max_dist = distance;
		}    			
		for(int i = 0; i < descriptors_object.rows; i++){
			if(matches[i].distance < 3*min_dist){
				good_matches.push_back(matches[i]);
			}
		}
		drawMatches(match_object_26_input_object, keypoints_object, match_object_26_input_image, keypoints_image, good_matches, 
		match_object_26_output_image, Scalar(222,184,135), Scalar(222,184,135), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
		for(int i = 0; i < good_matches.size(); i++){
			obj.push_back(keypoints_object[good_matches[i].queryIdx].pt);
    		image_dtc.push_back(keypoints_image[good_matches[i].trainIdx ].pt);
		}
		Mat homography = findHomography(obj, image_dtc, CV_RANSAC);
		obj_corners[0] = Point(0,0); 
		obj_corners[1] = Point(match_object_26_input_object.cols, 0);
  		obj_corners[2] = Point(match_object_26_input_object.cols, match_object_26_input_object.rows);
  		obj_corners[3] = Point(0, match_object_26_input_object.rows);
		perspectiveTransform(obj_corners, image_corners, homography);

		line(match_object_26_output_image, image_corners[0] + Point2f(match_object_26_input_object.cols, 0), image_corners[1] + Point2f(match_object_26_input_object.cols, 0), Scalar(0, 255, 0), 4);
		line(match_object_26_output_image, image_corners[1] + Point2f(match_object_26_input_object.cols, 0), image_corners[2] + Point2f(match_object_26_input_object.cols, 0), Scalar( 0, 255, 0), 4);
		line(match_object_26_output_image, image_corners[2] + Point2f(match_object_26_input_object.cols, 0), image_corners[3] + Point2f(match_object_26_input_object.cols, 0), Scalar( 0, 255, 0), 4);
		line(match_object_26_output_image, image_corners[3] + Point2f(match_object_26_input_object.cols, 0), image_corners[0] + Point2f(match_object_26_input_object.cols, 0), Scalar( 0, 255, 0), 4);
	}
        
        if(!match_object_26_output_image.empty()) 
        	show_image_4_input_image = match_object_26_output_image.clone();

    if(!show_image_4_input_image.empty()){
        imshow("My Image", show_image_4_input_image);
    }

                
    image_file_14_output_image.release();

	match_object_26_input_object.release();
	match_object_26_input_image.release();
	match_object_26_output_image.release();
        
    show_image_4_input_image.release();

    }

    destroyAllWindows();
    return 0;
}
