Beispiel #1
0
void set_disparity(int start, int end, vector<SDoublePlane> &D, SDoublePlane &V, vector<vector<SDoublePlane> > &m)
{
	//disp_arg *A = (disp_arg*)obj;

	double disp_score;
    double min_score = INT_MAX;
	int label, t=1;
	double neighbors_sum;
	start = (start < 1)? 1:start;
	end = (end < (V.rows()-1))?end:(V.rows()-1);
	for (int i = start; i < end-1; i++) {
		for (int j = 1; j < D[0].cols() - 1; j++) {
			min_score = INT_MAX;
			label = DLIMIT;
			for (int d = 0; d < DLIMIT; d++) {
				//cout << i<<","<<j<<endl;
				neighbors_sum = get_messages_from_neighbors(m[d][t], i, j, ALL);
				disp_score = D[d][i][j] + neighbors_sum;

				if (disp_score < min_score) {
					min_score = disp_score;
					label = d;
				}
			}

			V[i][j] = label;
		}
	}
}
SDoublePlane mrf_stereo(const SDoublePlane &left_image, const SDoublePlane &right_image)
{
  // implement this in step 4...
  //  this placeholder just returns a random disparity map
  SDoublePlane result(left_image.rows(), left_image.cols());
  //INITIALIZE THE MESSAGE TABLE
  vector<vector<MsgPiece> > msgTable = init_table(left_image,right_image);
  //LOOP BP
  for(int i = 0;i<LOOP;++i){
    bp_update(msgTable);
  }
  //printf("2\n");
  //MAP
  for(int i = 0;i<left_image.rows();++i)
    for(int j = 0;j<left_image.cols();++j)
    {
      double best= THRES;
      for(int ll = 0;ll<LABEL_NUM;++ll){
        double cost = msgTable[i][j].msg[0][ll];
        cost += msgTable[i][j].msg[1][ll];
        cost += msgTable[i][j].msg[2][ll];
        cost += msgTable[i][j].msg[3][ll];
        cost += msgTable[i][j].msg[4][ll];
        if(cost < best) {
          best = cost;
          result[i][j] = ll;
        }
      }
    }
 // printf("3\n");
    for(int i = 0;i<left_image.rows();++i)
      for(int j = 0;j<left_image.cols();++j)
        result[i][j] = (result[i][j]*256)/LABEL_NUM;
  return result;
}
// Apply an edge detector to an image, returns the binary edge map
// Pass thresh=0 to ignore binary map, else pass thresh [1-255]
// white_value only applies when thresh!=0, pass 1 for 0-1 image, or 255 for 0-255 binary image
// Returns edge_map and gradient_angle
pair<SDoublePlane, SDoublePlane> find_edges(const SDoublePlane &input, double thresh=0, double white_value=1)
{	
	SDoublePlane G(input.rows(), input.cols());
	SDoublePlane Rotation(input.rows(), input.cols());
	SDoublePlane Gx, Gy;

	Gx = sobel_gradient_filter(input, true);
	Gy = sobel_gradient_filter(input, false);
	
	for (int i = 0; i < input.rows(); ++i)
	{
		for (int j = 0; j < input.cols(); ++j)
		{
			G[i][j] = sqrt(Gx[i][j]*Gx[i][j]+Gy[i][j]*Gy[i][j]);						
			if (G[i][j] > 255) G[i][j] = 255;			
			if ( abs(Gx[i][j]) < 0.0001)
				Rotation[i][j] = PI / 2.0;
			else
				Rotation[i][j] = atan(Gy[i][j] / Gx[i][j]);			
		}		
	}

	if (abs(thresh) > 0.0001)
	{
		for (int i = 0; i < G.rows(); ++i)		
			for (int j = 0; j < G.cols(); ++j)
				G[i][j] = (G[i][j]>thresh?white_value:0);
	}
	return make_pair(G, Rotation);
}
HammingDistances find_hamming_distance(SDoublePlane &img_input, SDoublePlane &img_template){
	
	int input_rows = img_input.rows();
	int input_cols = img_input.cols();
	int template_rows = img_template.rows();
	int template_cols = img_template.cols();
	HammingDistances hm;
		
	double sum = 0.0;
	double max_hamming = 0.0;
	SDoublePlane output(input_rows, input_cols);
	for(int i =0;i<input_rows - template_rows ; ++i){
		for(int j =0;j<input_cols - template_cols; ++j){
			sum=0.0;
			for(int k =0;k<template_rows;++k){
				for(int l=0;l<template_cols;++l){
					sum = sum + (img_input[i+k][j+l] * img_template[k][l] + (1 - img_input[i+k][j+l])*(1 - img_template[k][l]));	
				}
			}
			output[i][j] = sum;
			if(sum>max_hamming)
				max_hamming = sum;
		}
	}
	//printImg2File("input_img_file_Output.txt", img_input);
	//printImg2File("img2fileOutput.txt", output);
	hm.hamming_matrix = output;
	hm.max_hamming_distance= max_hamming;
	return hm;	
}
SDoublePlane non_maximum_suppress(const SDoublePlane &input, double threshold, int w, int h)
{
	//double threshold = 0.84 * 255;
	SDoublePlane output(input.rows(), input.cols());
	
	for (int i = 0; i < input.rows(); i++)
	{
		for (int j = 0; j < input.cols(); j++)
		{
			if (input[i][j] > threshold &&
					is_max_in_neighbour(input, i, j, w, h))
			{
				if (input[i][j] > 0.85 * 255)
				{
					output[i][j] = 255;
				}
				else
				{
					output[i][j] = (input[i][j] - threshold)/(0.85 - threshold/255);
				}
			}
			else
			{
				output[i][j] = 0;
			}
		}
	}
	return output;
}
//using the normalized votes find the best row co-ordinates for staff lines
SDoublePlane find_best_line_intercepts(const SDoublePlane &row_votes,const SDoublePlane &normed_votes,int best_space,double norm_threshold=0.55,int neighbour_threshold=4,int start=0)
{	
	SDoublePlane row_spacing=row_votes;
	if(start < row_votes.rows()){
        SDoublePlane staff_lines(row_votes.rows(),1);
	int i=0;	
	double best_value=0;
        int intercept_value=0;
        while(i<row_votes.rows()){
                if(normed_votes[i][0] > norm_threshold){
                        best_value=normed_votes[i][0];
                        intercept_value=i;
			for(int j=1;j<neighbour_threshold;j++){
                                if(normed_votes[i+j][0] > best_value ){
                                        best_value=normed_votes[i+j][0];
                                        intercept_value=i+j;
                                }
                        }
		row_spacing=set_staff(row_spacing,best_space,intercept_value,start);
                i=intercept_value+(4*(best_space))+neighbour_threshold;
		start=intercept_value+(4*best_space)+neighbour_threshold;

                }
		
     		i++;
        }
	
        }
	return row_spacing;
}
SDoublePlane calculate_F(SDoublePlane D, SDoublePlane &binary_template, double threshold) {	
	double sum = 0.0;
	int m = binary_template.rows(), n = binary_template.cols();
	int i, j, k, l, input_rows = D.rows(), input_cols = D.cols();
	
	SDoublePlane output(input_rows, input_cols);
	for(i=0; i<input_rows - m; i++){
		for(j=0; j<input_cols - n; j++){
			sum=0.0;
			for(k =0; k<m; k++){
				for(l=0; l<n; l++){
					sum += binary_template[k][l] * D[i+k][j+l];
				}
			}
			output[i][j] = sum;
		}
	}
	//converting low scores to white n others black
	for(i=0; i<input_rows - m; i++)
		for(j=0; j<input_cols - n; j++)
			if(output[i][j] < threshold){
				output[i][j] = 255;
			}
			else
				output[i][j] = 0;
			
	return output;
}
// Convolve an image with a general convolution kernel
//
SDoublePlane convolve_general(const SDoublePlane &input, const SDoublePlane &filter)
{
	//Requires the dimension of the filter to be smaller than the input.
	//Switch the parameters otherwise.
	
	if ((input.rows() - filter.rows()) * (input.cols() - filter.cols()) < 0) {
		throw "Mismatched dimensions.";
	}
	if (input.rows() < filter.rows()) {
		return convolve_general(filter, input);
	}
	
	if (filter.rows()%2 == 0 || filter.cols()%2 == 0){
		throw "Expected an odd number of rows and columns in the filter";
	}
	//From here, we have ensured dimensions of input is larger than the filter.
	
	SDoublePlane output(input.rows(), input.cols());

	int 	filter_rows_num = filter.rows(),
			filter_cols_num = filter.cols(),
			image_rows_num = input.rows(),
			image_cols_num = input.cols();
	int 	start_row = filter.rows()/2,
			start_col = filter.cols()/2,
			end_row = input.rows() - start_row,
			end_col = input.cols() - start_col;

	for (int i = 0; i < image_rows_num; i++) {
		for (int j = 0; j < image_cols_num; j++) {
			int sum = 0;
			for (int p = -start_row; p <= start_row; p++) {
				for (int q = -start_col; q <= start_col; q++) {
					int x = i + p, y = j+q;
					if (0 > x || x >= image_rows_num || 
							0 > y || y >= image_cols_num) {
						if (y < 0) {
							y = -y;
						} else if (y >= image_cols_num) {
							y = 2*image_cols_num - y - 1;
						}

						if (x < 0) {
							x = -x;
						} else if (x >= image_rows_num) {
							x = 2*image_rows_num - x - 1;
						}
					}
					sum += input[x][y] * 
						filter[filter_rows_num - p - start_row - 1]
							  [filter_cols_num - q - start_col - 1];
				}
			}
			output[i][j] = sum;
		}
	}
	
	return output;
}
SDoublePlane scale_image(const SDoublePlane &input, double ratio)
{
	int m = input.rows();
	int n = input.cols();
	int m2 = input.rows()*ratio;
	int n2 = input.cols()*ratio;
	
	SDoublePlane output(m2, n2);
	
	if (ratio > 0.5)
	{
		for (int i = 0; i < m2; i++)
		{
			int sk = i/ratio;
			int ek = (i + 1)/ratio - 0.00001;
			for (int j = 0; j < n2; j++)
			{
				int sl = j/ratio;
				int el = (j + 1)/ratio - 0.00001;
				
				output[i][j] = input[sk][sl];
				output[i][j] += input[sk][el];
				output[i][j] += input[ek][sl];
				output[i][j] += input[ek][el];
				output[i][j] /= 4.0;
			}
		}
	}
	else
	{
		int span = 1.0/ratio + 0.5;
		for (int i = 0; i < m2; i++)
		{
			int sk = i/ratio;
			int ek = (i - 1)/ratio - 0.00001;
			for (int j = 0; j < n2; j++)
			{
				int sl = j/ratio;
				int el = (j - 1)/ratio - 0.00001;
				
				output[i][j] = 0;
				for (int u = sk; u <= ek; u++)
				{
					for (int v = sl; v <= el; v++)
					{
						output[i][j] += input[u][v];
					}
				}
				output[i][j] /= (ek - sk + 1)*(el - sl + 1);
			}
		}
	}
	
	
	return output;
}
SDoublePlane normalize_votes(const SDoublePlane &acc)
{
	SDoublePlane normalized(acc.rows(),acc.cols());
	double min = find_min_vote(acc);
	double max = find_max_vote(acc);
	for(int i=0;i<acc.rows();i++){
		normalized[i][0] = (acc[i][0] - min)/(max-min);
	}
	return normalized;
}
SDoublePlane normalise_kernel(const SDoublePlane& input) {
	std::cout<<"Normalising kernel: "<<input.rows()<<","<<input.cols()<<std::endl;
	debug_png("before-normalise-kernel.png", input);
	if (input.cols()%2 == 1 && input.rows()%2 == 1) {
		return input;
	}

	SDoublePlane output(input.rows()|1, input.cols()|1);

	for (int i=0; i<input.rows(); i++) {
		memcpy(output[i], input[i], sizeof(output[i][0]) * input.cols());
	}

	if (input.rows() + 1 == output.rows()) {
		memcpy(output[output.rows()-1], input[input.rows()-1], sizeof(output[0][0]) * input.cols());
	}

	if (input.cols() + 1 == output.cols()) {
		for (int i=0; i<input.rows(); i++) {
			output[i][output.cols()-1] = input[i][input.cols()-1];
		}
		if (input.rows() + 1 == output.rows()) {
			output[output.rows() - 1][output.cols() - 1] = input[input.rows()-1][input.cols()-1];
		}
	}

	debug_png("after-normalise-kernel.png", output);
	return output;
}
SDoublePlane flipxy(SDoublePlane input) {
	for (int i=0; i<input.rows()/2; i++) {
		for (int j=0; j<input.cols(); j++) {
			//std::cout<<"Flipping: "<<i<<" "<<j<<std::endl;
			double temp = input[input.rows() - i - 1][input.cols() - j - 1];
			input[input.rows() - i - 1][input.cols() - j - 1] = input[i][j];
			input[i][j] = temp;
		}
	}
	return input;
}
// Find symbols in the given image for the given template
void find_symbols(HammingDistances hm, SDoublePlane input, SDoublePlane img_template, vector <DetectedSymbol> &symbols, Type symbol_type){
	
	int template_rows = img_template.rows();
	int template_cols = img_template.cols();
	
	double max_hamming_distance = hm.max_hamming_distance;
	SDoublePlane matrix = hm.hamming_matrix;
	
	vector<LineLocation> allLinesLocVector;
	double confidence_threshold;
	if (symbol_type == NOTEHEAD){
		confidence_threshold = 0.9;
		allLinesLocVector = find_line_location(input);
	}
	else
		confidence_threshold = 0.95;
		
	// Finding symbols
	for(int i =0;i<matrix.rows();i++){
		for(int j=0;j<matrix.cols();j++){
			double value = matrix [i][j];
			if( value >= confidence_threshold * max_hamming_distance) {
				DetectedSymbol s;
				s.row = i;
				s.col = j;
				s.width = template_cols;
				s.height = template_rows;
				s.type = symbol_type;
				s.confidence = value;
				
				s.pitch = ' ';
				
				if(symbol_type == NOTEHEAD)
					set_symbol_marker(s, allLinesLocVector);
				else
					s.pitch = ' ';
				
				symbols.push_back(s);
				// Marking the pixels of the template so that they are not detected again
				for (int x=i; x < i+s.height; x++){
					for (int y=j; y < j+s.width; y++){
						matrix[x][y] = -100;
					}	
				}
				
			}

		}
	}
}
// compare two image values 
// returns true if they are similar, false otherwise
bool compare_image_value(const SDoublePlane &image1, const SDoublePlane &image2)
{
	if (image1.rows() != image2.rows() || image1.cols() != image2.cols())
		return false;
	for (int i = 0; i < image1.rows(); ++i)
	{
		for (int j = 0; j < image1.cols(); ++j)
		{
			if (image1[i][j] != image2[i][j])
				return false;	
		}
	}
	return true;
}
// Finding Line Location for Q4. As this was a open ended question, we found the number of lines using this approach.
vector<LineLocation> find_line_location(SDoublePlane &input){
	
	int rows = input.rows();
	int cols = input.cols();
	vector<LineLocation> allLinesLocVector;
	double sum;
	int lineCounter = 1;
	int j;
	
	for(int i=0;i<rows;i++)
	{	sum =0;
		for(j=cols - 45;j<cols -40;j++){
			sum += input[i][j]; 
		}
		if(sum/5 < 130){
			LineLocation lineLoc;
			lineLoc.row = i;
			lineLoc.col = j;
			set_line_tags(lineLoc, lineCounter);
			lineCounter++;
			allLinesLocVector.push_back(lineLoc);
		}
	
	}
	return allLinesLocVector;
}
SDoublePlane calculate_D(SDoublePlane &binary_image_blur_sobel) {
	int i, j, input_rows = binary_image_blur_sobel.rows(), input_cols = binary_image_blur_sobel.cols();
	SDoublePlane D(input_rows, input_cols);

	//initialize edges as 0 and others as infinity(10000) in binary_image_blur_sobel
	for(i=0;i<input_rows;i++)
		for(j=0;j<input_cols;j++)
			if(binary_image_blur_sobel[i][j] == 1)
				D[i][j] = 0;
			else
				D[i][j] = 10000;
	
	//distance below and to the right of edges
	for(i=1;i<input_rows;i++)
		for(j=1;j<input_cols;j++)
			D[i][j] = dmin(D[i][j], D[i][j-1]+1, D[i-1][j]+1);
	
	//distance above and to the left of edges
	for(i=input_rows-2; i>=0; i--)
		for(j=input_cols-2; j>=0 ;j--)
			D[i][j] = dmin(D[i][j], D[i+1][j]+1, D[i][j+1]+1);
	
	//bottom row
	i = input_rows-1;	
	for(j=input_cols-2; j>=0 ;j--)
		D[i][j] = dmin(D[i][j], D[i-1][j]+1, D[i][j+1]+1);
	
	//rightmost column
	j = input_cols-1;
	for(i=input_rows-2; i>=0; i--)
		D[i][j] = dmin(D[i][j], D[i+1][j]+1, D[i][j-1]+1);
	
	return D;
}
void write_staves_image(const string &filename, const SDoublePlane &img, vector<Line> linesVector){
	
	SDoublePlane output_planes[3];
	
	for (int i = 0; i < 3; i++)
		output_planes[i] = img;
					
	int r = img.rows();
	int c = img.cols();
	
	int x1, y1, x2, y2;
	for (int i = 0; i < linesVector.size(); i++) {
		x1 = linesVector[i].x1;
		y1 = linesVector[i].y1;
		x2 = linesVector[i].x2;
		y2 = linesVector[i].y2;
		//cout<<"(x1,y1): ("<<x1<<","<<y1<<"), (x2,y2):("<<x2<<","<<y2<<")\n"; 
		
		overlay_rectangle(output_planes[2], y1, x1, y2, x2, 255, 2);
		overlay_rectangle(output_planes[0], y1, x1, y2, x2, 0, 2);
		overlay_rectangle(output_planes[1], y1, x1, y2, x2, 0, 2);

	}
	
	SImageIO::write_png_file(filename.c_str(), output_planes[0],
			output_planes[1], output_planes[2]);
		
}
// Convolve an image with a separable convolution kernel
//
SDoublePlane convolve_separable(const SDoublePlane &input, const SDoublePlane &row_filter, const SDoublePlane &col_filter)
{
	SDoublePlane output(input.rows(), input.cols());

	output = convolve_general(input, row_filter);
	return convolve_general(output, col_filter);
}
int get_notes_possitions(const SDoublePlane &input, const SDoublePlane &tmpl,
		double threshold, SDoublePlane &output, Type t,
		vector<DetectedSymbol> &symbols)
{
	// non-maximum suppress size
	int sup_w,  sup_h;
	
	//shawn calc hamming distance
	
	// get template image
	//SDoublePlane template_note = SImageIO::read_png_file("template1.png");
	// get distance
	SDoublePlane hammdis_note = get_Hamming_distance(input, tmpl);
	if (t == NOTEHEAD)
	{
		write_image("scores4.png", hammdis_note);
	}
	//write_image("hamming_dist_note.png", hammdis_note);
	// print_image_value(hammdis_note);
	// cout << plane_max(hammdis_note) / 255 << endl;
	// non-maximum suppress
	SDoublePlane sup_note = non_maximum_suppress(hammdis_note, threshold*255, tmpl.cols()*0.5, tmpl.rows()-(int)(tmpl.rows()*0.4));
	//write_image("sup_hamming_dist_note.png", sup_note);
	get_symbols(sup_note, symbols, t, tmpl.cols(), tmpl.rows());

	
	return 0;
}
Beispiel #20
0
SDoublePlane compute_pairwise_cost(SDoublePlane disp, SDoublePlane &labels, int i, int j) {
	int sum = 0;
	int min_diff = INT_MAX;
	int min_label = DLIMIT;

	SDoublePlane result(disp.rows(), disp.cols());

//	for (int i = 1; i < disp.rows() - 1; i++) {
//		for (int j = 1; j < disp.cols() - 1; j++) {
			min_diff = INT_MAX;
			for (int d = 0; d < DLIMIT; d++) {
				sum = 0;
				sum += pow(d - disp[i][j - 1], 2);
				sum += pow(d - disp[i][j + 1], 2);
				sum += pow(d - disp[i + 1][j], 2);
				sum += pow(d - disp[i - 1][j], 2);
				if (sum < min_diff) {
					min_diff = sum;
					min_label = d;
				}
			}
			result[i][j] = min_diff;
			disp[i][j] = min_label;
			//cout<<min_diff<<endl;
//		}
//	}
	return result;
}
// Apply a sobel operator to an image, returns the result
// _gx=true for horizontal gradient, false for vertical gradient
SDoublePlane sobel_gradient_filter(const SDoublePlane &input, bool _gx)
{
	SDoublePlane output(input.rows(), input.cols());
	SDoublePlane row_filter(1, 3), col_filter(3, 1);
	if (_gx)
	{
		row_filter[0][0] = -1.0;
		row_filter[0][1] = 0.0;	
		row_filter[0][2] = 1.0;
			
		col_filter[0][0] = 1.0/8.0;
		col_filter[1][0] = 2.0/8.0;	
		col_filter[2][0] = 1.0/8.0;
	}
	else
	{
		row_filter[0][0] = 1.0/8.0;
		row_filter[0][1] = 2.0/8.0;
		row_filter[0][2] = 1.0/8.0;
			
		col_filter[0][0] = 1.0;
		col_filter[1][0] = 0.0;	
		col_filter[2][0] = -1.0;	
	}	

	SDoublePlane sobel = convolve_separable(input, row_filter, col_filter);	
	return sobel;
}
// Apply an edge detector to an image, returns the binary edge map
SDoublePlane find_edges(const SDoublePlane &input, double thresh = 0) {
	SDoublePlane output(input.rows(), input.cols());

	// Implement an edge detector of your choice, e.g.
	// use your sobel gradient operator to compute the gradient magnitude and threshold

	return output;
}
double find_min_vote(const SDoublePlane &acc)
{
	double min=acc[0][0];
	for(int i=1;i<acc.rows();i++){
		if(acc[i][0] < min ) min=acc[i][0]; 
	}
	return min;
}
//find max votes from accumulator
double find_max_vote(const SDoublePlane &acc)
{
	double max=0;
	for(int i=0;i<acc.rows();i++){
		if(acc[i][0] > max)max=acc[i][0];
	}
	return max;
}
int get_notes_pitch(vector<DetectedSymbol> &symbols, const SDoublePlane &lines, int interval)
{
	vector<int> line_pos;
	for (int i = 0; i < lines.rows(); i++)
	{
		if (lines[i][0] == 255)
		{
			line_pos.push_back(i);
		}
	}
	
	int last = 0;
	vector<int> groups;
	for(vector<int>::iterator iter = line_pos.begin(); iter < line_pos.end(); iter++)
	{
		int y = *iter;
		if (y - last > interval * 2)
		{
			groups.push_back(y);
		}
		last = y;
	}
	
	int ginterval = groups[1] - groups[0];
	int upper_bound = -4 * interval;
	int lower_bound = ginterval - 4 * interval;
	
	for(vector<DetectedSymbol>::iterator symiter = symbols.begin(); symiter < symbols.end(); symiter++)
	{
		if (symiter->type != NOTEHEAD)
		{
			continue;
		}
		for(vector<int>::iterator giter = groups.begin(); giter < groups.end(); giter++)
		{
			int gy = *giter;
			double dy = symiter->row - 0.2*interval - gy;
			//if (dy < upper_bound)
			//{
			//	// missing some group
			//	break;
			//}
			if(dy > lower_bound)
			{
				// belong to next group
				continue;
			}
			int np = 4 - (int)(dy * 2 / interval) + 28;
			if ((giter - groups.begin()) % 2 != 0)
			{
				np += 2;
			}
			np %= 7;
			symiter->pitch = 'A' + np;
			break;
		}
	}
}
// Get Hamming distance map
SDoublePlane get_Hamming_distance(const SDoublePlane &input, const SDoublePlane &target)
{
	SDoublePlane output(input.rows(), input.cols());
	
	// change to convolution function later
	for (int i = 0; i < input.rows(); i++)
	{
		for (int j = 0; j < input.cols(); j++)
		{
			double sum = 0;
			for (int u = 0; u < target.rows(); u++)
			{
				for (int v = 0; v < target.cols(); v++)
				{
					int k = i + u, l = j + v;
					if (k >= input.rows())
					{
						k = input.rows() - 1 - (k - input.rows() + 1);
					}
					if (l >= input.cols())
					{
						l = input.cols() - 1 - (l - input.cols() + 1);
					}
					double a = input[k][l] / 255;
					double b = target[u][v] / 255;
					sum += a * b;
					sum += (1 - a) * (1 - b);
				}
			}
			output[i][j] = sum / (target.rows() * target.cols()) * 255;
		}
	}
	
	return output;
}
SDoublePlane direct_sobel(const SDoublePlane &input) {
	SDoublePlane output1(input.rows(), input.cols());
	SDoublePlane output2(input.rows(), input.cols());
	SDoublePlane output(input.rows(), input.cols());

	// Implement a sobel gradient estimation filter with 1-d filters
	SDoublePlane sobelHorFilter(3, 3);
	SDoublePlane sobelVerFilter(3, 3);
	
	//initialize
	sobelHorFilter[0][0] = -1;
	sobelHorFilter[0][1] = 0;
	sobelHorFilter[0][2] = 1;
	sobelHorFilter[1][0] = -2;
	sobelHorFilter[1][1] = 0;
	sobelHorFilter[1][2] = 2;
	sobelHorFilter[2][0] = -1;
	sobelHorFilter[2][1] = 0;
	sobelHorFilter[2][2] = 1;
	
	sobelVerFilter[0][0] = -1;
	sobelVerFilter[0][1] = -2;
	sobelVerFilter[0][2] = -1;
	sobelVerFilter[1][0] = 0;
	sobelVerFilter[1][1] = 0;
	sobelVerFilter[1][2] = 0;
	sobelVerFilter[2][0] = 1;
	sobelVerFilter[2][1] = 2;
	sobelVerFilter[2][2] = 1;
	
	output1 = convolve_general(input, sobelHorFilter);
	output2 = convolve_general(input, sobelVerFilter);

	for (int i = 0; i < input.rows(); i++) 
		for (int j = 0; j < input.cols(); j++) {
			output[i][j] = sqrt(output1[i][j]*output1[i][j] + output2[i][j]*output2[i][j]);
			if(output[i][j] > 200)
				output[i][j] = 255;
			else
				output[i][j] = 0;
		}
				
	return output;
}
int main(int argc, char *argv[])
{
  if(argc != 4 && argc != 3)
    {
      cerr << "usage: " << argv[0] << " image_file1 image_file2 [gt_file]" << endl;
      return 1;
    }

  string input_filename1 = argv[1], input_filename2 = argv[2];
  string gt_filename;
  if(argc == 4)
    gt_filename = argv[3];

  // read in images and gt
  SDoublePlane image1 = SImageIO::read_png_file(input_filename1.c_str());
  SDoublePlane image2 = SImageIO::read_png_file(input_filename2.c_str());
  SDoublePlane gt;
  if(gt_filename != "")
  {
    gt = SImageIO::read_png_file(gt_filename.c_str());
    // gt maps are scaled by a factor of 3, undo this...
    for(int i=0; i<gt.rows(); i++)
      for(int j=0; j<gt.cols(); j++)
        gt[i][j] = gt[i][j] / 3.0;
  }
  
  // do stereo using mrf
  SDoublePlane disp3 = mrf_stereo(image1, image2);
  SImageIO::write_png_file("disp_mrf.png", disp3, disp3, disp3);

  // Measure error with respect to ground truth, if we have it...
  if(gt_filename != "")
    {
      double err=0;
      for(int i=0; i<gt.rows(); i++)
	for(int j=0; j<gt.cols(); j++)
	  err += sqrt((disp3[i][j] - gt[i][j])*(disp3[i][j] - gt[i][j]));

      cout << "MRF stereo technique mean error = " << err/gt.rows()/gt.cols() << endl;

    }

  return 0;
}
SDoublePlane disparity_map(const SDoublePlane &input1, const SDoublePlane &input2)
{
int temp=0;
int sum=0;
int min=30000;
SDoublePlane dup(input1.rows(),input1.cols());
SDoublePlane result(input1.rows(), input1.cols());

int count=0;

for(int i=0;i<input1.rows();i++)
{
    min=30000;
    for(int j=0;j<input1.cols();j++)
    {
		min=30000;
        sum=0;
		for(int d=0;d<50;d++)
		{       
			sum=0;
			for(int k=i-1;k<i+2;k++)
			{
				for(int l=j-1;l<j+2;l++)
				{
					if(k>=0 && k<input1.rows() && l+d>=0 && l+d<input1.cols())
					{
						sum+=pow((input1[k][l]-input2[k][l+d]),2);
					}
				}
			}
			//Finding value of d corresponding to minimum "sum"
			if(sum<min)
			{
				min=sum;
				dup[i][j]=abs(input1[i][j]-input2[i][j+d]);
				result[i][j]=d;
			}
		}
	}
}

return result;
}
// Draws a rectangle on an image plane, using the specified gray level value and line width.
//
void overlay_rectangle(SDoublePlane &input, int _top, int _left, int _bottom, int _right, double graylevel, int width)
{
	for(int w=-width/2; w<=width/2; w++) {
		int top = _top+w, left = _left+w, right=_right+w, bottom=_bottom+w;

		// if any of the coordinates are out-of-bounds, truncate them 
		top = min( max( top, 0 ), input.rows()-1);
		bottom = min( max( bottom, 0 ), input.rows()-1);
		left = min( max( left, 0 ), input.cols()-1);
		right = min( max( right, 0 ), input.cols()-1);

		// draw top and bottom lines
		for(int j=left; j<=right; j++)
			input[top][j] = input[bottom][j] = graylevel;
		// draw left and right lines
		for(int i=top; i<=bottom; i++)
			input[i][left] = input[i][right] = graylevel;
	}
}