https://doi.org/10.5201/ipol.2014.106
Raw File
lens_distortion_correction_division_model_1p.cpp
/*
   Copyright (c) 2010-2013, AMI RESEARCH GROUP <lalvarez@dis.ulpgc.es>
   License : CC Creative Commons "Attribution-NonCommercial-ShareAlike"
   see http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.en
 */


/**
 * @file lens_distortion_correction_division_model_1p.cpp
 * @brief distortion correction using the improved Hough transform with the 1 parameter division distortion model
 *
 * @author Luis Alvarez <lalvarez@dis.ulpgc.es> and Daniel Santana-Cedres <dsantana@ctim.es>
 */


//Included libraries
#include "ami_image/image.h"
#include "ami_filters/filters.h"
#include "ami_primitives/subpixel_image_contours.h"
#include "ami_primitives/line_extraction.h"
#include "ami_primitives/image_primitives.h"
#include "ami_lens_distortion/lens_distortion_procedures.h"
#include "ami_utilities/utilities.h"
#include <iostream>
#include <fstream>
using namespace std;

int main(int argc, char *argv[])
{
  if(argc!=11){
    print_function_syntax_lens_distortion_correction_division_model_1p();
    exit(EXIT_FAILURE);
  }

  if(check_params_lens_distortion_correction_division_model_1p(argv) != 0){
    manage_failure(argv);
    exit(EXIT_SUCCESS);
  }



  //We read the input image and some variables are initialized
  ami::image<unsigned char> input(argv[1]); // input image
  int width = input.width(), height = input.height();//input image dimensions
  int size_ = width*height; // image size
  ami::image<unsigned char> gray(width,height,1,0);//gray-level image to call canny
  ami::image<unsigned char> edges(width,height,1,0);//image to store edge information
  float canny_high_threshold = atof(argv[5]);// high threshold for canny detector
  float initial_distortion_parameter=atof(argv[6]);//left side of allowed distortion parameter interval
  float final_distortion_parameter = atof(argv[7]);//Hough parameter
  float distance_point_line_max_hough = atof(argv[8]);//Hough parameter
  //maximum difference allowed (in degrees) between edge and line orientation
  float angle_point_orientation_max_difference = atof(argv[9]);


  //Converting the input image to gray level
  for(int i=0; i<size_; i++)
    gray[i] = 0.3*input[i] + 0.59*input[i+size_] + 0.11*input[i+size_*2];

  //ALGORITHM STAGE 1 : Detecting edges with Canny
  float canny_low_threshold = 0.7; //default value for canny lower threshold
  ami::subpixel_image_contours contours=canny(gray,edges,canny_low_threshold,canny_high_threshold);

  //We create writable 3 channel images for edges and gray level
  ami::image<unsigned char> edges3c(width, height, 3),gray3c(width, height, 3);
  edges3c=edges;
  gray3c=gray;

  //Writing Canny detector output
  edges3c.write(argv[2]);
  cout << "...edges detected" << endl;

  //ALGORITHM STAGE 2 : Detecting lines with improved_hough_quotient
  cout << "Detecting lines with improved Hough and division model..." << endl;
  image_primitives i_primitives_quo;//object to store output edge line structure
  int max_lines=30; //maximun number of lines estimated
  float angle_resolution=0.1; // angle discretization step (in degrees)
  float distance_resolution=1.; // line distance discretization step
  float distortion_parameter_resolution=0.1;//distortion parameter discretization step
  //we call 3D Hough line extraction
  line_equation_distortion_extraction_improved_hough_quotient(
    contours,
    i_primitives_quo,
    distance_point_line_max_hough,
    max_lines,
    angle_resolution,
    distance_resolution,
    initial_distortion_parameter,
    final_distortion_parameter,
    distortion_parameter_resolution,
    angle_point_orientation_max_difference
  );

  // WE CHECK IF THE IMPROVED HOUGH PROCEDURE FINISHS PROPERLY
  if(i_primitives_quo.get_lines().size()==0){
    manage_failure(argv);
    exit(EXIT_SUCCESS);
  }
  cout << "...lines detected: " << i_primitives_quo.get_lines().size() <<
	        " with " << count_points(i_primitives_quo) << " points" << endl;

  //ALGORITHM STAGE 3 : Optimising the distortion parameter value by minimizing
  //the distance between the points and their corresponding lines
  cout << "Optimising the distortion model..." << endl;

  double dmi = i_primitives_quo.get_distortion().get_distortion_center().norm();
  dmi*=dmi;


  double error = model_estimation_1p_quotient(i_primitives_quo.get_distortion().get_distortion_center(),
                               i_primitives_quo.get_lines(),
                               i_primitives_quo.get_distortion());
  cout << "...distortion model optimised." << endl;



  //Drawing the detected lines on the original image to illustrate the results
  drawHoughLines(i_primitives_quo,gray3c);
  gray3c.write(argv[3]);

  //ALGORITHM STAGE 4 : Correcting the image distortion using the estimated model
  if(i_primitives_quo.get_distortion().get_d().size()>0){
    cout << "Correcting the distortion..." << endl;
    ami::image<unsigned char> undistorted =undistort_quotient_image_inverse(
      input, // input image
      i_primitives_quo.get_distortion(), // lens distortion model
      2.0 // integer index to fix the way the corrected image is scaled to fit input size image
    );
    //writing the distortion corrected image
    undistorted.write(argv[4]);
    cout << "...distortion corrected." << endl;
  }

  // WRITING OUTPUT TEXT DOCUMENTS
  // writing in a file the lens distortion model and the lines and associated points
  i_primitives_quo.write(argv[10]);
  // writing function parameters and basic outputs :
  ofstream fs("output.txt");//Output file
  fs << "Selected parameters:" << endl;
  fs << "\t High Canny's threshold: " << argv[5] << endl;
  fs << "\t Initial normalized distortion parameter: " << argv[6] << endl;
  fs << "\t Final normalized distortion parameter: " << argv[7] << endl;
  fs << "\t Maximum distance between points and line: " << argv[8] << endl;
  fs << "\t Maximum differente between edge point and line orientations: "
     << argv[9]	<< endl;
  fs << "-------------------------" << endl;
  fs << "Results: " << endl;
  fs << "\t Number of detected lines: " << i_primitives_quo.get_lines().size()
	   << endl;
  int count = count_points(i_primitives_quo);
  fs << "\t Total amount of line points: " << count << endl;
  fs << "\t Estimated normalized distortion parameter: " <<
	   (-i_primitives_quo.get_distortion().get_d()[1]*dmi) /
		 (1+i_primitives_quo.get_distortion().get_d()[1]*dmi)
		 << endl;
  fs << "\t Average squared error distance between line and associated points = " << error/count << endl;

  fs.close();
  exit(EXIT_SUCCESS);
}
back to top