void *intensity_processing(void *pointer) {

	vector < Mat > Intensity_Maps = Pyr_CenSur(IntensityImg);
	AggInt = aggregateMaps(Intensity_Maps);
	normalize(AggInt, AggInt, 0, 255, NORM_MINMAX, -1);


	pthread_exit (NULL);
}
void *color_processing(void *pointer) {
	Mat *imgPtr = (Mat *) pointer;
	vector < Mat > color_map;
	
	color_map = Normalize_color(*imgPtr, IntensityImg);
	vector < Mat > RGBYMap(6);

	for (int i = 0; i < 6; i++)
		addWeighted(color_map[i], 0.5, color_map[i + 6], 0.5, 0, RGBYMap[i],
				-1);

	AggColor = aggregateMaps(RGBYMap);
	normalize(AggColor, AggColor, 0, 255, NORM_MINMAX, -1);

	pthread_exit (NULL);
}
int main(int argc, char **argv)
{
    
    
    /**********************************/
    /*        Program options         */
    /**********************************/
    // Need to specify elevation grid
    // Need to specify channel
    std::string map_file;
    std::string template_file;
    std::string output_file_depth;
    std::string output_file_proportion;
    
    bool ignore_na = false;
    bool do_max = false;
    bool majority = false;
    //
    
    namespace prog_opt = boost::program_options;
    namespace fs = boost::filesystem;
    namespace raster_util = blink::raster;
    
    prog_opt::options_description desc("Allowed options");
    desc.add_options()
    ("help,h", "produce help message")
    ("map,m", prog_opt::value<std::string>(&map_file), "path of the gdal capatible raster for aggregating")
    ("template,t", prog_opt::value<std::string>(&template_file), "path of the gdal capatible raster which works as a template (output raster will have same extent and cell size as template)")
    ("depth-out,d", prog_opt::value<std::string>(&output_file_depth)->default_value("aggregated-depth.tif"), "path where the output gtif raster of depth is saved")
    ("proportion-out,p", prog_opt::value<std::string>(&output_file_proportion)->default_value("aggregated-proportion.tif"), "path where the output gtif raster of proportion flooded is saved")
    ("maximum,x", "use maximum statistic, rather than average")
    ("majority,a", "only assign value if majority of cells are not noValue")
    ("ignore-na,i", "ignore pixels with nodata when taking statistic");
    prog_opt::variables_map vm;
    prog_opt::store(prog_opt::parse_command_line(argc, argv, desc), vm);
    prog_opt::notify(vm);
    if (vm.count("help"))
    {
        std::cout << desc << "\n";
        return 1;
    }
    if (vm.count("maximum"))
    {
        do_max = true;
    }
    if (vm.count("ignore-na"))
    {
        ignore_na = true;
    }
    if (vm.count("majority"))
    {
        majority = true;
    }
    
    fs::path map_path(map_file);
    fs::path template_path(template_file);
    fs::path output_path_depth(output_file_depth);
    fs::path output_path_proportion(output_file_proportion);
    
    
    // Check file exists
    if (!fs::exists(map_path))
    {
        std::stringstream ss;
        ss << map_path << " does not exist";
        throw std::runtime_error(ss.str());
        return (EXIT_FAILURE);
    }
    
    if (!fs::exists(template_path))
    {
        std::stringstream ss;
        ss << template_path << " does not exist";
        throw std::runtime_error(ss.str());
        return (EXIT_FAILURE);
    }
    
    
    /**********************************/
    /*         Read in maps           */
    /**********************************/
    std::cout << "\n\n*************************************\n";
    std::cout <<     "*             Read in maps          *\n";
    std::cout <<     "*************************************" << std::endl;
    auto template_m = raster_util::open_gdal_raster<double>(template_path, GA_ReadOnly);
    
    auto map = raster_util::open_gdal_raster<double>(map_path, GA_ReadOnly);
    
    
    /********************************************/
    /*       Assign memory for output map       */
    /********************************************/
    std::cout << "\n\n**************************************\n";
    std::cout <<     "*    Assign memory for output maps   *\n";
    std::cout <<     "**************************************" << std::endl;
    auto output_map_depth = raster_util::create_gdal_raster_from_model<double>(output_path_depth, template_m);
    auto output_map_proportion = raster_util::create_gdal_raster_from_model<double>(output_path_proportion, template_m);
    
    
    aggregateMaps(map, template_m, output_map_depth, output_map_proportion, ignore_na, do_max, majority);
    
    return (EXIT_SUCCESS);
}
int main(int argc, char** argv)
{
long totaltime, intTime, intTime_o, colTime, colTime_o , orTime, orTime_o;
if(argc != 2)
{
	cout << "No image"<<endl;
	return -1;
}
cout<<"Loading Image: ";
cout<< argv[1]<<endl;
Mat inputImage = imread(argv[1], CV_LOAD_IMAGE_COLOR);

if(!inputImage.data)
{
	cout <<"Invalid Image"<<endl;
}

Mat IntensityImg, finalImage;
for(int counter = 0; counter < 1; counter++)
{
totaltime = timestamp();

intTime = timestamp();
IntensityImg = Get_Intensity_Image(inputImage);
vector<Mat> Intensity_Maps = Pyr_CenSur(IntensityImg);
Mat AggInt = aggregateMaps(Intensity_Maps);
normalize(AggInt, AggInt, 0, 255, NORM_MINMAX, -1);
intTime_o = timestamp() - intTime;

colTime = timestamp();
vector<Mat> color_map;
color_map = Normalize_color(inputImage, IntensityImg);
vector<Mat> RGBYMap(6); 
for(int i = 0; i<6; i++)
addWeighted(color_map[i], 0.5, color_map[i+6], 0.5, 0, RGBYMap[i], -1);
Mat AggColor = aggregateMaps(RGBYMap);
normalize(AggColor, AggColor, 0, 255, NORM_MINMAX, -1);
colTime_o = timestamp() - colTime;

orTime = timestamp();
Mat AggOr;
AggOr = getGaborImage(IntensityImg);
normalize(AggOr, AggOr, 0, 255, NORM_MINMAX, -1);
orTime_o = timestamp() - orTime;

finalImage = (AggInt + AggColor + AggOr) /3;
normalize(finalImage, finalImage, 0, 255, NORM_MINMAX, -1);

for(int bCtr = 0; bCtr<4; bCtr++)
{
	pyrUp(finalImage, finalImage);
}

cout <<"Intensity Time: "<< (intTime_o) << "\n";
cout <<"Color Time: "<< (colTime_o) << "\n";
cout <<"Orientation Time: "<< (orTime_o) << "\n";
cout <<"Total Time: "<< (timestamp() - totaltime) << "\n";
}



Mat contImg;
inRange(finalImage, 160, 230, contImg);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;

findContours(contImg, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
for(int i = 0; i>=0; i =hierarchy[i][0])
{
	Scalar color(rand()&255, rand()&255, rand()&255);
	drawContours(inputImage, contours, i, color, 3, 8, hierarchy);
}

imwrite("Salient_Image.jpg" , inputImage);

waitKey(0);
return 0;
}