// Filter description
// ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
// Name: Barrel Distortion Correction Filter
// Purpose: Correcting the barrel distortion of the lens
// Original author: Laurence Muller (aka Falcon4ever)
/*
Tool url:
http://www.multigesture.net/wp-content/uploads/2007/12/touchlib_barreldistortion_tool.zip
example of usage:
Place the camera.yml (created by the calibration tool) in the same directory as the config.xml
*/
#include
BarrelDistortionCorrectionFilter::BarrelDistortionCorrectionFilter(char* s) : Filter(s)
{
CvFileNode *node;
const char* configfile = "camera.yml";
CvFileStorage *fs = cvOpenFileStorage( configfile, 0, CV_STORAGE_READ );
node = cvGetFileNodeByName (fs, NULL, "camera_matrix");
camera = (CvMat *) cvRead (fs, node);
node = cvGetFileNodeByName (fs, NULL, "distortion_coefficients");
dist_coeffs = (CvMat *) cvRead (fs, node);
cvReleaseFileStorage (&fs);
border_size = 0;
init = false;
init2 = false;
MapX = NULL;
MapY = NULL;
}
BarrelDistortionCorrectionFilter::~BarrelDistortionCorrectionFilter()
{
cvReleaseMat(&b_intrinsic);
if(init2)
{
cvReleaseImage(&MapX);
cvReleaseImage(&MapY);
cvReleaseImage(&bordered);
cvReleaseImage(&bordered_corr);
}
}
void BarrelDistortionCorrectionFilter::getParameters(ParameterMap& pMap)
{
pMap[std::string("border_size")] = toString(border_size);
}
void BarrelDistortionCorrectionFilter::setParameter(const char *name, const char *value)
{
if(strcmp(name, "border_size") == 0)
{
border_size = (int) atof(value);
}
}
void BarrelDistortionCorrectionFilter::kernel()
{
if( !destination )
{
destination = cvCreateImage(cvSize(source->width,source->height), source->depth, source->nChannels);
destination->origin = source->origin; // same vertical flip as source
}
// Make option to choose method
if(border_size>0)
//destination = undistorted_with_border( source, camera, dist_coeffs, border_size );
destination = undistorted_with_border2( source, camera, dist_coeffs, border_size );
else
//cvUndistort2( source, destination, camera, dist_coeffs );
destination = undistorted_with_border2( source, camera, dist_coeffs, 0);
}
IplImage* BarrelDistortionCorrectionFilter::undistorted_with_border( const IplImage *image, const CvMat *intrinsic,const CvMat *distortion, short int border )
{
if(!init)
{
//move cx,cy (intrinsic point)
b_intrinsic = cvCloneMat( intrinsic );
cvSetReal2D( b_intrinsic, 0,2, cvGetReal2D(b_intrinsic,0,2)+border );
cvSetReal2D( b_intrinsic, 1,2, cvGetReal2D(b_intrinsic,1,2)+border );
bordered = cvCreateImage( cvSize(image->width+2*border,image->height+2*border), image->depth, image->nChannels );
bordered_corr = cvCreateImage( cvSize(image->width+2*border,image->height+2*border), image->depth, image->nChannels );
init = true;
}
//add border to image
cvCopyMakeBorder( image, bordered, cvPoint(border,border), IPL_BORDER_CONSTANT, cvScalarAll(0) );
//undistort
cvUndistort2( bordered, bordered_corr, b_intrinsic, distortion );
return bordered_corr;
}
IplImage* BarrelDistortionCorrectionFilter::undistorted_with_border2( const IplImage *image, const CvMat *intrinsic,const CvMat *distortion, short int border )
{
if(!init2)
{
//move cx,cy (intrinsic point)
b_intrinsic = cvCloneMat( intrinsic );
cvSetReal2D( b_intrinsic, 0,2, cvGetReal2D(b_intrinsic,0,2)+border );
cvSetReal2D( b_intrinsic, 1,2, cvGetReal2D(b_intrinsic,1,2)+border );
bordered = cvCreateImage( cvSize(image->width+2*border,image->height+2*border), image->depth, image->nChannels );
bordered_corr = cvCreateImage( cvSize(image->width+2*border,image->height+2*border), image->depth, image->nChannels );
// Create a undistort map
MapX = cvCreateImage(cvSize(bordered_corr->width,bordered_corr->height), IPL_DEPTH_32F, 1);
MapY = cvCreateImage(cvSize(bordered_corr->width,bordered_corr->height), IPL_DEPTH_32F, 1);
cvInitUndistortMap( b_intrinsic, distortion, MapX, MapY);
init2 = true;
}
//add border to image
cvCopyMakeBorder( image, bordered, cvPoint(border,border), IPL_BORDER_CONSTANT, cvScalarAll(0) );
//undistort
cvRemap(bordered, bordered_corr, MapX, MapY, CV_INTER_LINEAR, cvScalarAll(0));
// Fix origin
bordered_corr->origin = image->origin;
return bordered_corr;
}