From: <bl...@us...> - 2009-07-06 17:15:57
|
Revision: 3996 http://hugin.svn.sourceforge.net/hugin/?rev=3996&view=rev Author: blimbo Date: 2009-07-06 17:15:49 +0000 (Mon, 06 Jul 2009) Log Message: ----------- Altered orientation code, added some mapping code, bug fixes Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/CMakeLists.txt hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp Added Paths: ----------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.h Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/CMakeLists.txt =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/CMakeLists.txt 2009-07-05 18:03:30 UTC (rev 3995) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/CMakeLists.txt 2009-07-06 17:15:49 UTC (rev 3996) @@ -2,6 +2,7 @@ Main.cpp Globals.cpp #PointLineDist.cpp +MapPoints.cpp ProcessImage.cpp #LineParamEstimator.cpp #PolynomialEstimator.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-05 18:03:30 UTC (rev 3995) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-06 17:15:49 UTC (rev 3996) @@ -30,11 +30,13 @@ std::string format = (".jpg"); double sizefactor = 1; double threshold = 8; -double length_threshold = 0.2; +double length_threshold = 0.3; double min_line_length_squared; double scale = 2; double tscale = 1.45; -unsigned int gap_limit = 3; +double a = 140.0; +double corner_threshold = 200; +unsigned int gap_limit = 4; unsigned int vertical_slices = 12; unsigned int horizontal_slices = 8; unsigned int generate_images = 1; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-05 18:03:30 UTC (rev 3995) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-06 17:15:49 UTC (rev 3996) @@ -15,7 +15,9 @@ extern double length_threshold; extern double min_line_length_squared; extern double scale; -extern double tscale; +extern double tscale; +extern double a; +extern double corner_threshold; extern unsigned int gap_limit; extern unsigned int horizontal_slices; extern unsigned int vertical_slices; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-05 18:03:30 UTC (rev 3995) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-06 17:15:49 UTC (rev 3996) @@ -304,10 +304,12 @@ cout << " -s <float> Edge detector scale. Default 2" << endl; cout << " -t <float> Edge detector threshold. Default 8" << endl; cout << " -b <float> Boundary tensor scale. Default 1.45" << endl; - cout << " -g <int> Gap in pixels permitted within a line. Default 3" << endl; - cout << " -l <float> Minimum line length as a fraction of longest dimension. Default 0.2" << endl; + cout << " -g <int> Gap in pixels permitted within a line. Default 4" << endl; + cout << " -l <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; cout << " -r <float> Rho parameter for hourglass filter. Default 0.4" << endl; + cout << " -y <float> Corner threshold. Default 200" << endl; + cout << " -a <float> Lens HFoV in degrees. Default 140" << endl; cout << " -i <0|1> Generate intermediate images. Default 1" << endl; cout << " -v <0|1> Verbose. Default 0" << endl; cout << " -h Print usage." << endl; @@ -354,7 +356,9 @@ case 'd' : {resize_dimension = atoi(argv[i]); break;} case 's' : {scale = atof(argv[i]); break;} case 'b' : {tscale = atof(argv[i]); break;} + case 'a' : {a = atof(argv[i]); break;} case 't' : {threshold = atof(argv[i]); break;} + case 'y' : {corner_threshold = atof(argv[i]); break;} case 'l' : {length_threshold = atof(argv[i]); break;} case 'i' : {generate_images = atoi(argv[i]); break;} case 'm' : {sigma = atof(argv[i]); break;} Added: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp (rev 0) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-06 17:15:49 UTC (rev 3996) @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2009 by Tim Nugent * + * tim...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "vigra/diff2d.hxx" +#include <iostream> +#include <stdio.h> +#include <math.h> +#include "Globals.h" + +using namespace vigra; +using namespace std; + +void map_points(int w, int h){ + +/* + + For example the Cartesian coordinates of the point on the unit radius sphere = a vector of length 1 in the direction of view. + Assuming Y is up, X left and the optical axis points toward +Z, that can be computed from the pixel coordinates (u,v) and + the "true" radial angle, a, as follows: + + z = cos( a ); + s = sqrt((1 - z * z) / ( u * u + v * v )); + x = -s * u; // I said x runs left, I'm assuming u runs right + y = s * v; + + Note (u,v) direction in the plane z = cos(a) is same as in image plane z = 1. So + you get (x,y) by scaling (u,v). + +*/ + + // Covert degrees to radians + a = a / (180/M_PI); + + cout << "Mapping points..." << endl; + cout << "Width:\t" << w << endl << "Height:\t" << h << endl << "HFov:\t" << a << endl << endl; + + double u,v,z,s,x,y; + + for (unsigned int l = 0; l < lines.size(); l++){ + + cout << "Processing line " << l+1 << ":" << endl; + + for (unsigned int i = 0; i < lines[l].size(); i++){ + + u = lines[l][i]->x; + v = lines[l][i]->y; + cout << u << "," << v << "\t=>\t"; + + // Move coordinates so 0,0 is in the centre of the image + u += w/2; + v *= -1; + v += h/2; + cout << u << "," << v << "\t=>\t"; + + z = cos( a ); + s = sqrt((1 - z * z) / ( u * u + v * v )); + x = -s * u; + y = s * v; + cout << x << "," << y << "," << z << endl; + + } + cout << endl; + + } + } Added: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.h (rev 0) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.h 2009-07-06 17:15:49 UTC (rev 3996) @@ -0,0 +1,6 @@ +#ifndef MAPPOINTS_H +#define MAPPOINTS_H + +void map_points(int, int); + +#endif Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-05 18:03:30 UTC (rev 3995) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-06 17:15:49 UTC (rev 3996) @@ -29,6 +29,8 @@ #include <vigra/rgbvalue.hxx> #include "Globals.h" #include "ProcessImage.h" +#include "MapPoints.h" + //#include "Ransac.h" //#include "SplineEstimator.h" //#include "LineParamEstimator.h" @@ -161,6 +163,7 @@ queryPt[1] = coords[queryidx]->y; double orientation_scale = 1; + double orientation_threshold = 0.2; // Add direction as 3rd dimension double first_o; @@ -189,7 +192,7 @@ double previous_length = 0; int first_line_end_x = first_x, first_line_end_y = first_y; - if(verbose) cout << "Query Pixel\tNN Pixel\tIndex\tDistance" << endl; + if(verbose) cout << "Query Pixel\tNN Pixel\tIndex\tDistance\tOrientation diff" << endl; while (cont){ @@ -229,15 +232,18 @@ } } - //kdTree = new ANNkd_tree(dataPts,nPts,2); - kdTree = new ANNkd_tree(dataPts,nPts,dim); + kdTree = new ANNkd_tree(dataPts,nPts,2); + //kdTree = new ANNkd_tree(dataPts,nPts,dim); kdTree->annkSearch(queryPt,k,nnIdx,dists,eps); dists[0] = sqrt(dists[0]); double this_length = line_length_squared(first_x,first_y,close_neighbors[nnIdx[0]]->x,close_neighbors[nnIdx[0]]->y); + + double orientation_diff = abs(queryPt[2] - dataPts[nnIdx[0]][2]); + //double orientation_diff = abs(first_o - dataPts[nnIdx[0]][2]); if (this_length < previous_length){ - if(verbose) cout << "(" << queryPt[0] << "," << queryPt[1] << "," << queryPt[2] << ")\t(" << close_neighbors[nnIdx[0]]->x << "," << close_neighbors[nnIdx[0]]->y << ")" << "\t" << nnIdx[0] << "\t" << dists[0] << endl; + if(verbose) cout << "(" << queryPt[0] << "," << queryPt[1] << "," << queryPt[2] << ")\t(" << close_neighbors[nnIdx[0]]->x << "," << close_neighbors[nnIdx[0]]->y << ")" << "\t" << nnIdx[0] << "\t" << dists[0] << "\t" << orientation_diff << endl; if(verbose) cout << "This point is closer to the inital query pixel than the previous one..." << endl; // Go back to the start point and go down the line in the reverse direction @@ -263,25 +269,38 @@ //if(verbose) cout << "End of line reached." << endl; //cont = 0; } - }else{ - if(verbose) cout << "(" << queryPt[0] << "," << queryPt[1] << "," << queryPt[2] << ")\t(" << close_neighbors[nnIdx[0]]->x << "," << close_neighbors[nnIdx[0]]->y << ")" << "\t" << nnIdx[0] << "\t" << dists[0] << endl; + }else{ + + if (orientation_diff < orientation_threshold){ + + if(verbose) cout << "(" << queryPt[0] << "," << queryPt[1] << "," << queryPt[2] << ")\t(" << close_neighbors[nnIdx[0]]->x << "," << + close_neighbors[nnIdx[0]]->y << ")" << "\t" << nnIdx[0] << "\t" << dists[0] << "\t" << orientation_diff << endl; - // Set query point to NN - queryPt[0] = close_neighbors[nnIdx[0]]->x; - queryPt[1] = close_neighbors[nnIdx[0]]->y; + // Set query point to NN + queryPt[0] = close_neighbors[nnIdx[0]]->x; + queryPt[1] = close_neighbors[nnIdx[0]]->y; - // Add direction as 3rd dimension - if (dim > 2){ - TinyVector<float, 2> value = edgeness(queryPt[0],queryPt[1]); - queryPt[2] = value[1] * orientation_scale; - } + // Add direction as 3rd dimension + if (dim > 2){ + TinyVector<float, 2> value = edgeness(queryPt[0],queryPt[1]); + queryPt[2] = value[1] * orientation_scale; + } - // Add NN to inliers - inliers.push_back(close_neighbors[nnIdx[0]]); + // Add NN to inliers + inliers.push_back(close_neighbors[nnIdx[0]]); - // Erase it from coords so we don't see it again - coords.erase(coords.begin()+coords_index[nnIdx[0]]); - previous_length = this_length; + // Erase it from coords so we don't see it again + coords.erase(coords.begin()+coords_index[nnIdx[0]]); + previous_length = this_length; + }else{ + + if(verbose) cout << "Pixel orientation is significantly different from query:\t" << orientation_diff << endl; + + // Erase it from coords so we don't see it again + coords.erase(coords.begin()+coords_index[nnIdx[0]]); + + } + } // Clean up @@ -502,7 +521,7 @@ for (unsigned int w = 0; w < corners.width(); w++){ // Change this threshold to remove more corner pixels - if (corners(w,h) > 200){ + if (corners(w,h) > corner_threshold){ // Change the size of the box to draw around corner pixel int size = 3; @@ -758,5 +777,6 @@ exportImage(srcImageRange(cornerness), ImageExportInfo(output.c_str()).setPixelType("UINT8")); detect_edge(grey, cornerness, edgeness, filename, path, format); + map_points(nw, nh); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-06 22:34:19
|
Revision: 3997 http://hugin.svn.sourceforge.net/hugin/?rev=3997&view=rev Author: blimbo Date: 2009-07-06 22:34:11 +0000 (Mon, 06 Jul 2009) Log Message: ----------- Trying to track down segfault, caused by double free I think Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-06 17:15:49 UTC (rev 3996) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-06 22:34:11 UTC (rev 3997) @@ -320,11 +320,6 @@ int main(int argc, const char* argv[]){ - // Exit with usage unless filename given as argument - if (argc < 2){ - usage(); - } - unsigned int i = 1; unsigned int pto_image = 0; unsigned int cps_per_line = 10; @@ -388,6 +383,8 @@ } } + //images.push_back("/home/tnugent/src/gsoc2009_lenscalibration/src/lens_calibrate/dsc_0040.jpg"; + if (!images.size()){ //cout << "No images provided!" << endl << endl; usage(); Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-06 17:15:49 UTC (rev 3996) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-06 22:34:11 UTC (rev 3997) @@ -336,6 +336,14 @@ //annDeallocPt(queryPt); annClose(); +/* +export MALLOC_CHECK=0 + +Program received signal SIGSEGV, Segmentation fault. +[Switching to Thread 0xb714c6d0 (LWP 7191)] +0xb720958d in free () from /lib/tls/i686/cmov/libc.so.6 +*/ + double length = line_length_squared(first_line_end_x, first_line_end_y,inliers[inliers.size()-1]->x,inliers[inliers.size()-1]->y); if(verbose) cout << endl << "Measuring distance from " << first_line_end_x << "," << first_line_end_y << " to " << inliers[inliers.size()-1]->x << "," << This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-09 17:25:44
|
Revision: 4015 http://hugin.svn.sourceforge.net/hugin/?rev=4015&view=rev Author: blimbo Date: 2009-07-09 17:25:41 +0000 (Thu, 09 Jul 2009) Log Message: ----------- Altered mapping code, function to measure 3d point to line dist Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-08 23:02:12 UTC (rev 4014) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-09 17:25:41 UTC (rev 4015) @@ -25,6 +25,8 @@ unsigned int verbose = 0; unsigned int resize_dimension = 800; unsigned int detector = 0; +unsigned int lens_type = 1; +double focal_length = 10; std::string path = ("output/"); //std::string path = (""); std::string format = (".jpg"); Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-08 23:02:12 UTC (rev 4014) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-09 17:25:41 UTC (rev 4015) @@ -8,6 +8,8 @@ extern unsigned int verbose; extern unsigned int resize_dimension; extern unsigned int detector; +extern unsigned int lens_type; +extern double focal_length; extern std::string path; extern std::string format; extern double sizefactor; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-08 23:02:12 UTC (rev 4014) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-09 17:25:41 UTC (rev 4015) @@ -308,8 +308,11 @@ cout << " -l <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; cout << " -r <float> Rho parameter for hourglass filter. Default 0.4" << endl; - cout << " -y <float> Corner threshold. Default 200" << endl; - cout << " -a <float> Lens HFoV in degrees. Default 140" << endl; + cout << " -y <float> Corner threshold. Default 200" << endl; + cout << " -q <float> Focal length. Default 10" << endl; + cout << " -k <int> Lens type. 1 = Rectilinear (default)" << endl; + cout << " 2 = Equal-area fisheye" << endl; + cout << " 3 = Equal-angle fisheye" << endl; cout << " -i <0|1> Generate intermediate images. Default 1" << endl; cout << " -v <0|1> Verbose. Default 0" << endl; cout << " -h Print usage." << endl; @@ -356,6 +359,8 @@ case 'y' : {corner_threshold = atof(argv[i]); break;} case 'l' : {length_threshold = atof(argv[i]); break;} case 'i' : {generate_images = atoi(argv[i]); break;} + case 'k' : {lens_type = atoi(argv[i]); break;} + case 'q' : {focal_length = atof(argv[i]); break;} case 'm' : {sigma = atof(argv[i]); break;} case 'r' : {rho = atof(argv[i]); break;} } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-08 23:02:12 UTC (rev 4014) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-09 17:25:41 UTC (rev 4015) @@ -17,16 +17,44 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ - -#include "vigra/diff2d.hxx" + #include <iostream> #include <stdio.h> #include <math.h> #include "Globals.h" - -using namespace vigra; + using namespace std; + +typedef struct { + double x, y, z; +} XYZPoint; + +double magnitude(XYZPoint *Point1, XYZPoint *Point2){ + + XYZPoint Vector; + Vector.x = Point2->x - Point1->x; + Vector.y = Point2->y - Point1->y; + Vector.z = Point2->z - Point1->z; + return (double)sqrt( Vector.x * Vector.x + Vector.y * Vector.y + Vector.z * Vector.z); +} + +double DistancePointLine(XYZPoint *Point, XYZPoint *linestart, XYZPoint *lineend, double LineMag){ + + double U; + XYZPoint intersection; + U = ( ( ( Point->x - linestart->x ) * (lineend->x - linestart->x ) ) + + ( ( Point->y - linestart->y ) * (lineend->y - linestart->y ) ) + + ( ( Point->z - linestart->z ) * (lineend->z - linestart->z ) ) ) / + ( LineMag * LineMag ); + + intersection.x = linestart->x + U * (lineend->x - linestart->x); + intersection.y = linestart->y + U * (lineend->y - linestart->y); + intersection.z = linestart->z + U * (lineend->z - linestart->z); + + return magnitude(Point, &intersection); +} + void map_points(int w, int h){ /* @@ -46,18 +74,63 @@ */ // Covert degrees to radians - a = a / (180/M_PI); + // a is set on the command line + //a = a / (180/M_PI); - cout << "Mapping points..." << endl; - cout << "Width:\t" << w << endl << "Height:\t" << h << endl << "HFov:\t" << a << endl << endl; + string lens_name = ("Rectilinear"); + + double r = 1.5; + double u = r / focal_length; + double p2 = 1; + double p4 = 1; + double k = 2; + double R = u + p2 * (u*u) + p4 * (u*u*u*u); + + if (lens_type == 2){ + a = k * asin( R / k ); // for an equal-area type fisheye (design parameter k) + lens_name = ("Equal-area fisheye"); + }else if (lens_type == 3){ + a = R; // for a true equal-angle fisheye. + lens_name = ("Equal-angle fisheye"); + }else{ + a = atan( R ); // for a rectilinear lens + } + + cout << "Mapping points..." << endl; + cout << "Lens type:\t" << lens_name << endl; + cout << "Width:\t\t" << w << endl << "Height:\t\t" << h << endl << "a:\t\t" << a << endl << endl; - double u,v,z,s,x,y; + double v,z,s,x,y; for (unsigned int l = 0; l < lines.size(); l++){ cout << "Processing line " << l+1 << ":" << endl; + + XYZPoint LineStart, LineEnd; + + u = lines[l][0]->x; + v = lines[l][0]->y; + u += w/2; + v *= -1; + v += h/2; + s = sqrt((1 - z * z) / ( u * u + v * v )); + LineStart.x = -s * u; + LineStart.y = s * v; + LineStart.z = cos(a); - for (unsigned int i = 0; i < lines[l].size(); i++){ + u = lines[l][lines[l].size()]->x; + v = lines[l][lines[l].size()]->y; + u += w/2; + v *= -1; + v += h/2; + s = sqrt((1 - z * z) / ( u * u + v * v )); + LineEnd.x = -s * u; + LineEnd.y = s * v; + LineEnd.z = cos(a); + + double LineMag = magnitude(&LineEnd, &LineStart); + + for (unsigned int i = 1; i < lines[l].size()-1; i++){ u = lines[l][i]->x; v = lines[l][i]->y; @@ -67,13 +140,17 @@ u += w/2; v *= -1; v += h/2; - cout << u << "," << v << "\t=>\t"; + cout << u << "," << v << "\t=>\t"; - z = cos( a ); s = sqrt((1 - z * z) / ( u * u + v * v )); - x = -s * u; - y = s * v; - cout << x << "," << y << "," << z << endl; + XYZPoint Point; + Point.x = -s * u; + Point.y = s * v; + Point.z = cos(a); + + double distance = DistancePointLine(&Point, &LineStart, &LineEnd, LineMag); + + cout << x << "," << y << "," << z << "\tDistance:\t" << distance <<endl; } cout << endl; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-09 22:54:48
|
Revision: 4018 http://hugin.svn.sourceforge.net/hugin/?rev=4018&view=rev Author: blimbo Date: 2009-07-09 22:54:46 +0000 (Thu, 09 Jul 2009) Log Message: ----------- Minor fix Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-09 18:09:53 UTC (rev 4017) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-09 22:54:46 UTC (rev 4018) @@ -388,7 +388,7 @@ } } - //images.push_back("/home/tnugent/src/gsoc2009_lenscalibration/src/lens_calibrate/dsc_0040.jpg"; + //images.push_back("/home/tnugent/src/gsoc2009_lenscalibration/src/lens_calibrate/dsc_0040.jpg"); if (!images.size()){ //cout << "No images provided!" << endl << endl; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-09 18:09:53 UTC (rev 4017) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-09 22:54:46 UTC (rev 4018) @@ -114,9 +114,10 @@ v *= -1; v += h/2; s = sqrt((1 - z * z) / ( u * u + v * v )); + z = cos(a); LineStart.x = -s * u; LineStart.y = s * v; - LineStart.z = cos(a); + LineStart.z = z; u = lines[l][lines[l].size()]->x; v = lines[l][lines[l].size()]->y; @@ -126,7 +127,7 @@ s = sqrt((1 - z * z) / ( u * u + v * v )); LineEnd.x = -s * u; LineEnd.y = s * v; - LineEnd.z = cos(a); + LineEnd.z = z; double LineMag = magnitude(&LineEnd, &LineStart); @@ -140,13 +141,14 @@ u += w/2; v *= -1; v += h/2; + z = cos(a); cout << u << "," << v << "\t=>\t"; s = sqrt((1 - z * z) / ( u * u + v * v )); XYZPoint Point; Point.x = -s * u; Point.y = s * v; - Point.z = cos(a); + Point.z = z; double distance = DistancePointLine(&Point, &LineStart, &LineEnd, LineMag); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-10 15:05:41
|
Revision: 4022 http://hugin.svn.sourceforge.net/hugin/?rev=4022&view=rev Author: blimbo Date: 2009-07-10 15:05:32 +0000 (Fri, 10 Jul 2009) Log Message: ----------- Minor changes Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-10 14:33:29 UTC (rev 4021) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-10 15:05:32 UTC (rev 4022) @@ -26,7 +26,7 @@ unsigned int resize_dimension = 800; unsigned int detector = 0; unsigned int lens_type = 1; -double focal_length = 10; +double focal_length = 15; std::string path = ("output/"); //std::string path = (""); std::string format = (".jpg"); @@ -45,4 +45,4 @@ std::vector<vigra::Point2D> inliers; std::vector<std::vector<vigra::Point2D> > lines; double sigma = 1.4; -double rho = 0.4; +double r = 140; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-10 14:33:29 UTC (rev 4021) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-10 15:05:32 UTC (rev 4022) @@ -28,6 +28,6 @@ extern std::vector<vigra::Point2D> inliers; extern std::vector<std::vector<vigra::Point2D> > lines; extern double sigma; -extern double rho; +extern double r; #endif Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-10 14:33:29 UTC (rev 4021) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-10 15:05:32 UTC (rev 4022) @@ -307,9 +307,9 @@ cout << " -g <int> Gap in pixels permitted within a line. Default 4" << endl; cout << " -l <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; - cout << " -r <float> Rho parameter for hourglass filter. Default 0.4" << endl; cout << " -y <float> Corner threshold. Default 200" << endl; - cout << " -q <float> Focal length. Default 10" << endl; + cout << " -r <float> Lens HFoV in degrees. Default 140" << endl; + cout << " -q <float> Focal length. Default 15" << endl; cout << " -k <int> Lens type. 1 = Rectilinear (default)" << endl; cout << " 2 = Equal-area fisheye" << endl; cout << " 3 = Equal-angle fisheye" << endl; @@ -362,7 +362,7 @@ case 'k' : {lens_type = atoi(argv[i]); break;} case 'q' : {focal_length = atof(argv[i]); break;} case 'm' : {sigma = atof(argv[i]); break;} - case 'r' : {rho = atof(argv[i]); break;} + case 'r' : {r = atof(argv[i]); break;} } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-10 14:33:29 UTC (rev 4021) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-10 15:05:32 UTC (rev 4022) @@ -74,12 +74,11 @@ */ // Covert degrees to radians - // a is set on the command line - //a = a / (180/M_PI); + // r is set on the command line + r = r / (180/M_PI); string lens_name = ("Rectilinear"); - double r = 1.5; double u = r / focal_length; double p2 = 1; double p4 = 1; @@ -96,9 +95,12 @@ a = atan( R ); // for a rectilinear lens } - cout << "Mapping points..." << endl; + cout << "Mapping points..." << endl << endl; cout << "Lens type:\t" << lens_name << endl; - cout << "Width:\t\t" << w << endl << "Height:\t\t" << h << endl << "a:\t\t" << a << endl << endl; + cout << "Width:\t\t" << w << endl << "Height:\t\t" << h << endl; + cout << "a:\t\t" << a << endl; + cout << "r:\t\t" << r << endl; + cout << "R:\t\t" << R << endl << endl; double v,z,s,x,y; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-15 17:35:14
|
Revision: 4042 http://hugin.svn.sourceforge.net/hugin/?rev=4042&view=rev Author: blimbo Date: 2009-07-15 17:34:59 +0000 (Wed, 15 Jul 2009) Log Message: ----------- Added LM function for optimisation Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-13 23:04:18 UTC (rev 4041) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-15 17:34:59 UTC (rev 4042) @@ -26,7 +26,11 @@ unsigned int resize_dimension = 800; unsigned int detector = 0; unsigned int lens_type = 1; +unsigned int current_line = 0;; +double original_width = 0; +double original_height = 0;; double focal_length = 15; +double pixel_density = 300; std::string path = ("output/"); //std::string path = (""); std::string format = (".jpg"); Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-13 23:04:18 UTC (rev 4041) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-15 17:34:59 UTC (rev 4042) @@ -9,7 +9,11 @@ extern unsigned int resize_dimension; extern unsigned int detector; extern unsigned int lens_type; +extern unsigned int current_line; +extern double original_width; +extern double original_height; extern double focal_length; +extern double pixel_density; extern std::string path; extern std::string format; extern double sizefactor; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-13 23:04:18 UTC (rev 4041) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-15 17:34:59 UTC (rev 4042) @@ -303,17 +303,17 @@ cout << " -o <path> Output path. Default output/" << endl; cout << " -s <float> Edge detector scale. Default 2" << endl; cout << " -t <float> Edge detector threshold. Default 8" << endl; - cout << " -b <float> Boundary tensor scale. Default 1.45" << endl; + //cout << " -b <float> Boundary tensor scale. Default 1.45" << endl; cout << " -g <int> Gap in pixels permitted within a line. Default 4" << endl; cout << " -l <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; - cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; - cout << " -y <float> Corner threshold. Default 200" << endl; - cout << " -r <float> Lens HFoV in degrees. Default 140" << endl; + //cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; + //cout << " -y <float> Corner threshold. Default 200" << endl; + cout << " -i <float> Pixel density in pixels/inch. Default 300" << endl; cout << " -q <float> Focal length. Default 15" << endl; cout << " -k <int> Lens type. 1 = Rectilinear (default)" << endl; cout << " 2 = Equal-area fisheye" << endl; cout << " 3 = Equal-angle fisheye" << endl; - cout << " -i <0|1> Generate intermediate images. Default 1" << endl; + //cout << " -i <0|1> Generate intermediate images. Default 1" << endl; cout << " -v <0|1> Verbose. Default 0" << endl; cout << " -h Print usage." << endl; cout << endl; @@ -358,7 +358,7 @@ case 't' : {threshold = atof(argv[i]); break;} case 'y' : {corner_threshold = atof(argv[i]); break;} case 'l' : {length_threshold = atof(argv[i]); break;} - case 'i' : {generate_images = atoi(argv[i]); break;} + case 'i' : {pixel_density = atof(argv[i]); break;} case 'k' : {lens_type = atoi(argv[i]); break;} case 'q' : {focal_length = atof(argv[i]); break;} case 'm' : {sigma = atof(argv[i]); break;} Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-13 23:04:18 UTC (rev 4041) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-15 17:34:59 UTC (rev 4042) @@ -21,6 +21,7 @@ #include <iostream> #include <stdio.h> #include <math.h> +#include <levmar/lm.h> #include "Globals.h" using namespace std; @@ -29,135 +30,169 @@ double x, y, z; } XYZPoint; -double magnitude(XYZPoint *Point1, XYZPoint *Point2){ +XYZPoint CrossProduct (XYZPoint v1, XYZPoint v2){ + XYZPoint cp; + cp.x = v1.y * v2.z - v1.z * v2.y; + cp.y = v1.z * v2.x - v1.x * v2.z; + cp.z = v1.x * v2.y - v1.y * v2.x; + return(cp); +} - XYZPoint Vector; - Vector.x = Point2->x - Point1->x; - Vector.y = Point2->y - Point1->y; - Vector.z = Point2->z - Point1->z; - return (double)sqrt( Vector.x * Vector.x + Vector.y * Vector.y + Vector.z * Vector.z); +double DotProduct (XYZPoint v1, XYZPoint v2){ + return((v1.x*v2.x + v1.y*v2.y + v1.z*v2.z)); } -double DistancePointLine(XYZPoint *Point, XYZPoint *linestart, XYZPoint *lineend, double LineMag){ - - double U; - XYZPoint intersection; - - U = ( ( ( Point->x - linestart->x ) * (lineend->x - linestart->x ) ) + - ( ( Point->y - linestart->y ) * (lineend->y - linestart->y ) ) + - ( ( Point->z - linestart->z ) * (lineend->z - linestart->z ) ) ) / - ( LineMag * LineMag ); - - intersection.x = linestart->x + U * (lineend->x - linestart->x); - intersection.y = linestart->y + U * (lineend->y - linestart->y); - intersection.z = linestart->z + U * (lineend->z - linestart->z); - - return magnitude(Point, &intersection); +double PointPointDist(double x1, double y1, double x2, double y2){ + double d1 = x1 - x2; + double d2 = y1 - y2; + return sqrt(d1*d1+d2*d2); } - -void map_points(int w, int h){ -/* +void Mapto3d (double *p, double *x, int m, int n, void *data){ + + XYZPoint mapped_point[n]; - For example the Cartesian coordinates of the point on the unit radius sphere = a vector of length 1 in the direction of view. - Assuming Y is up, X left and the optical axis points toward +Z, that can be computed from the pixel coordinates (u,v) and - the "true" radial angle, a, as follows: - - z = cos( a ); - s = sqrt((1 - z * z) / ( u * u + v * v )); - x = -s * u; // I said x runs left, I'm assuming u runs right - y = s * v; - - Note (u,v) direction in the plane z = cos(a) is same as in image plane z = 1. So - you get (x,y) by scaling (u,v). - -*/ + // Re-scale pixles + double invert_size_factor = 1.0/sizefactor; - // Covert degrees to radians - // r is set on the command line - r = r * (M_PI/180); - - string lens_name = ("Rectilinear"); + // Map points to 3D and fill the above array with XYZPoints + for(unsigned int i = 0; i < n; i++){ - double u = r / focal_length; - double p2 = 1; - double p4 = 1; - double k = 2; - double R = u + p2 * (u*u) + p4 * (u*u*u*u); + double x_point = invert_size_factor * lines[current_line][n]->x; + double y_point = invert_size_factor * lines[current_line][n]->y; - if (lens_type == 2){ - a = k * asin( R / k ); // for an equal-area type fisheye (design parameter k) - lens_name = ("Equal-area fisheye"); - }else if (lens_type == 3){ - a = R; // for a true equal-angle fisheye. - lens_name = ("Equal-angle fisheye"); - }else{ - a = atan( R ); // for a rectilinear lens + // Move coordinates so 0,0 is in the centre of the image + x_point += original_width/2; + y_point *= -1; + y_point += original_height/2; + + // r - distance of a point from the center of projection, in pixels + double r = PointPointDist(x_point,y_point,p[1],p[2]); + + // u = r / f; + double u = r / p[0]; + + // R - distance of a point from the center of projection, corrected for barrel distortion, unitless, or radians + // (1 - p2 - p4) is for normalisation + // p2 = p[3], p4 = [4] + double R = (1 - p[3] - p[4]) * u + p[3] * (u*u) + p[4] * (u*u*u*u); + + // a - angular distance of a point from the center of projection, in radians + double a; + + if (lens_type == 2){ + + // k - equal-area type fisheye design parameter, initial value of 2 + double k = p[5]; + a = k * asin( R / k ); + + }else if (lens_type == 3){ + // Equal-angle fisheye + a = R; // for a true equal-angle fisheye. + }else{ + // Rectilinear lens + a = atan( R ); + } + + double z = cos(a); + + double s = sqrt((1 - z * z) / ( x_point * x_point + y_point * y_point )); + + XYZPoint Point; + + Point.x = -s * x_point; + Point.y = s * y_point; + Point.z = z; + + mapped_point[i] = Point; + + cout << current_line+1 << "\t" << i << "\t(" << Point.x << "," << Point.y << "," << Point.z << ")" << endl; + } - cout << "Mapping points..." << endl << endl; - cout << "Lens type:\t" << lens_name << endl; - cout << "Width:\t\t" << w << endl << "Height:\t\t" << h << endl; - cout << "a:\t\t" << a << endl; - cout << "r:\t\t" << r << endl; - cout << "R:\t\t" << R << endl << endl; - - double v,z,s,x,y; - - for (unsigned int l = 0; l < lines.size(); l++){ + // Vector cross product of the end points - this is the normal to the estimated plane + XYZPoint norm = CrossProduct(mapped_point[0],mapped_point[n-1]); - cout << "Processing line " << l+1 << ":" << endl; + cout << endl << "Cross product of end points:" << endl; + cout << norm.x << endl; + cout << norm.y << endl; + cout << norm.z << endl << endl; - XYZPoint LineStart, LineEnd; - - u = lines[l][0]->x; - v = lines[l][0]->y; - u += w/2; - v *= -1; - v += h/2; - s = sqrt((1 - z * z) / ( u * u + v * v )); - z = cos(a); - LineStart.x = -s * u; - LineStart.y = s * v; - LineStart.z = z; + double ssq = 0; + + // Comput straigthness error + for(unsigned int i = 1; i < n - 1; i++){ + // Add square of dot product of that point with norm + ssq += sqrt(DotProduct(norm,mapped_point[i])); + } + // Add to optimizer's error vector + for(unsigned int i = 1; i < n - 1; i++){ + x[i] = sqrt((n - 2) * ssq ); + } + cout << "Error:\t" << x[0] << endl << endl; + - u = lines[l][lines[l].size()]->x; - v = lines[l][lines[l].size()]->y; - u += w/2; - v *= -1; - v += h/2; - s = sqrt((1 - z * z) / ( u * u + v * v )); - LineEnd.x = -s * u; - LineEnd.y = s * v; - LineEnd.z = z; +} + +int visf (double *p, double *hx, int m, int n, int iter, double p_eL2, void *adata){ + + // What goes here?? + +} + +void map_points(){ + + cout << "Focal length (mm):\t" << focal_length << endl; + // Convert focal length to pixels + // 1 mm = 0.0393700787402 inches + focal_length = (focal_length * 0.0393700787402) * pixel_density; + cout << "Focal length (pixels):\t" << focal_length << endl << endl; + + int iterations = 1000; + double opts[5]; + double info[LM_INFO_SZ]; + + for (unsigned int l = 0; l < lines.size(); l++){ + + current_line = l; + + // Set up initial parameters + int m = 6; + double * p = new double[m]; - double LineMag = magnitude(&LineEnd, &LineStart); + p[0] = focal_length; // from command line -- needs to be corrected as we re-size image?? + p[1] = 0; // x_center; + p[2] = 0; // y_center; + p[3] = 0; // p2 + p[4] = 0; // p4 - for (unsigned int i = 1; i < lines[l].size()-1; i++){ - - u = lines[l][i]->x; - v = lines[l][i]->y; - cout << u << "," << v << "\t=>\t"; - - // Move coordinates so 0,0 is in the centre of the image - u += w/2; - v *= -1; - v += h/2; - z = cos(a); - cout << u << "," << v << "\t=>\t"; - - s = sqrt((1 - z * z) / ( u * u + v * v )); - XYZPoint Point; - Point.x = -s * u; - Point.y = s * v; - Point.z = z; - - double distance = DistancePointLine(&Point, &LineStart, &LineEnd, LineMag); - - cout << x << "," << y << "," << z << "\tDistance:\t" << distance <<endl; - - } + if (lens_type == 2){ + p[5] = 0; // k + }else{ + m = 5; + } + + // Set up measurement vector + int n = lines[l].size(); + double * x = new double[n]; + for (unsigned int i = 0; i < n; i++){ + x[i] = 0; + } + + int ret = dlevmar_dif(&Mapto3d, &visf, p, x, m, n, iterations, opts, info, NULL, NULL, NULL); + + cout << "Line " << l+1 << " parameters-----" << endl; + cout << "Focal length:\t" << p[0] << endl; + cout << "x center:\t" << p[1] << endl; + cout << "y center\t" << p[2] << endl; + cout << "p2:\t\t" << p[3] << endl; + cout << "p4:\t\t" << p[4] << endl; + if (lens_type == 2){ + cout << "k:\t\t" << p[5] << endl; + } cout << endl; - + + delete [] p; + delete [] x; } } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.h 2009-07-13 23:04:18 UTC (rev 4041) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.h 2009-07-15 17:34:59 UTC (rev 4042) @@ -1,6 +1,6 @@ #ifndef MAPPOINTS_H #define MAPPOINTS_H -void map_points(int, int); +void map_points(); #endif Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-13 23:04:18 UTC (rev 4041) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-15 17:34:59 UTC (rev 4042) @@ -695,6 +695,9 @@ int nw = info.width(), nh = info.height(); + original_width = info.width(); + original_height = info.height(); + if (nw > nh){ min_line_length_squared = (length_threshold*nw)*(length_threshold*nw); }else{ @@ -785,6 +788,6 @@ exportImage(srcImageRange(cornerness), ImageExportInfo(output.c_str()).setPixelType("UINT8")); detect_edge(grey, cornerness, edgeness, filename, path, format); - map_points(nw, nh); + map_points(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-16 16:14:58
|
Revision: 4045 http://hugin.svn.sourceforge.net/hugin/?rev=4045&view=rev Author: blimbo Date: 2009-07-16 16:14:54 +0000 (Thu, 16 Jul 2009) Log Message: ----------- Options to optimise projection centre Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-16 12:38:29 UTC (rev 4044) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-16 16:14:54 UTC (rev 4045) @@ -18,6 +18,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include <map> #include "Globals.h" #include <string> #include <vector> @@ -26,7 +27,8 @@ unsigned int resize_dimension = 800; unsigned int detector = 0; unsigned int lens_type = 1; -unsigned int current_line = 0;; +unsigned int current_line = 0; +unsigned int optimise_centre = 0; double original_width = 0; double original_height = 0;; double focal_length = 15; @@ -50,3 +52,4 @@ std::vector<std::vector<vigra::Point2D> > lines; double sigma = 1.4; double r = 140; +std::map<int,double> line_errors; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-16 12:38:29 UTC (rev 4044) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-16 16:14:54 UTC (rev 4045) @@ -1,6 +1,7 @@ #ifndef GLOBALS_H #define GLOBALS_H +#include <map> #include <string> #include <vector> #include "vigra/diff2d.hxx" @@ -10,6 +11,7 @@ extern unsigned int detector; extern unsigned int lens_type; extern unsigned int current_line; +extern unsigned int optimise_centre; extern double original_width; extern double original_height; extern double focal_length; @@ -33,5 +35,6 @@ extern std::vector<std::vector<vigra::Point2D> > lines; extern double sigma; extern double r; +extern std::map<int,double> line_errors; #endif Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-16 12:38:29 UTC (rev 4044) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-16 16:14:54 UTC (rev 4045) @@ -301,8 +301,8 @@ cout << " -d <int> Maximum dimension for re-sized image prior to processing. Default 800." << endl; cout << " -f <string> Output file format. Default .JPG" << endl; cout << " -o <path> Output path. Default output/" << endl; - cout << " -s <float> Edge detector scale. Default 2" << endl; - cout << " -t <float> Edge detector threshold. Default 8" << endl; + //cout << " -s <float> Edge detector scale. Default 2" << endl; + //cout << " -t <float> Edge detector threshold. Default 8" << endl; //cout << " -b <float> Boundary tensor scale. Default 1.45" << endl; cout << " -g <int> Gap in pixels permitted within a line. Default 4" << endl; cout << " -l <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; @@ -314,6 +314,7 @@ cout << " 2 = Equal-area fisheye" << endl; cout << " 3 = Equal-angle fisheye" << endl; //cout << " -i <0|1> Generate intermediate images. Default 1" << endl; + cout << " -t <0|1> Optimise image centre. Default 0" << endl; cout << " -v <0|1> Verbose. Default 0" << endl; cout << " -h Print usage." << endl; cout << endl; @@ -350,12 +351,13 @@ case 'f' : {format = argv[i]; break;} case 'e' : {detector = atoi(argv[i]); break;} case 'g' : {gap_limit = atoi(argv[i]); break;} + case 't' : {optimise_centre = atoi(argv[i]); break;} case 'v' : {verbose = atoi(argv[i]); break;} case 'd' : {resize_dimension = atoi(argv[i]); break;} case 's' : {scale = atof(argv[i]); break;} case 'b' : {tscale = atof(argv[i]); break;} case 'a' : {a = atof(argv[i]); break;} - case 't' : {threshold = atof(argv[i]); break;} + //case 't' : {threshold = atof(argv[i]); break;} case 'y' : {corner_threshold = atof(argv[i]); break;} case 'l' : {length_threshold = atof(argv[i]); break;} case 'i' : {pixel_density = atof(argv[i]); break;} Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-16 12:38:29 UTC (rev 4044) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-16 16:14:54 UTC (rev 4045) @@ -18,6 +18,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include <map> #include <iostream> #include <stdio.h> #include <math.h> @@ -50,6 +51,7 @@ void Mapto3d (double *p, double *x, int m, int n, void *data){ + /* cout << "Line " << current_line+1 << " current parameters-----" << endl; cout << "Focal length:\t" << p[0] << endl; cout << "x center:\t" << p[1] << endl; @@ -60,6 +62,22 @@ cout << "k:\t\t" << p[5] << endl; } cout << endl; + */ + + + double x_centre = 0; + double y_centre = 0; + if (lens_type == 2){ + if(optimise_centre){ + x_centre = p[4]; + y_centre = p[5]; + } + }else{ + if(optimise_centre){ + x_centre = p[3]; + y_centre = p[4]; + } + } XYZPoint mapped_point[n]; @@ -80,7 +98,7 @@ //cout << "(x,y)\t(" << x_point << "," << y_point << ")" << endl; // r - distance of a point from the center of projection, in pixels - double r = PointPointDist(x_point,y_point,p[1],p[2]); + double r = PointPointDist(x_point,y_point,x_centre,y_centre); // u = r / f; double u = r / p[0]; @@ -88,10 +106,12 @@ // R - distance of a point from the center of projection, corrected for barrel distortion, unitless, or radians // (1 - p2 - p4) is for normalisation // p2 = p[3], p4 = [4] - double R = (1 - p[3] - p[4]) * u + p[3] * (u*u) + p[4] * (u*u*u*u); + double R = (1 - p[1] - p[2]) * u + p[1] * (u*u) + p[2] * (u*u*u*u); // Convert R to radians + //cout << "R in degrees:\t" << R << endl; R = R * (M_PI/180); + //cout << "R in radians:\t" << R << endl; // a - angular distance of a point from the center of projection, in radians double a; @@ -99,7 +119,7 @@ if (lens_type == 2){ // k - equal-area type fisheye design parameter, initial value of 2 - double k = p[5]; + double k = p[3]; a = k * asin( R / k ); }else if (lens_type == 3){ @@ -111,8 +131,10 @@ } // Convert a to radians - a = a * (M_PI/180); - + //cout << "a in degrees:\t" << a << endl; + //a = a * (M_PI/180); + //cout << "a in radians:\t" << a << endl; + double z = cos(a); double s = sqrt((1 - z * z) / ( x_point * x_point + y_point * y_point )); @@ -125,17 +147,19 @@ mapped_point[i] = Point; - cout << current_line+1 << "\t" << i << "\t(" << Point.x << "," << Point.y << "," << Point.z << ")" << endl; + //cout << current_line+1 << "\t" << i << "\t(" << Point.x << "," << Point.y << "," << Point.z << ")" << endl; } // Vector cross product of the end points - this is the normal to the estimated plane XYZPoint norm = CrossProduct(mapped_point[0],mapped_point[n-1]); + /* cout << endl << "Cross product of end points:" << endl; cout << norm.x << endl; cout << norm.y << endl; cout << norm.z << endl << endl; + */ // Comput straigthness error double ssq = 0; @@ -149,18 +173,15 @@ x[i] = sqrt((n - 2) * ssq ); //cout << "x[i]" << x[i] << endl; } - //cout << "ssq\t:\t" << ssq << endl << endl; - x[0] = 0; - x[n-1] = 0; - cout << "Total error for line " << current_line+1 << " :\t" << x[1] << endl << endl; + + //cout << "Total error for line " << current_line+1 << " :\t" << x[1] << endl << endl; + line_errors[current_line] = x[1]; } int visf (double *p, double *hx, int m, int n, int iter, double p_eL2, void *adata){ - - // What goes here?? - + return(1); } void map_points(){ @@ -172,7 +193,6 @@ cout << "Focal length (pixels):\t" << focal_length << endl << endl; int iterations = 1000; - double opts[5]; double info[LM_INFO_SZ]; for (unsigned int l = 0; l < lines.size(); l++){ @@ -184,15 +204,25 @@ double * p = new double[m]; p[0] = focal_length; - p[1] = 0; // x_center; - p[2] = 0; // y_center; - p[3] = 0; // p2 - p[4] = 0; // p4 + p[1] = 0; // p2 + p[2] = 0; // p4 if (lens_type == 2){ - p[5] = 2; // k + p[3] = 2; // k + if(optimise_centre){ + p[4] = 0; // x_center; + p[5] = 0; // y_center; + }else{ + m = 4; + } }else{ - m = 5; + if(optimise_centre){ + m = 5; + p[3] = 0; // x_center; + p[4] = 0; // y_center; + }else{ + m = 3; + } } // Set up measurement vector @@ -202,19 +232,36 @@ x[i] = 0; } - int ret = dlevmar_dif(&Mapto3d, &visf, p, x, m, n, iterations, opts, info, NULL, NULL, NULL); + int ret = dlevmar_dif(&Mapto3d, &visf, p, x, m, n, iterations, NULL, info, NULL, NULL, NULL); - cout << "Line " << l+1 << " final parameters-----" << endl; + printf("Levenberg-Marquardt returned in %g iter, reason %g\nLine %d solution:\n", info[5], info[6],l+1); cout << "Focal length:\t" << p[0] << endl; - cout << "x center:\t" << p[1] << endl; - cout << "y center\t" << p[2] << endl; - cout << "p2:\t\t" << p[3] << endl; - cout << "p4:\t\t" << p[4] << endl; - if (lens_type == 2){ - cout << "k:\t\t" << p[5] << endl; + cout << "p2:\t\t" << p[1] << endl; + cout << "p4:\t\t" << p[2] << endl; + + if (lens_type == 2){ + cout << "k:\t\t" << p[3] << endl; + if(optimise_centre){ + cout << "x centre:\t" << p[4] << endl; + cout << "y centre\t" << p[5] << endl; + } + }else{ + if(optimise_centre){ + cout << "x centre:\t" << p[3] << endl; + cout << "y centre\t" << p[4] << endl; + } + } + cout << "Error:\t\t" << line_errors[current_line] << endl; + cout << endl; + + /* + // Print info + for (int i = 0; i <=7; i++){ + cout << "info " << i << ":\t" << info[i] << endl; } cout << endl; - + */ + delete [] p; delete [] x; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-16 22:21:40
|
Revision: 4046 http://hugin.svn.sourceforge.net/hugin/?rev=4046&view=rev Author: blimbo Date: 2009-07-16 22:21:34 +0000 (Thu, 16 Jul 2009) Log Message: ----------- Optimises all lines together Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-16 16:14:54 UTC (rev 4045) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-16 22:21:34 UTC (rev 4046) @@ -31,7 +31,7 @@ unsigned int optimise_centre = 0; double original_width = 0; double original_height = 0;; -double focal_length = 15; +double focal_length = 10; double pixel_density = 300; std::string path = ("output/"); //std::string path = (""); Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-16 16:14:54 UTC (rev 4045) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-16 22:21:34 UTC (rev 4046) @@ -309,7 +309,7 @@ //cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; //cout << " -y <float> Corner threshold. Default 200" << endl; cout << " -i <float> Pixel density in pixels/inch. Default 300" << endl; - cout << " -q <float> Focal length. Default 15" << endl; + cout << " -q <float> Focal length. Default 10" << endl; cout << " -k <int> Lens type. 1 = Rectilinear (default)" << endl; cout << " 2 = Equal-area fisheye" << endl; cout << " 3 = Equal-angle fisheye" << endl; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-16 16:14:54 UTC (rev 4045) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-16 22:21:34 UTC (rev 4046) @@ -51,20 +51,9 @@ void Mapto3d (double *p, double *x, int m, int n, void *data){ - /* - cout << "Line " << current_line+1 << " current parameters-----" << endl; - cout << "Focal length:\t" << p[0] << endl; - cout << "x center:\t" << p[1] << endl; - cout << "y center\t" << p[2] << endl; - cout << "p2:\t\t" << p[3] << endl; - cout << "p4:\t\t" << p[4] << endl; - if (lens_type == 2){ - cout << "k:\t\t" << p[5] << endl; - } - cout << endl; - */ + // Re-scale pixles + double invert_size_factor = 1.0/sizefactor; - double x_centre = 0; double y_centre = 0; if (lens_type == 2){ @@ -78,106 +67,112 @@ y_centre = p[4]; } } + + for (unsigned int l = 0; l < lines.size(); l++){ - XYZPoint mapped_point[n]; + //cout << "Optimising line " << l+1 << "..." << endl; + + XYZPoint mapped_point[lines[current_line].size()]; - // Re-scale pixles - double invert_size_factor = 1.0/sizefactor; + // Map points to 3D and fill the above array with XYZPoints + for(unsigned int i = 0; i < lines[current_line].size(); i++){ - // Map points to 3D and fill the above array with XYZPoints - for(unsigned int i = 0; i < n; i++){ + double x_point = invert_size_factor * lines[l][i]->x; + double y_point = invert_size_factor * lines[l][i]->y; - double x_point = invert_size_factor * lines[current_line][i]->x; - double y_point = invert_size_factor * lines[current_line][i]->y; - - // Move coordinates so 0,0 is in the centre of the image - x_point += original_width/2; - y_point *= -1; - y_point += original_height/2; + // Move coordinates so 0,0 is in the centre of the image + x_point += original_width/2; + y_point *= -1; + y_point += original_height/2; - //cout << "(x,y)\t(" << x_point << "," << y_point << ")" << endl; - - // r - distance of a point from the center of projection, in pixels - double r = PointPointDist(x_point,y_point,x_centre,y_centre); + //cout << "(x,y)\t(" << x_point << "," << y_point << ")" << endl; - // u = r / f; - double u = r / p[0]; + // Replace with distances from centre + x_point = x_point - x_centre; + y_point = y_point - y_centre; - // R - distance of a point from the center of projection, corrected for barrel distortion, unitless, or radians - // (1 - p2 - p4) is for normalisation - // p2 = p[3], p4 = [4] - double R = (1 - p[1] - p[2]) * u + p[1] * (u*u) + p[2] * (u*u*u*u); + //cout << "(x,y)\t(" << x_point << "," << y_point << ")" << endl; + + // r - distance of a point from the center of projection, in pixels + double r = PointPointDist(x_point,y_point,x_centre,y_centre); - // Convert R to radians - //cout << "R in degrees:\t" << R << endl; - R = R * (M_PI/180); - //cout << "R in radians:\t" << R << endl; - - // a - angular distance of a point from the center of projection, in radians - double a; - - if (lens_type == 2){ + // u = r / f; + double u = r / p[0]; - // k - equal-area type fisheye design parameter, initial value of 2 - double k = p[3]; - a = k * asin( R / k ); + // R - distance of a point from the center of projection, + // corrected for barrel distortion, unitless, or radians + // (1 - p2 - p4) is for normalisation + // p2 = p[3], p4 = [4] + double R = (1 - p[1] - p[2]) * u + p[1] * (u*u) + p[2] * (u*u*u*u); - }else if (lens_type == 3){ - // Equal-angle fisheye - a = R; // for a true equal-angle fisheye. - }else{ - // Rectilinear lens - a = atan( R ); - } + // a - angular distance of a point from the center of projection, in radians + double a; - // Convert a to radians - //cout << "a in degrees:\t" << a << endl; - //a = a * (M_PI/180); - //cout << "a in radians:\t" << a << endl; + if (lens_type == 2){ + // k - equal-area type fisheye design parameter, initial value of 2 + double k = p[3]; + a = k * asin( R / k ); + + cout << "k:\t" << p[3] << endl; + cout << "r/k:\t" << R/k << endl; + cout << "asin(r/k):\t" << asin( R / k ) << endl; + cout << "a:\t" << a << endl; + + }else if (lens_type == 3){ + // Equal-angle fisheye + a = R; // for a true equal-angle fisheye. + }else{ + // Rectilinear lens + a = atan( R ); + } - double z = cos(a); + double z = cos(a); + double s = sqrt((1 - z * z) / ( x_point * x_point + y_point * y_point )); - double s = sqrt((1 - z * z) / ( x_point * x_point + y_point * y_point )); + XYZPoint Point; - XYZPoint Point; + Point.x = -s * x_point; + Point.y = s * y_point; + Point.z = z; - Point.x = -s * x_point; - Point.y = s * y_point; - Point.z = z; - - mapped_point[i] = Point; - - //cout << current_line+1 << "\t" << i << "\t(" << Point.x << "," << Point.y << "," << Point.z << ")" << endl; + mapped_point[i] = Point; + + /* + cout << "r:\t" << r << endl; + cout << "u:\t" << u << endl; + cout << "R:\t" << R << endl; + cout << "a:\t" << a << endl; + cout << "z:\t" << z << endl; + cout << "s:\t" << s << endl; + double check = (Point.x*Point.x + Point.y*Point.y + Point.z*Point.z); + cout << "Unit vector?\t" << check << endl; + cout << l+1 << "\t" << i << "\t(" << Point.x << "," << Point.y << "," << Point.z << ")" << endl; + */ - } + } - // Vector cross product of the end points - this is the normal to the estimated plane - XYZPoint norm = CrossProduct(mapped_point[0],mapped_point[n-1]); - - /* - cout << endl << "Cross product of end points:" << endl; - cout << norm.x << endl; - cout << norm.y << endl; - cout << norm.z << endl << endl; - */ + // Vector cross product of the end points - this is the normal to the estimated plane + XYZPoint norm = CrossProduct(mapped_point[0],mapped_point[n-1]); - // Comput straigthness error - double ssq = 0; - for(unsigned int i = 1; i < n - 1; i++){ - // Add square of dot product of that point with norm - ssq += sqrt(abs(DotProduct(norm,mapped_point[i]))); - //cout << i << " error:\t" << sqrt(abs(DotProduct(norm,mapped_point[i]))) << "\t(" << ssq << ")" << endl; + /* + cout << endl << "Cross product of end points:" << endl; + cout << norm.x << endl; + cout << norm.y << endl; + cout << norm.z << endl << endl; + */ + + // Comput straigthness error + double ssq = 0; + for(unsigned int i = 1; i < n - 1; i++){ + // Add square of dot product of that point with norm + double d = DotProduct(norm,mapped_point[i]); + ssq += d * d; + } + // Add to optimizer's error vector + x[l] = sqrt((n - 2) * ssq ); + //cout << "Error:\t" << x[l] << endl; + line_errors[l] = x[l]; } - // Add to optimizer's error vector - for(unsigned int i = 1; i < n - 1; i++){ - x[i] = sqrt((n - 2) * ssq ); - //cout << "x[i]" << x[i] << endl; - } - - //cout << "Total error for line " << current_line+1 << " :\t" << x[1] << endl << endl; - - line_errors[current_line] = x[1]; - } int visf (double *p, double *hx, int m, int n, int iter, double p_eL2, void *adata){ @@ -186,6 +181,10 @@ void map_points(){ + + if(lens_type == 1) cout << "Rectilinear lens" << endl; + if(lens_type == 2) cout << "Equal-area fisheye lens" << endl; + if(lens_type == 3) cout << "Equal-angle fisheye lens" << endl; cout << "Focal length (mm):\t" << focal_length << endl; // Convert focal length to pixels // 1 mm = 0.0393700787402 inches @@ -195,74 +194,71 @@ int iterations = 1000; double info[LM_INFO_SZ]; - for (unsigned int l = 0; l < lines.size(); l++){ - - current_line = l; - - // Set up initial parameters - int m = 6; - double * p = new double[m]; + // Set up initial parameters + int m = 6; + double * p = new double[m]; - p[0] = focal_length; - p[1] = 0; // p2 - p[2] = 0; // p4 + p[0] = focal_length; + p[1] = 0; // p2 + p[2] = 0; // p4 - if (lens_type == 2){ - p[3] = 2; // k - if(optimise_centre){ - p[4] = 0; // x_center; - p[5] = 0; // y_center; - }else{ - m = 4; - } + if (lens_type == 2){ + p[3] = 2; // k + if(optimise_centre){ + p[4] = 0; // x_center; + p[5] = 0; // y_center; }else{ - if(optimise_centre){ - m = 5; - p[3] = 0; // x_center; - p[4] = 0; // y_center; - }else{ - m = 3; - } - } - - // Set up measurement vector - int n = lines[l].size(); - double * x = new double[n]; - for (unsigned int i = 0; i < n; i++){ - x[i] = 0; + m = 4; + } + }else{ + if(optimise_centre){ + m = 5; + p[3] = 0; // x_center; + p[4] = 0; // y_center; + }else{ + m = 3; } + } - int ret = dlevmar_dif(&Mapto3d, &visf, p, x, m, n, iterations, NULL, info, NULL, NULL, NULL); + // Set up measurement vector + int n = lines.size(); + double * x = new double[n]; + for (unsigned int i = 0; i < n; i++){ + x[i] = 0; + } - printf("Levenberg-Marquardt returned in %g iter, reason %g\nLine %d solution:\n", info[5], info[6],l+1); - cout << "Focal length:\t" << p[0] << endl; - cout << "p2:\t\t" << p[1] << endl; - cout << "p4:\t\t" << p[2] << endl; + int ret = dlevmar_dif(&Mapto3d, &visf, p, x, m, n, iterations, NULL, info, NULL, NULL, NULL); - if (lens_type == 2){ - cout << "k:\t\t" << p[3] << endl; - if(optimise_centre){ - cout << "x centre:\t" << p[4] << endl; - cout << "y centre\t" << p[5] << endl; - } - }else{ - if(optimise_centre){ - cout << "x centre:\t" << p[3] << endl; - cout << "y centre\t" << p[4] << endl; - } + printf("\nLevenberg-Marquardt returned in %g iter, reason %g\nSolution:\n", info[5], info[6]); + cout << "Focal length:\t\t" << p[0] << endl; + cout << "p2:\t\t\t" << p[1] << endl; + cout << "p4:\t\t\t" << p[2] << endl; + + if (lens_type == 2){ + cout << "k:\t\t\t" << p[3] << endl; + if(optimise_centre){ + cout << "x centre:\t\t" << p[4] << endl; + cout << "y centre\t\t" << p[5] << endl; } - cout << "Error:\t\t" << line_errors[current_line] << endl; - cout << endl; - - /* - // Print info - for (int i = 0; i <=7; i++){ - cout << "info " << i << ":\t" << info[i] << endl; + }else{ + if(optimise_centre){ + cout << "x centre:\t\t" << p[3] << endl; + cout << "y centre\t\t" << p[4] << endl; } - cout << endl; - */ + } + for (unsigned int i = 0; i < n; i++){ + cout << "Line " << i+1 << " error:\t\t" << line_errors[i] << endl; + } + + /* + // Print info + for (int i = 0; i <=7; i++){ + cout << "info " << i << ":\t" << info[i] << endl; + } + cout << endl; + */ - delete [] p; - delete [] x; - } + delete [] p; + delete [] x; + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-17 14:41:35
|
Revision: 4051 http://hugin.svn.sourceforge.net/hugin/?rev=4051&view=rev Author: blimbo Date: 2009-07-17 14:41:32 +0000 (Fri, 17 Jul 2009) Log Message: ----------- Applied patch fixes, added some jhead/exiv reading stuff Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-17 13:24:12 UTC (rev 4050) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-17 14:41:32 UTC (rev 4051) @@ -29,10 +29,12 @@ unsigned int lens_type = 1; unsigned int current_line = 0; unsigned int optimise_centre = 0; +double sensor_width = 0; +double sensor_height = 0; double original_width = 0; double original_height = 0;; -double focal_length = 10; -double pixel_density = 300; +double focal_length = 0; +double pixel_density = 4000; std::string path = ("output/"); //std::string path = (""); std::string format = (".jpg"); Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-17 13:24:12 UTC (rev 4050) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-17 14:41:32 UTC (rev 4051) @@ -12,6 +12,8 @@ extern unsigned int lens_type; extern unsigned int current_line; extern unsigned int optimise_centre; +extern double sensor_width; +extern double sensor_height; extern double original_width; extern double original_height; extern double focal_length; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-17 13:24:12 UTC (rev 4050) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-17 14:41:32 UTC (rev 4051) @@ -308,7 +308,7 @@ cout << " -l <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; //cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; //cout << " -y <float> Corner threshold. Default 200" << endl; - cout << " -i <float> Pixel density in pixels/inch. Default 300" << endl; + cout << " -i <float> Pixel density in pixels/inch. Default 4000" << endl; cout << " -q <float> Focal length. Default 10" << endl; cout << " -k <int> Lens type. 1 = Rectilinear (default)" << endl; cout << " 2 = Equal-area fisheye" << endl; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-17 13:24:12 UTC (rev 4050) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-17 14:41:32 UTC (rev 4051) @@ -72,18 +72,21 @@ //cout << "Optimising line " << l+1 << "..." << endl; - XYZPoint mapped_point[lines[current_line].size()]; + //XYZPoint mapped_point[lines[current_line].size()]; + XYZPoint * mapped_point = new XYZPoint[lines[l].size()]; // Map points to 3D and fill the above array with XYZPoints - for(unsigned int i = 0; i < lines[current_line].size(); i++){ + for(unsigned int i = 0; i < lines[l].size(); i++){ double x_point = invert_size_factor * lines[l][i]->x; double y_point = invert_size_factor * lines[l][i]->y; // Move coordinates so 0,0 is in the centre of the image - x_point += original_width/2; - y_point *= -1; - y_point += original_height/2; + x_point -= original_width/2; + y_point -= original_height/2; + y_point *= -1; + + //cout << "(x,y)\t(" << x_point << "," << y_point << ")" << endl; @@ -94,7 +97,8 @@ //cout << "(x,y)\t(" << x_point << "," << y_point << ")" << endl; // r - distance of a point from the center of projection, in pixels - double r = PointPointDist(x_point,y_point,x_centre,y_centre); + //double r = PointPointDist(x_point,y_point,x_centre,y_centre); + double r = sqrt(x_point * x_point + y_point * y_point); // u = r / f; double u = r / p[0]; @@ -112,12 +116,12 @@ // k - equal-area type fisheye design parameter, initial value of 2 double k = p[3]; a = k * asin( R / k ); - + /* cout << "k:\t" << p[3] << endl; cout << "r/k:\t" << R/k << endl; cout << "asin(r/k):\t" << asin( R / k ) << endl; cout << "a:\t" << a << endl; - + */ }else if (lens_type == 3){ // Equal-angle fisheye a = R; // for a true equal-angle fisheye. @@ -172,6 +176,8 @@ x[l] = sqrt((n - 2) * ssq ); //cout << "Error:\t" << x[l] << endl; line_errors[l] = x[l]; + + delete [] mapped_point; } } @@ -181,7 +187,6 @@ void map_points(){ - if(lens_type == 1) cout << "Rectilinear lens" << endl; if(lens_type == 2) cout << "Equal-area fisheye lens" << endl; if(lens_type == 3) cout << "Equal-angle fisheye lens" << endl; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-17 13:24:12 UTC (rev 4050) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-17 14:41:32 UTC (rev 4051) @@ -18,6 +18,16 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#define HUGIN_USE_EXIV2 + +#include <jhead/jhead.h> + +#ifdef HUGIN_USE_EXIV2 +#include <exiv2/exif.hpp> +#include <exiv2/image.hpp> +#endif + + #include "vigra/impex.hxx" #include "vigra/stdimage.hxx" #include "vigra/edgedetection.hxx" @@ -27,19 +37,17 @@ #include <vigra/orientedtensorfilters.hxx> #include "vigra/diff2d.hxx" #include <vigra/rgbvalue.hxx> +#include <vigra/utilities.hxx> #include "Globals.h" #include "ProcessImage.h" #include "MapPoints.h" +#include <ANN/ANN.h> -//#include "Ransac.h" -//#include "SplineEstimator.h" -//#include "LineParamEstimator.h" -//#include "PolynomialEstimator.h" -#include <ANN/ANN.h> #if _MSC_VER //def _WIN32 #include <time.h> #endif +//using namespace hugin_utils; using namespace vigra; using namespace std; @@ -391,7 +399,7 @@ // Stop when only 35% of coordinates are left unsigned int good_lines = 0; //while (good_lines < 10 && coords.size() && 100*((double)coords.size()/intital_coords_size) >= 25){ - while (good_lines < 10 && coords.size()){ + while (good_lines < 10 && coords.size() > 1){ if(verbose) cout << "Searching for line " << good_lines+1 << ":" << endl; if(verbose) cout << "=====================" << endl << endl; @@ -685,6 +693,343 @@ } } +#ifdef HUGIN_USE_EXIV2 +// Convenience functions to work with Exiv2 +bool getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, long & value) +{ + Exiv2::ExifKey key(keyName); + Exiv2::ExifData::iterator itr = exifData.findKey(key); + if (itr != exifData.end()) { + value = itr->toLong(); + //DEBUG_DEBUG("" << keyName << ": " << value); + return true; + } else { + return false; + } +} + + +bool getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, float & value) +{ + Exiv2::ExifKey key(keyName); + Exiv2::ExifData::iterator itr = exifData.findKey(key); + if (itr != exifData.end()) { + value = itr->toFloat(); + //DEBUG_DEBUG("" << keyName << ": " << value); + return true; + } else { + return false; + } +} +#endif // HUGIN_USE_EXIV2 + +bool get_exif_data(string& filename){ + + + + cout << "Using jhead..." << endl; + + // Read exif data + + + ImageInfo_t exif; + ResetJpgfile(); + // Start with an empty image information structure. + + memset(&exif, 0, sizeof(exif)); + + if (!ReadJpegFile(exif,filename.c_str(), READ_EXIF)){ + puts("Exif read failed"); + }else{ + if (focal_length == 0) { + focal_length = exif.FocalLength; + cout << "Found focal length:\t" << focal_length << endl; + } + if (sensor_width == 0){ + sensor_width = exif.CCDWidth; + cout << "Found sensor width:\t" << sensor_width << endl; + } + if (sensor_height == 0){ + sensor_height = exif.CCDHeight; + cout << "Found sensor height:\t" << sensor_height << endl; + } + } + cout << endl; + + + #ifdef HUGIN_USE_EXIV2 + + typedef struct { + double x, y; + } sensor; + + cout << "Scanning EXIF data..." << endl; + + double width = original_width; + double height = original_height; + double cropFactor,focalLength; + + Exiv2::Image::AutoPtr image; + try { + image = Exiv2::ImageFactory::open(filename.c_str()); + }catch(...) { + std::cout << __FILE__ << " " << __LINE__ << " Error opening file" << std::endl; + return false; + } + if (image.get() == 0) { + std::cout << "Unable to open file to read EXIF data: " << filename << std::endl; + return false; + } + + image->readMetadata(); + Exiv2::ExifData &exifData = image->exifData(); + if (exifData.empty()) { + std::cout << "Unable to read EXIF data from opened file:" << filename << std::endl; + return false; + } + + + /* + //getExiv2Value(exifData,"Exif.Photo.ExposureTime",exposureTime); + // TODO: reconstruct real exposure value from "rounded" ones saved by the cameras? + + getExiv2Value(exifData,"Exif.Photo.FNumber",photoFNumber); + + if (exposureTime > 0 && photoFNumber > 0) { + double gain = 1; + if (getExiv2Value(exifData,"Exif.Photo.ISOSpeedRatings",isoSpeed)) { + if (isoSpeed > 0) { + gain = isoSpeed / 100.0; + } + } + eV = log2(photoFNumber * photoFNumber / (gain * exposureTime)); + DEBUG_DEBUG ("Ev: " << eV); + } + + + Exiv2::ExifKey key("Exif.Image.Make"); + Exiv2::ExifData::iterator itr = exifData.findKey(key); + if (itr != exifData.end()) + setExifMake(itr->toString()); + else + setExifMake("Unknown"); + + Exiv2::ExifKey key2("Exif.Image.Model"); + itr = exifData.findKey(key2); + if (itr != exifData.end()) + setExifModel(itr->toString()); + else + setExifModel("Unknown"); + + long orientation = 0; + if (getExiv2Value(exifData,"Exif.Image.Orientation",orientation)) { + switch (orientation) { + case 3: // rotate 180 + roll = 180; + break; + case 6: // rotate 90 + roll = 90; + break; + case 8: // rotate 270 + roll = 270; + break; + default: + break; + } + } + + long pixXdim = 0; + getExiv2Value(exifData,"Exif.Photo.PixelXDimension",pixXdim); + + long pixYdim = 0; + getExiv2Value(exifData,"Exif.Photo.PixelYDimension",pixYdim); + + if (pixXdim !=0 && pixYdim !=0 ) { + double ratioExif = pixXdim/(double)pixYdim; + double ratioImage = width/(double)height; + if (fabs( ratioExif - ratioImage) > 0.1) { + // Image has been modified without adjusting exif tags. + // Assume user has rotated to upright pose + roll = 0; + } + } + + */ + + //GWP - CCD info was previously computed by the jhead library. Migration + // to exiv2 means we do it here + + // some cameras do not provide Exif.Image.ImageWidth / Length + // notably some Olympus + + long eWidth = 0; + getExiv2Value(exifData,"Exif.Image.ImageWidth",eWidth); + + long eLength = 0; + getExiv2Value(exifData,"Exif.Image.ImageLength",eLength); + + double sensorPixelWidth = 0; + double sensorPixelHeight = 0; + if (eWidth > 0 && eLength > 0) { + sensorPixelHeight = (double)eLength; + sensorPixelWidth = (double)eWidth; + } else { + // No EXIF information, use number of pixels in image + sensorPixelWidth = width; + sensorPixelHeight = height; + } + + // force landscape sensor orientation + if (sensorPixelWidth < sensorPixelHeight ) { + double t = sensorPixelWidth; + sensorPixelWidth = sensorPixelHeight; + sensorPixelHeight = t; + } + + //DEBUG_DEBUG("sensorPixelWidth: " << sensorPixelWidth); + //DEBUG_DEBUG("sensorPixelHeight: " << sensorPixelHeight); + + // some cameras do not provide Exif.Photo.FocalPlaneResolutionUnit + // notably some Olympus + + long exifResolutionUnits = 0; + getExiv2Value(exifData,"Exif.Photo.FocalPlaneResolutionUnit",exifResolutionUnits); + + float resolutionUnits= 0; + switch (exifResolutionUnits) { + case 3: resolutionUnits = 10.0; break; //centimeter + case 4: resolutionUnits = 1.0; break; //millimeter + case 5: resolutionUnits = .001; break; //micrometer + default: resolutionUnits = 25.4; break; //inches + } + + //DEBUG_DEBUG("Resolution Units: " << resolutionUnits); + + // some cameras do not provide Exif.Photo.FocalPlaneXResolution and + // Exif.Photo.FocalPlaneYResolution, notably some Olympus + + float fplaneXresolution = 0; + getExiv2Value(exifData,"Exif.Photo.FocalPlaneXResolution",fplaneXresolution); + + float fplaneYresolution = 0; + getExiv2Value(exifData,"Exif.Photo.FocalPlaneYResolution",fplaneYresolution); + + float CCDWidth = 0; + if (fplaneXresolution != 0) { +// CCDWidth = (float)(sensorPixelWidth * resolutionUnits / +// fplaneXresolution); + CCDWidth = (float)(sensorPixelWidth / ( fplaneXresolution / resolutionUnits)); + } + + float CCDHeight = 0; + if (fplaneYresolution != 0) { + CCDHeight = (float)(sensorPixelHeight / ( fplaneYresolution / resolutionUnits)); + } + + //DEBUG_DEBUG("CCDHeight:" << CCDHeight); + //DEBUG_DEBUG("CCDWidth: " << CCDWidth); + + // calc sensor dimensions if not set and 35mm focal length is available + sensor sensorSize; + + if (CCDHeight > 0 && CCDWidth > 0) { + // read sensor size directly. + sensorSize.x = CCDWidth; + sensorSize.y = CCDHeight; + if (exif.CameraModel == "Canon EOS 20D") { + // special case for buggy 20D camera + sensorSize.x = 22.5; + sensorSize.y = 15; + } + // + // check if sensor size ratio and image size fit together + double rsensor = (double)sensorSize.x / sensorSize.y; + double rimg = (double) width / height; + if ( (rsensor > 1 && rimg < 1) || (rsensor < 1 && rimg > 1) ) { + // image and sensor ratio do not match + // swap sensor sizes + float t; + t = sensorSize.y; + sensorSize.y = sensorSize.x; + sensorSize.x = t; + } + + //DEBUG_DEBUG("sensorSize.y: " << sensorSize.y); + //DEBUG_DEBUG("sensorSize.x: " << sensorSize.x); + + cropFactor = sqrt(36.0*36.0+24.0*24.0) / + sqrt(sensorSize.x*sensorSize.x + sensorSize.y*sensorSize.y); + // FIXME: HACK guard against invalid image focal plane definition in EXIF metadata with arbitrarly chosen limits for the crop factor ( 1/100 < crop < 100) + if (cropFactor < 0.01 || cropFactor > 100) { + cropFactor = 0; + } + }else{ + // alternative way to calculate the crop factor for Olympus cameras + + // Windows debug stuff + // left in as example on how to get "console output" + // written to a log file + // freopen ("oly.log","a",stdout); + // fprintf (stdout,"Starting Alternative crop determination\n"); + + float olyFPD = 0; + getExiv2Value(exifData,"Exif.Olympus.FocalPlaneDiagonal",olyFPD); + + if (olyFPD > 0.0) { + // Windows debug stuff + // fprintf(stdout,"Oly_FPD:"); + // fprintf(stdout,"%f",olyFPD); + cropFactor = sqrt(36.0*36.0+24.0*24.0) / olyFPD; + } + + } + //DEBUG_DEBUG("cropFactor: " << cropFactor); + + float eFocalLength = 0; + getExiv2Value(exifData,"Exif.Photo.FocalLength",eFocalLength); + + float eFocalLength35 = 0; + getExiv2Value(exifData,"Exif.Photo.FocalLengthIn35mmFilm",eFocalLength35); + + //The various methods to detmine crop factor + if (eFocalLength > 0 && cropFactor > 0) { + // user provided crop factor + focalLength = eFocalLength; + }else if (eFocalLength35 > 0 && eFocalLength > 0) { + cropFactor = eFocalLength35 / eFocalLength; + focalLength = eFocalLength; + }else if (eFocalLength35 > 0) { + // 35 mm equiv focal length available, crop factor unknown. + // do not ask for crop factor, assume 1. Probably a full frame sensor + cropFactor = 1; + focalLength = eFocalLength35; + }else if (eFocalLength > 0 && cropFactor <= 0) { + // need to redo, this time with crop + focalLength = eFocalLength; + cropFactor = 0; + } + + cout << "Width:\t\t" << width << endl; + cout << "Height:\t\t" << height << endl; + cout << "eWidth:\t\t" << eWidth << endl; + cout << "eHeight:\t" << eLength << endl; + cout << "Focal length:\t" << focalLength << endl; + cout << "Crop factor:\t" << cropFactor << endl; + cout << "sensorSize.x:\t" << sensorSize.x << endl; + cout << "sensorSize.y:\t" << sensorSize.y << endl; + cout << "CCDHeight:\t" << CCDHeight << endl; + cout << "CCDWidth:\t" << CCDWidth << endl; + cout << "sensorPixelWidth:\t" << sensorPixelWidth << CCDWidth << endl; + cout << "sensorPixelHeight:\t" << sensorPixelHeight << CCDWidth << endl; + cout << "Resolution Units:\t" << resolutionUnits << CCDWidth << endl << endl; + + +#endif + + return false; + +} + void process_image(string& filename){ ImageImportInfo info(filename.c_str()); @@ -697,6 +1042,8 @@ original_width = info.width(); original_height = info.height(); + + bool exif_ok = get_exif_data(filename); if (nw > nh){ min_line_length_squared = (length_threshold*nw)*(length_threshold*nw); @@ -788,6 +1135,7 @@ exportImage(srcImageRange(cornerness), ImageExportInfo(output.c_str()).setPixelType("UINT8")); detect_edge(grey, cornerness, edgeness, filename, path, format); + map_points(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-20 15:23:45
|
Revision: 4073 http://hugin.svn.sourceforge.net/hugin/?rev=4073&view=rev Author: blimbo Date: 2009-07-20 15:23:43 +0000 (Mon, 20 Jul 2009) Log Message: ----------- Now reads EXIF data properly Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-20 12:47:12 UTC (rev 4072) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-20 15:23:43 UTC (rev 4073) @@ -24,7 +24,7 @@ #include <vector> unsigned int verbose = 0; -unsigned int resize_dimension = 800; +unsigned int resize_dimension = 1600; unsigned int detector = 0; unsigned int lens_type = 1; unsigned int current_line = 0; @@ -35,6 +35,8 @@ double original_height = 0;; double focal_length = 0; double pixel_density = 4000; +double focal_length_pixels = 0; +double cropFactor = 0; std::string path = ("output/"); //std::string path = (""); std::string format = (".jpg"); Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-20 12:47:12 UTC (rev 4072) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-20 15:23:43 UTC (rev 4073) @@ -18,6 +18,8 @@ extern double original_height; extern double focal_length; extern double pixel_density; +extern double focal_length_pixels; +extern double cropFactor; extern std::string path; extern std::string format; extern double sizefactor; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-20 12:47:12 UTC (rev 4072) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-20 15:23:43 UTC (rev 4073) @@ -295,22 +295,24 @@ cout << endl << "Usage: calibrate_lens [options] image1 image2.." << endl << endl; cout << "Options:" << endl << endl; cout << " -p <filename> Input Hugin PTO file." << endl; - cout << " -n <int> Image in Hugin PTO file to process. Default 0" << endl; - cout << " -c <int> Control points to add to PTO file per line. Default 10." << endl; + cout << " -i <int> Image in Hugin PTO file to process. Default 0" << endl; + //cout << " -c <int> Control points to add to PTO file per line. Default 10." << endl; cout << " -e <0|1> Edge detector. 0 = Canny (default) 1 = Shen-Castan." << endl; - cout << " -d <int> Maximum dimension for re-sized image prior to processing. Default 800." << endl; - cout << " -f <string> Output file format. Default .JPG" << endl; + cout << " -d <int> Maximum dimension for re-sized image prior to processing. Default 1600." << endl; + //cout << " -f <string> Output file format. Default .JPG" << endl; cout << " -o <path> Output path. Default output/" << endl; //cout << " -s <float> Edge detector scale. Default 2" << endl; //cout << " -t <float> Edge detector threshold. Default 8" << endl; //cout << " -b <float> Boundary tensor scale. Default 1.45" << endl; cout << " -g <int> Gap in pixels permitted within a line. Default 4" << endl; - cout << " -l <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; + cout << " -m <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; //cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; //cout << " -y <float> Corner threshold. Default 200" << endl; - cout << " -i <float> Pixel density in pixels/inch. Default 4000" << endl; - cout << " -q <float> Focal length. Default 10" << endl; - cout << " -k <int> Lens type. 1 = Rectilinear (default)" << endl; + //cout << " -i <float> Pixel density in pixels/inch. Default 4000" << endl; + cout << " -f <float> Focal length (mm). Read from EXIF data." << endl; + cout << " -c <int> Crop factor. Read/calculated from EXIF data." << endl; + cout << " -s <float> Shortest dimension of sensor (mm), used to calculate crop factor." << endl; + cout << " -l <int> Lens type. 1 = Rectilinear (default)" << endl; cout << " 2 = Equal-area fisheye" << endl; cout << " 3 = Equal-angle fisheye" << endl; //cout << " -i <0|1> Generate intermediate images. Default 1" << endl; @@ -346,24 +348,26 @@ case 'h' : {usage();} case 'o' : {path = argv[i]; break;} case 'p' : {pto_file = argv[i]; break;} - case 'n' : {pto_image = atoi(argv[i]); break;} - case 'c' : {cps_per_line = atoi(argv[i]); break;} - case 'f' : {format = argv[i]; break;} + case 'i' : {pto_image = atoi(argv[i]); break;} + //case 'c' : {cps_per_line = atoi(argv[i]); break;} + //case 'f' : {format = argv[i]; break;} case 'e' : {detector = atoi(argv[i]); break;} case 'g' : {gap_limit = atoi(argv[i]); break;} case 't' : {optimise_centre = atoi(argv[i]); break;} case 'v' : {verbose = atoi(argv[i]); break;} case 'd' : {resize_dimension = atoi(argv[i]); break;} - case 's' : {scale = atof(argv[i]); break;} + //case 's' : {scale = atof(argv[i]); break;} + case 's' : {cropFactor = 24.0/atof(argv[i]); break;} case 'b' : {tscale = atof(argv[i]); break;} case 'a' : {a = atof(argv[i]); break;} //case 't' : {threshold = atof(argv[i]); break;} case 'y' : {corner_threshold = atof(argv[i]); break;} - case 'l' : {length_threshold = atof(argv[i]); break;} - case 'i' : {pixel_density = atof(argv[i]); break;} - case 'k' : {lens_type = atoi(argv[i]); break;} - case 'q' : {focal_length = atof(argv[i]); break;} - case 'm' : {sigma = atof(argv[i]); break;} + case 'm' : {length_threshold = atof(argv[i]); break;} + case 'c' : {cropFactor = atof(argv[i]); break;} + //case 'i' : {pixel_density = atof(argv[i]); break;} + case 'l' : {lens_type = atoi(argv[i]); break;} + case 'f' : {focal_length = atof(argv[i]); break;} + //case 'm' : {sigma = atof(argv[i]); break;} case 'r' : {r = atof(argv[i]); break;} } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-20 12:47:12 UTC (rev 4072) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-20 15:23:43 UTC (rev 4073) @@ -86,8 +86,6 @@ y_point -= original_height/2; y_point *= -1; - - //cout << "(x,y)\t(" << x_point << "," << y_point << ")" << endl; // Replace with distances from centre @@ -187,15 +185,6 @@ void map_points(){ - if(lens_type == 1) cout << "Rectilinear lens" << endl; - if(lens_type == 2) cout << "Equal-area fisheye lens" << endl; - if(lens_type == 3) cout << "Equal-angle fisheye lens" << endl; - cout << "Focal length (mm):\t" << focal_length << endl; - // Convert focal length to pixels - // 1 mm = 0.0393700787402 inches - focal_length = (focal_length * 0.0393700787402) * pixel_density; - cout << "Focal length (pixels):\t" << focal_length << endl << endl; - int iterations = 1000; double info[LM_INFO_SZ]; @@ -203,7 +192,7 @@ int m = 6; double * p = new double[m]; - p[0] = focal_length; + p[0] = focal_length_pixels; p[1] = 0; // p2 p[2] = 0; // p4 Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-20 12:47:12 UTC (rev 4072) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-20 15:23:43 UTC (rev 4073) @@ -140,7 +140,6 @@ } lines.push_back(inliers); - if (generate_images){ // Export slice to file string output = path; @@ -413,6 +412,8 @@ } if (good_lines == 0){ cout << "No lines found!" << endl; + }else{ + //cout << endl; } } @@ -674,14 +675,6 @@ tensorTrace(srcImageRange(boundarytensor), destImage(boundarystrength)); tensorToEdgeCorner(srcImageRange(boundarytensor), destImage(edgeness), destImage(cornerness)); - - - - - - - - //nuke_corners(out, corners, file); nuke_corners(out, cornerness, file); extract_coords(out, edgeness, 1); @@ -694,174 +687,119 @@ } #ifdef HUGIN_USE_EXIV2 -// Convenience functions to work with Exiv2 -bool getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, long & value) -{ - Exiv2::ExifKey key(keyName); - Exiv2::ExifData::iterator itr = exifData.findKey(key); - if (itr != exifData.end()) { - value = itr->toLong(); - //DEBUG_DEBUG("" << keyName << ": " << value); - return true; - } else { - return false; - } + +bool getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, long & value){ + Exiv2::ExifKey key(keyName); + Exiv2::ExifData::iterator itr = exifData.findKey(key); + if (itr != exifData.end()) { + value = itr->toLong(); + //DEBUG_DEBUG("" << keyName << ": " << value); + return true; + }else{ + return false; + } } - -bool getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, float & value) -{ - Exiv2::ExifKey key(keyName); - Exiv2::ExifData::iterator itr = exifData.findKey(key); - if (itr != exifData.end()) { - value = itr->toFloat(); - //DEBUG_DEBUG("" << keyName << ": " << value); - return true; - } else { - return false; - } +bool getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, float & value){ + Exiv2::ExifKey key(keyName); + Exiv2::ExifData::iterator itr = exifData.findKey(key); + if (itr != exifData.end()) { + value = itr->toFloat(); + //DEBUG_DEBUG("" << keyName << ": " << value); + return true; + }else{ + return false; + } } #endif // HUGIN_USE_EXIV2 -bool get_exif_data(string& filename){ +void calculate_focal_length_pixels(){ + if(lens_type == 1) cout << "Rectilinear lens" << endl; + if(lens_type == 2) cout << "Equal-area fisheye lens" << endl; + if(lens_type == 3) cout << "Equal-angle fisheye lens" << endl; + cout << "Crop factor:\t\t\t" << cropFactor << endl; - cout << "Using jhead..." << endl; + double pixels_per_mm = 0; + if (cropFactor != 0){ + if (cropFactor > 1){ + if (original_width > original_height){ + pixels_per_mm = original_height * (cropFactor/24.0); + + }else{ + pixels_per_mm = original_width * (cropFactor/24.0); + } + }else{ + if (original_width > original_height){ + pixels_per_mm = original_height * (24.0/cropFactor); + + }else{ + pixels_per_mm = original_width * (24.0/cropFactor); + } + } + cout << "Pixel density (pixels/mm):\t" << pixels_per_mm << endl; + }else{ + // Need command line param + cout << "Could not identify crop factor from EXIF data. Please provide it as a command line parameter with the -c flag." << endl; + exit(1); + } + + if (focal_length != 0){ + + focal_length_pixels = focal_length*pixels_per_mm; + + cout << "Focal length (mm):\t\t" << focal_length << endl; + cout << "Focal length (pixels):\t\t" << focal_length_pixels << endl << endl; + }else{ + // Need command line param + cout << "Could not identify focal length from EXIF data. Please provide it as a command line parameter with the -f flag." << endl; + exit(1); + } - // Read exif data +} +int get_exif_data(string& filename){ + // Read exif data using jhead + // Needed to check if exif.CameraModel == "Canon EOS 20D" ImageInfo_t exif; ResetJpgfile(); - // Start with an empty image information structure. - memset(&exif, 0, sizeof(exif)); + ReadJpegFile(exif,filename.c_str(), READ_EXIF); - if (!ReadJpegFile(exif,filename.c_str(), READ_EXIF)){ - puts("Exif read failed"); - }else{ - if (focal_length == 0) { - focal_length = exif.FocalLength; - cout << "Found focal length:\t" << focal_length << endl; - } - if (sensor_width == 0){ - sensor_width = exif.CCDWidth; - cout << "Found sensor width:\t" << sensor_width << endl; - } - if (sensor_height == 0){ - sensor_height = exif.CCDHeight; - cout << "Found sensor height:\t" << sensor_height << endl; - } - } - cout << endl; - - + // Read exif data using exiv2 #ifdef HUGIN_USE_EXIV2 typedef struct { double x, y; } sensor; - - cout << "Scanning EXIF data..." << endl; - + double width = original_width; double height = original_height; - double cropFactor,focalLength; - + Exiv2::Image::AutoPtr image; try { image = Exiv2::ImageFactory::open(filename.c_str()); }catch(...) { - std::cout << __FILE__ << " " << __LINE__ << " Error opening file" << std::endl; - return false; + cout << "Error opening file " << filename << endl; + cout << "Please provide crop factor and focal length values via command line parameters." << endl << endl; + exit(1); } if (image.get() == 0) { - std::cout << "Unable to open file to read EXIF data: " << filename << std::endl; - return false; + cout << "Unable to open file " << filename << " to read EXIF data." << endl; + cout << "Please provide crop factor and focal length values via command line parameters." << endl << endl; + exit(1); } image->readMetadata(); Exiv2::ExifData &exifData = image->exifData(); if (exifData.empty()) { - std::cout << "Unable to read EXIF data from opened file:" << filename << std::endl; - return false; + cout << "Unable to read EXIF data from file " << filename << endl; + cout << "Please provide crop factor and focal length values via command line parameters." << endl << endl; + exit(1); } - - - /* - //getExiv2Value(exifData,"Exif.Photo.ExposureTime",exposureTime); - // TODO: reconstruct real exposure value from "rounded" ones saved by the cameras? - - getExiv2Value(exifData,"Exif.Photo.FNumber",photoFNumber); - - if (exposureTime > 0 && photoFNumber > 0) { - double gain = 1; - if (getExiv2Value(exifData,"Exif.Photo.ISOSpeedRatings",isoSpeed)) { - if (isoSpeed > 0) { - gain = isoSpeed / 100.0; - } - } - eV = log2(photoFNumber * photoFNumber / (gain * exposureTime)); - DEBUG_DEBUG ("Ev: " << eV); - } - - - Exiv2::ExifKey key("Exif.Image.Make"); - Exiv2::ExifData::iterator itr = exifData.findKey(key); - if (itr != exifData.end()) - setExifMake(itr->toString()); - else - setExifMake("Unknown"); - - Exiv2::ExifKey key2("Exif.Image.Model"); - itr = exifData.findKey(key2); - if (itr != exifData.end()) - setExifModel(itr->toString()); - else - setExifModel("Unknown"); - - long orientation = 0; - if (getExiv2Value(exifData,"Exif.Image.Orientation",orientation)) { - switch (orientation) { - case 3: // rotate 180 - roll = 180; - break; - case 6: // rotate 90 - roll = 90; - break; - case 8: // rotate 270 - roll = 270; - break; - default: - break; - } - } - - long pixXdim = 0; - getExiv2Value(exifData,"Exif.Photo.PixelXDimension",pixXdim); - - long pixYdim = 0; - getExiv2Value(exifData,"Exif.Photo.PixelYDimension",pixYdim); - - if (pixXdim !=0 && pixYdim !=0 ) { - double ratioExif = pixXdim/(double)pixYdim; - double ratioImage = width/(double)height; - if (fabs( ratioExif - ratioImage) > 0.1) { - // Image has been modified without adjusting exif tags. - // Assume user has rotated to upright pose - roll = 0; - } - } - */ - - //GWP - CCD info was previously computed by the jhead library. Migration - // to exiv2 means we do it here - - // some cameras do not provide Exif.Image.ImageWidth / Length - // notably some Olympus - long eWidth = 0; getExiv2Value(exifData,"Exif.Image.ImageWidth",eWidth); @@ -886,12 +824,8 @@ sensorPixelHeight = t; } - //DEBUG_DEBUG("sensorPixelWidth: " << sensorPixelWidth); - //DEBUG_DEBUG("sensorPixelHeight: " << sensorPixelHeight); - // some cameras do not provide Exif.Photo.FocalPlaneResolutionUnit // notably some Olympus - long exifResolutionUnits = 0; getExiv2Value(exifData,"Exif.Photo.FocalPlaneResolutionUnit",exifResolutionUnits); @@ -903,11 +837,6 @@ default: resolutionUnits = 25.4; break; //inches } - //DEBUG_DEBUG("Resolution Units: " << resolutionUnits); - - // some cameras do not provide Exif.Photo.FocalPlaneXResolution and - // Exif.Photo.FocalPlaneYResolution, notably some Olympus - float fplaneXresolution = 0; getExiv2Value(exifData,"Exif.Photo.FocalPlaneXResolution",fplaneXresolution); @@ -916,8 +845,6 @@ float CCDWidth = 0; if (fplaneXresolution != 0) { -// CCDWidth = (float)(sensorPixelWidth * resolutionUnits / -// fplaneXresolution); CCDWidth = (float)(sensorPixelWidth / ( fplaneXresolution / resolutionUnits)); } @@ -926,12 +853,8 @@ CCDHeight = (float)(sensorPixelHeight / ( fplaneYresolution / resolutionUnits)); } - //DEBUG_DEBUG("CCDHeight:" << CCDHeight); - //DEBUG_DEBUG("CCDWidth: " << CCDWidth); - // calc sensor dimensions if not set and 35mm focal length is available sensor sensorSize; - if (CCDHeight > 0 && CCDWidth > 0) { // read sensor size directly. sensorSize.x = CCDWidth; @@ -946,17 +869,14 @@ double rsensor = (double)sensorSize.x / sensorSize.y; double rimg = (double) width / height; if ( (rsensor > 1 && rimg < 1) || (rsensor < 1 && rimg > 1) ) { - // image and sensor ratio do not match - // swap sensor sizes - float t; - t = sensorSize.y; - sensorSize.y = sensorSize.x; - sensorSize.x = t; + // image and sensor ratio do not match + // swap sensor sizes + float t; + t = sensorSize.y; + sensorSize.y = sensorSize.x; + sensorSize.x = t; } - //DEBUG_DEBUG("sensorSize.y: " << sensorSize.y); - //DEBUG_DEBUG("sensorSize.x: " << sensorSize.x); - cropFactor = sqrt(36.0*36.0+24.0*24.0) / sqrt(sensorSize.x*sensorSize.x + sensorSize.y*sensorSize.y); // FIXME: HACK guard against invalid image focal plane definition in EXIF metadata with arbitrarly chosen limits for the crop factor ( 1/100 < crop < 100) @@ -970,8 +890,7 @@ // left in as example on how to get "console output" // written to a log file // freopen ("oly.log","a",stdout); - // fprintf (stdout,"Starting Alternative crop determination\n"); - + // fprintf (stdout,"Starting Alternative crop determination\n"); float olyFPD = 0; getExiv2Value(exifData,"Exif.Olympus.FocalPlaneDiagonal",olyFPD); @@ -983,37 +902,37 @@ } } - //DEBUG_DEBUG("cropFactor: " << cropFactor); - float eFocalLength = 0; - getExiv2Value(exifData,"Exif.Photo.FocalLength",eFocalLength); + float efocal_length = 0; + getExiv2Value(exifData,"Exif.Photo.FocalLength",efocal_length); - float eFocalLength35 = 0; - getExiv2Value(exifData,"Exif.Photo.FocalLengthIn35mmFilm",eFocalLength35); + float efocal_length35 = 0; + getExiv2Value(exifData,"Exif.Photo.FocalLengthIn35mmFilm",efocal_length35); //The various methods to detmine crop factor - if (eFocalLength > 0 && cropFactor > 0) { + if (efocal_length > 0 && cropFactor > 0) { // user provided crop factor - focalLength = eFocalLength; - }else if (eFocalLength35 > 0 && eFocalLength > 0) { - cropFactor = eFocalLength35 / eFocalLength; - focalLength = eFocalLength; - }else if (eFocalLength35 > 0) { + focal_length = efocal_length; + }else if (efocal_length35 > 0 && efocal_length > 0) { + cropFactor = efocal_length35 / efocal_length; + focal_length = efocal_length; + }else if (efocal_length35 > 0) { // 35 mm equiv focal length available, crop factor unknown. // do not ask for crop factor, assume 1. Probably a full frame sensor cropFactor = 1; - focalLength = eFocalLength35; - }else if (eFocalLength > 0 && cropFactor <= 0) { + focal_length = efocal_length35; + }else if (efocal_length > 0 && cropFactor <= 0) { // need to redo, this time with crop - focalLength = eFocalLength; + focal_length = efocal_length; cropFactor = 0; } + /* cout << "Width:\t\t" << width << endl; cout << "Height:\t\t" << height << endl; cout << "eWidth:\t\t" << eWidth << endl; cout << "eHeight:\t" << eLength << endl; - cout << "Focal length:\t" << focalLength << endl; + cout << "Focal length:\t" << focal_length << endl; cout << "Crop factor:\t" << cropFactor << endl; cout << "sensorSize.x:\t" << sensorSize.x << endl; cout << "sensorSize.y:\t" << sensorSize.y << endl; @@ -1022,12 +941,11 @@ cout << "sensorPixelWidth:\t" << sensorPixelWidth << CCDWidth << endl; cout << "sensorPixelHeight:\t" << sensorPixelHeight << CCDWidth << endl; cout << "Resolution Units:\t" << resolutionUnits << CCDWidth << endl << endl; - - + */ #endif + calculate_focal_length_pixels(); + return(1); - return false; - } void process_image(string& filename){ @@ -1043,7 +961,11 @@ original_width = info.width(); original_height = info.height(); - bool exif_ok = get_exif_data(filename); + if (focal_length && cropFactor){ + calculate_focal_length_pixels(); + }else{ + int exif_ok = get_exif_data(filename); + } if (nw > nh){ min_line_length_squared = (length_threshold*nw)*(length_threshold*nw); @@ -1136,6 +1058,6 @@ detect_edge(grey, cornerness, edgeness, filename, path, format); - map_points(); + if (lines.size()) map_points(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-26 23:48:04
|
Revision: 4106 http://hugin.svn.sourceforge.net/hugin/?rev=4106&view=rev Author: blimbo Date: 2009-07-26 23:47:54 +0000 (Sun, 26 Jul 2009) Log Message: ----------- Appied Tom's patch, cleaned up ProcessImages.cpp a lot, no longer optimise focal length Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-26 15:56:01 UTC (rev 4105) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-26 23:47:54 UTC (rev 4106) @@ -52,7 +52,6 @@ unsigned int vertical_slices = 12; unsigned int horizontal_slices = 8; unsigned int generate_images = 1; -std::vector<vigra::Point2D> inliers; std::vector<std::vector<vigra::Point2D> > lines; double sigma = 1.4; double r = 140; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-26 15:56:01 UTC (rev 4105) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-26 23:47:54 UTC (rev 4106) @@ -35,7 +35,6 @@ extern unsigned int vertical_slices; extern unsigned int generate_images; extern unsigned int generate_images; -extern std::vector<vigra::Point2D> inliers; extern std::vector<std::vector<vigra::Point2D> > lines; extern double sigma; extern double r; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-26 15:56:01 UTC (rev 4105) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-26 23:47:54 UTC (rev 4106) @@ -25,6 +25,8 @@ #include "Globals.h" #include "ProcessImage.h" +#include "MapPoints.h" + using namespace std; #define VERSION 0.1 @@ -413,9 +415,21 @@ } cout << "Processing image " << images[i].c_str() << endl << endl; process_image(images[i]); - } + cout << "Found "<< lines.size() <<" lines"<<endl; + + int n_params = 2; + if (lens_type == 2) ++n_params; + if(optimise_centre) n_params += 2; + + if (lines.size() >= n_params ) map_points(); + else{ + cout << "Not enough lines to fit "<< n_params <<" parameters."<<endl; + return 3; + } + + if (pto_file != ("")){ write_pto(output_pto,pto_file_top,pto_file_cps,pto_file_end,pto_image,cps_per_line); cout << "Written file " << output_pto << endl; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-26 15:56:01 UTC (rev 4105) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-26 23:47:54 UTC (rev 4106) @@ -27,10 +27,23 @@ using namespace std; -typedef struct { +class XYZPoint { +public: double x, y, z; -} XYZPoint; + XYZPoint( double X, double Y, double Z ) + : x(X), y(Y), z(Z) {} + XYZPoint() : x(0), y(0), z(0) {} +}; +XYZPoint XYZdifference( XYZPoint & a, XYZPoint & b ){ + return XYZPoint( b.x - a.x, b.y - a.y, b.z - a.z ); +} + +double XYZdistance( XYZPoint & a, XYZPoint & b ){ + XYZPoint d = XYZdifference( a, b ); + return sqrt( d.x * d.x + d.y * d.y + d.z * d.z ); +} + XYZPoint CrossProduct (XYZPoint v1, XYZPoint v2){ XYZPoint cp; cp.x = v1.y * v2.z - v1.z * v2.y; @@ -58,25 +71,26 @@ double y_centre = 0; if (lens_type == 2){ if(optimise_centre){ - x_centre = p[4]; - y_centre = p[5]; + x_centre = p[3]; + y_centre = p[4]; } }else{ if(optimise_centre){ - x_centre = p[3]; - y_centre = p[4]; + x_centre = p[2]; + y_centre = p[3]; } } for (unsigned int l = 0; l < lines.size(); l++){ //cout << "Optimising line " << l+1 << "..." << endl; + int npnts = lines[l].size(); //XYZPoint mapped_point[lines[current_line].size()]; - XYZPoint * mapped_point = new XYZPoint[lines[l].size()]; + XYZPoint * mapped_point = new XYZPoint[npnts]; // Map points to 3D and fill the above array with XYZPoints - for(unsigned int i = 0; i < lines[l].size(); i++){ + for(unsigned int i = 0; i < npnts; i++){ double x_point = invert_size_factor * lines[l][i]->x; double y_point = invert_size_factor * lines[l][i]->y; @@ -99,13 +113,13 @@ double r = sqrt(x_point * x_point + y_point * y_point); // u = r / f; - double u = r / p[0]; + double u = r / focal_length_pixels; // R - distance of a point from the center of projection, // corrected for barrel distortion, unitless, or radians // (1 - p2 - p4) is for normalisation - // p2 = p[3], p4 = [4] - double R = (1 - p[1] - p[2]) * u + p[1] * (u*u) + p[2] * (u*u*u*u); + // p2 = p[0], p4 = [1] + double R = (1 - p[0] - p[1]) * u + p[0] * (u*u) + p[1] * (u*u*u*u); // a - angular distance of a point from the center of projection, in radians double a; @@ -154,8 +168,8 @@ } // Vector cross product of the end points - this is the normal to the estimated plane - XYZPoint norm = CrossProduct(mapped_point[0],mapped_point[n-1]); - + XYZPoint norm = CrossProduct(mapped_point[0],mapped_point[npnts - 1]); + /* cout << endl << "Cross product of end points:" << endl; cout << norm.x << endl; @@ -165,15 +179,15 @@ // Comput straigthness error double ssq = 0; - for(unsigned int i = 1; i < n - 1; i++){ + for(unsigned int i = 1; i < npnts - 1; i++){ // Add square of dot product of that point with norm double d = DotProduct(norm,mapped_point[i]); ssq += d * d; } - // Add to optimizer's error vector - x[l] = sqrt((n - 2) * ssq ); + // normalize, weight, add to optimizer's error vecto + x[l] = sqrt((npnts - 2) * ssq ) / XYZdistance(mapped_point[0],mapped_point[npnts - 1]); //cout << "Error:\t" << x[l] << endl; - line_errors[l] = x[l]; + line_errors[l] = x[l] / npnts; // save error per data point delete [] mapped_point; } @@ -189,28 +203,28 @@ double info[LM_INFO_SZ]; // Set up initial parameters - int m = 6; + int m = 5; double * p = new double[m]; - p[0] = focal_length_pixels; - p[1] = 0; // p2 - p[2] = 0; // p4 + //p[0] = focal_length_pixels; + p[0] = 0; // p2 + p[1] = 0; // p4 if (lens_type == 2){ - p[3] = 2; // k + p[2] = 2; // k if(optimise_centre){ - p[4] = 0; // x_center; - p[5] = 0; // y_center; + p[3] = 0; // x_center; + p[4] = 0; // y_center; }else{ - m = 4; + m = 3; } }else{ if(optimise_centre){ - m = 5; - p[3] = 0; // x_center; - p[4] = 0; // y_center; + m = 4; + p[2] = 0; // x_center; + p[3] = 0; // y_center; }else{ - m = 3; + m = 2; } } @@ -224,20 +238,20 @@ int ret = dlevmar_dif(&Mapto3d, &visf, p, x, m, n, iterations, NULL, info, NULL, NULL, NULL); printf("\nLevenberg-Marquardt returned in %g iter, reason %g\nSolution:\n", info[5], info[6]); - cout << "Focal length:\t\t" << p[0] << endl; - cout << "p2:\t\t\t" << p[1] << endl; - cout << "p4:\t\t\t" << p[2] << endl; + //cout << "Focal length:\t\t" << p[0] << endl; + cout << "p2:\t\t\t" << p[0] << endl; + cout << "p4:\t\t\t" << p[1] << endl; if (lens_type == 2){ - cout << "k:\t\t\t" << p[3] << endl; + cout << "k:\t\t\t" << p[2] << endl; if(optimise_centre){ - cout << "x centre:\t\t" << p[4] << endl; - cout << "y centre\t\t" << p[5] << endl; + cout << "x centre:\t\t" << p[3] << endl; + cout << "y centre\t\t" << p[4] << endl; } }else{ if(optimise_centre){ - cout << "x centre:\t\t" << p[3] << endl; - cout << "y centre\t\t" << p[4] << endl; + cout << "x centre:\t\t" << p[2] << endl; + cout << "y centre\t\t" << p[3] << endl; } } for (unsigned int i = 0; i < n; i++){ Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-26 15:56:01 UTC (rev 4105) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-26 23:47:54 UTC (rev 4106) @@ -47,7 +47,6 @@ #include <time.h> #endif -//using namespace hugin_utils; using namespace vigra; using namespace std; @@ -61,31 +60,6 @@ } -/* -void ransac(vector<Point2D>& coords){ - - cout << coords.size() << " 'edge' coordinates found." << endl; - - vector<double> curveParameters; - double desiredProbabilityForNoOutliers = 0.9; - double maximalOutlierPercentage = 0.8; - // Use 4 points - // Point must be within 10 units of curve to agree - //ParameterEstimator curveEstimator(3, 0.1); - //ParameterEstimator curveEstimator(4, 2); - LineParamEstimator curveEstimator(2,10); - - cout << endl << "Computing RANSAC..." << endl; - double usedData = Ransac::compute(curveParameters, &curveEstimator, coords, desiredProbabilityForNoOutliers, maximalOutlierPercentage); - //for (int i = 0; i < curveParameters.size(); i++){ - // cout << "Parameter " << i << ":\t" << curveParameters[i] << endl; - //} - - cout << "Percentage of points which were used for final estimate: "<< usedData/coords.size() << " % (" << usedData << ")" << endl << endl; - -} -*/ - bool compare_yx (const vigra::Point2D i,const vigra::Point2D j){ return (j->x<i->x); } @@ -94,26 +68,44 @@ return (i->x<j->x); } -void plot_inliers(BImage& image, int i){ +void sort_inliers(vector<Point2D>& inliers){ - vigra::BRGBImage tmp(image.width(),image.height()); - vigra::initImage(srcIterRange(tmp.upperLeft(), - tmp.upperLeft() + vigra::Diff2D(image.width(),image.height())), - RGB(255,255,255) ); - unsigned int top = 0; unsigned int bottom = 100000; unsigned int left = 100000; unsigned int right = 0; - cout << "Plotting line " << i << ". Pixels:\t" << inliers.size() << endl << endl; for (unsigned int il = 0; il < inliers.size(); il++){ if(inliers[il]->x < left) left = inliers[il]->x; if(inliers[il]->x > right) right = inliers[il]->x; if(inliers[il]->y < bottom) bottom = inliers[il]->y; if(inliers[il]->y > top) top = inliers[il]->y; + + } + + // Sort pixels for adding CPs to PTO file + int d1 = abs(top-bottom); + int d2 = abs(right-left); + if(d2 > d1){ + sort(inliers.begin(), inliers.end(), compare_xy); + }else{ + sort(inliers.begin(), inliers.end(), compare_yx); + } +} +void plot_inliers(BImage& image, vector<Point2D>& inliers, int i){ + + vigra::BRGBImage tmp(image.width(),image.height()); + vigra::initImage(srcIterRange(tmp.upperLeft(), + tmp.upperLeft() + vigra::Diff2D(image.width(),image.height())), + RGB(255,255,255) ); + + cout << "Plotting line " << i << ". Pixels:\t" << inliers.size() << endl << endl; + for (unsigned int il = 0; il < inliers.size(); il++){ + + /* + // Careful, this might segfault if the box goes off the image.. if(il == 0 )vigra::initImage(srcIterRange(tmp.upperLeft() + vigra::Diff2D(inliers[il]->x-3, inliers[il]->y-3), tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+3, inliers[il]->y+3)), @@ -123,22 +115,12 @@ vigra::Diff2D(inliers[il]->x-3, inliers[il]->y-3), tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+3, inliers[il]->y+3)), RGB(0,255,0) ); - + */ vigra::initImage(srcIterRange(tmp.upperLeft() + vigra::Diff2D(inliers[il]->x, inliers[il]->y), tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+1, inliers[il]->y+1)), RGB(255,0,0) ); } - - // Sort pixels for adding CPs to PTO file - int d1 = abs(top-bottom); - int d2 = abs(right-left); - if(d2 > d1){ - sort(inliers.begin(), inliers.end(), compare_xy); - }else{ - sort(inliers.begin(), inliers.end(), compare_yx); - } - lines.push_back(inliers); if (generate_images){ // Export slice to file @@ -152,12 +134,10 @@ exportImage(srcImageRange(tmp), ImageExportInfo(output.c_str()).setPixelType("UINT8")); //exportImage(srcImageRange(tmp), output.c_str().setPixelType("UINT8")); } - } -void find_ann(vector<Point2D>& coords, FVector2Image& edgeness, unsigned int& good_lines){ +void find_ann(vector<Point2D>& coords, FVector2Image& edgeness, vector<Point2D>& inliers, unsigned int& good_lines){ - int k = 1; // Number of nearest neighbours int dim = 3; // Dimensions double eps = 0.0; // Error bound @@ -340,17 +320,8 @@ } annDeallocPts(dataPts); } - //annDeallocPt(queryPt); annClose(); -/* -export MALLOC_CHECK=0 - -Program received signal SIGSEGV, Segmentation fault. -[Switching to Thread 0xb714c6d0 (LWP 7191)] -0xb720958d in free () from /lib/tls/i686/cmov/libc.so.6 -*/ - double length = line_length_squared(first_line_end_x, first_line_end_y,inliers[inliers.size()-1]->x,inliers[inliers.size()-1]->y); if(verbose) cout << endl << "Measuring distance from " << first_line_end_x << "," << first_line_end_y << " to " << inliers[inliers.size()-1]->x << "," << @@ -369,169 +340,19 @@ } -void extract_coords(BImage& image, FVector2Image& edgeness, int i){ +void extract_coords(BImage& image, vector<Point2D>& coords){ - vector<Point2D> coords; - // Gather black pixels for (unsigned int h = 0; h < image.height(); h++){ for (unsigned int w = 0; w < image.width(); w++){ - RGBValue<int,0u,1u,2u> value = image(w,h); - if (value[0] != 255){ - + if (value[0] != 255){ coords.push_back(Point2D(w,h)); - - //cout << "(" << w << "," << h << ")" << endl; } } } - - //ransac(coords); - //plot_inliers(image,i); - - unsigned int intital_coords_size = coords.size(); - - if(verbose) cout << "Initial 'edge' pixel count:\t" << coords.size() << endl << endl; - - // Get 10 strongest lines - // Stop when only 35% of coordinates are left - unsigned int good_lines = 0; - //while (good_lines < 10 && coords.size() && 100*((double)coords.size()/intital_coords_size) >= 25){ - while (good_lines < 10 && coords.size() > 1){ - if(verbose) cout << "Searching for line " << good_lines+1 << ":" << endl; - if(verbose) cout << "=====================" << endl << endl; - - find_ann(coords, edgeness, good_lines); - //ransac(coords); - - if(inliers.size())plot_inliers(image,good_lines); - if(verbose) cout << "Remaining coords:\t" << coords.size() << "\t(" << 100*((double)coords.size()/intital_coords_size) << " %)" << endl << endl; - - inliers.clear(); - } - if (good_lines == 0){ - cout << "No lines found!" << endl; - }else{ - //cout << endl; - } - } -/* -void sub_image(BImage& image){ - - unsigned int vertical_slice_width = image.width()/vertical_slices; - unsigned int horizontal_slice_height = image.height()/horizontal_slices; - - //cout << "vertical_slice_width: " << vertical_slice_width << endl; - //cout << "horizontal_slice_height: " << horizontal_slice_height << endl; - - try{ - - cout << "Generate vertical slices..." << endl; - - unsigned int sub_y0 = 0; - unsigned int sub_y1 = image.height(); - - for (unsigned int i = 0; i <= vertical_slices; i++){ - - int sub_x0 = i * vertical_slice_width; - int sub_x1 = (i+1) * vertical_slice_width; - // Make the slices overlap by 50% - if (i){ - sub_x0 -= vertical_slice_width/2; - sub_x1 -= vertical_slice_width/2; - } - if (sub_x1 > image.width()) sub_x1 = image.width(); - - if (i){ - cout << "Vertical slice " << i << "\t: (" << sub_x0 << "," << sub_y0 << ")\t--->\t("; - cout << sub_x1 << "," << sub_y1 << ")" << endl; - }else{ - cout << "Vertical slice " << i << "\t: (" << sub_x0 << "," << sub_y0 << ")\t\t--->\t("; - cout << sub_x1 << "," << sub_y1 << ")" << endl; - } - - BImage out(sub_x1 - sub_x0, sub_y1 - sub_y0); - // Copy region of interest by moving the input - // iterators to the appropriate positions - copyImage(srcIterRange(image.upperLeft() + Diff2D(sub_x0, sub_y0), - image.upperLeft() + Diff2D(sub_x1, sub_y1)), - destImage(out)); - - // Get line coordinates - extract_coords(out,i); - - if (generate_images){ - // Export slice to file - string output = path; - output.append("vertical_slice_"); - stringstream ii; - ii << i; - output.append(ii.str()); - output.append(".jpg"); - exportImage(srcImageRange(out), output.c_str()); - } - - } - - exit(1); - - unsigned int sub_x0 = 0; - unsigned int sub_x1 = image.width(); - - cout << endl << "Generate horiztonal slices..." << endl; - - for (unsigned int i = 0; i <= horizontal_slices; i++){ - - int sub_y0 = i * horizontal_slice_height; - int sub_y1 = (i+1) * horizontal_slice_height; - // Make the slices overlap by 50% - if (i){ - sub_y0 -= horizontal_slice_height/2; - sub_y1 -= horizontal_slice_height/2; - } - if (sub_y1 > image.height()) sub_y1 = image.height(); - - if (i){ - cout << "Horizontal slice " << i << "\t: (" << sub_x0 << "," << sub_y0 << ")\t--->\t("; - cout << sub_x1 << "," << sub_y1 << ")" << endl; - }else{ - cout << "Horizontal slice " << i << "\t: (" << sub_x0 << "," << sub_y0 << ")\t\t--->\t("; - cout << sub_x1 << "," << sub_y1 << ")" << endl; - } - - BImage out(sub_x1 - sub_x0, sub_y1 - sub_y0); - // Copy region of interest by moving the input - // iterators to the appropriate positions - copyImage(srcIterRange(image.upperLeft() + Diff2D(sub_x0, sub_y0), - image.upperLeft() + Diff2D(sub_x1, sub_y1)), - destImage(out)); - - // Get line coordinates - extract_coords(out,i); - - if (generate_images){ - //Export slice to file - string output = path; - output.append("horizontal_slice_"); - stringstream ii; - ii << i; - output.append(ii.str()); - output.append(".jpg"); - exportImage(srcImageRange(out), output.c_str()); - } - } - } - - catch (StdException & e){ - cout << e.what() << endl; - } - -} -*/ - void nuke_corners(BImage& image, FImage& corners, string& file){ for (unsigned int h = 0; h < corners.height(); h++){ @@ -612,31 +433,25 @@ } } -void detect_edge(BImage& image, FImage& corners, FVector2Image& edgeness, string& file, string& path, string& format){ +void detect_edge(BImage& image, string& file, string& path, string& format, BImage& edge_image){ - try{ - + try{ // Paint output image white - BImage out(image.width(), image.height()); - //cout << image.width() << " x " << image.height() << endl; - out = 255; + edge_image = 255; cout << "Detecting edges..." << endl << endl; - if(detector){ - + if(detector){ // Call Shen-Castan detector algorithm - differenceOfExponentialEdgeImage(srcImageRange(image), destImage(out), + differenceOfExponentialEdgeImage(srcImageRange(image), destImage(edge_image), scale, threshold, 0); - }else{ - + }else{ // Call Canny detector algorithm - cannyEdgeImage(srcImageRange(image), destImage(out), + cannyEdgeImage(srcImageRange(image), destImage(edge_image), scale, threshold, 0); } if (generate_images){ - // Create output file name string output = path; @@ -658,32 +473,25 @@ output.append(format); cout << "Writing " << output << endl; - exportImage(srcImageRange(out), output.c_str()); + exportImage(srcImageRange(edge_image), output.c_str()); } + } + catch (StdException & e){ + cout << e.what() << endl; + } +} +void generate_boundary_tensor(BImage& image, FVector2Image& edgeness, FImage& cornerness){ - // Get cornerness from edge detection output - // Create image of appropriate size for boundary tensor - FVector3Image boundarytensor(image.width(), image.height()); + // Get cornerness from edge detection output + // Create image of appropriate size for boundary tensor + FVector3Image boundarytensor(image.width(), image.height()); - // Calculate the boundary tensor - cout << "Calculating boundary tensor..." << endl; - boundaryTensor(srcImageRange(out), destImage(boundarytensor), tscale); + // Calculate the boundary tensor + cout << "Calculating boundary tensor..." << endl; + boundaryTensor(srcImageRange(image), destImage(boundarytensor), tscale); - FImage boundarystrength(image.width(), image.height()), cornerness(image.width(), image.height()); - FVector2Image edgeness(image.width(), image.height()); - - tensorTrace(srcImageRange(boundarytensor), destImage(boundarystrength)); - tensorToEdgeCorner(srcImageRange(boundarytensor), destImage(edgeness), destImage(cornerness)); - - nuke_corners(out, cornerness, file); - extract_coords(out, edgeness, 1); - - } - - catch (StdException & e){ - cout << e.what() << endl; - } + tensorToEdgeCorner(srcImageRange(boundarytensor), destImage(edgeness), destImage(cornerness)); } #ifdef HUGIN_USE_EXIV2 @@ -948,44 +756,21 @@ } -void process_image(string& filename){ - - ImageImportInfo info(filename.c_str()); - - UInt16RGBImage in(info.width(), info.height()); - - importImage(info, destImage(in)); - - int nw = info.width(), nh = info.height(); +void resize_image(UInt16RGBImage& in, int& nw, int& nh){ - original_width = info.width(); - original_height = info.height(); - - if (focal_length && cropFactor){ - calculate_focal_length_pixels(); - }else{ - int exif_ok = get_exif_data(filename); - } - - if (nw > nh){ - min_line_length_squared = (length_threshold*nw)*(length_threshold*nw); - }else{ - min_line_length_squared = (length_threshold*nh)*(length_threshold*nh); - } - // Re-size to max dimension - if (info.width() > resize_dimension || info.height() > resize_dimension){ + if (in.width() > resize_dimension || in.height() > resize_dimension){ - if (info.width() >= info.height()){ - sizefactor = (double)resize_dimension/info.width(); + if (in.width() >= in.height()){ + sizefactor = (double)resize_dimension/in.width(); // calculate new image size nw = resize_dimension; - nh = static_cast<int>(0.5 + (sizefactor*info.height())); + nh = static_cast<int>(0.5 + (sizefactor*in.height())); min_line_length_squared = (length_threshold*nw)*(length_threshold*nw); }else{ - sizefactor = (double)resize_dimension/info.height(); + sizefactor = (double)resize_dimension/in.height(); // calculate new image size - nw = static_cast<int>(0.5 + (sizefactor*info.width())); + nw = static_cast<int>(0.5 + (sizefactor*in.width())); nh = resize_dimension; min_line_length_squared = (length_threshold*nh)*(length_threshold*nh); } @@ -1001,63 +786,79 @@ resizeImageNoInterpolation(srcImageRange(in),destImageRange(out)); in = out; - - //exportImage(srcImageRange(in), ImageExportInfo("resized.jpg").setPixelType("UINT8")); - //exportImage(srcImageRange(in), ImageExportInfo("resized.tif").setPixelType("UINT16")); + } +} +void process_image(string& filename){ + + ImageImportInfo info(filename.c_str()); + + UInt16RGBImage in(info.width(), info.height()); + + importImage(info, destImage(in)); + + int nw = info.width(), nh = info.height(); + + original_width = info.width(); + original_height = info.height(); + + if (focal_length && cropFactor){ + calculate_focal_length_pixels(); + }else{ + int exif_ok = get_exif_data(filename); } + + if (nw > nh){ + min_line_length_squared = (length_threshold*nw)*(length_threshold*nw); + }else{ + min_line_length_squared = (length_threshold*nh)*(length_threshold*nh); + } + // Resize image + resize_image(in, nw, nh); + // Convert to greyscale BImage grey(nw, nh); copyImage(srcImageRange(in, RGBToGrayAccessor<RGBValue<UInt16> >()), destImage(grey)); - //exportImage(srcImageRange(grey), ImageExportInfo("resized.jpg").setPixelType("UINT8")); - // Uncomment this block to generate images at different scales/thresholds - /* + BImage image(nw, nh); + FVector2Image edgeness(nw,nh); + FImage cornerness(nw, nh); + vector<Point2D> coords, inliers; + + // Run Canny edge detector + detect_edge(grey, filename, path, format, image); - double scale_start = 0.1 ,scale_stop = 25; - double threshold_start = 0, threshold_stop = 10; - double scale_increment = 2, threshold_increment = 1; + // Generate boundary tensor + generate_boundary_tensor(image, edgeness, cornerness); - for (double threshold_test = threshold_start; threshold_test <= threshold_stop; threshold_test += threshold_increment){ + // Remove corners + nuke_corners(image, cornerness, filename); - for (double scale_test = scale_start;scale_test <= scale_stop; scale_test += scale_increment){ - - detect_edge(grey, filename, path, format); + // Get coordinates + extract_coords(image, coords); - } + unsigned int intital_coords_size = coords.size(); + + if(verbose) cout << "Initial 'edge' pixel count:\t" << coords.size() << endl << endl; + + // Get 10 strongest lines + unsigned int good_lines = 0; + while (good_lines < 10 && coords.size() > 1){ + if(verbose) cout << "Searching for line " << good_lines+1 << ":" << endl; + if(verbose) cout << "=====================" << endl << endl; + find_ann(coords, edgeness, inliers, good_lines); + if(inliers.size()){ + sort_inliers(inliers); + plot_inliers(image,inliers,good_lines); + lines.push_back(inliers); + inliers.clear(); + } + if(verbose) cout << "Remaining coords:\t" << coords.size() << "\t(" << 100*((double)coords.size()/intital_coords_size) << " %)" << endl << endl; + } - */ + if (good_lines == 0){ + cout << "No lines found!" << endl; + } - // Create image of appropriate size for boundary tensor - FVector3Image boundarytensor(nw, nh); - - // Calculate the boundary tensor - //cout << "Calculating boundary tensor using original image..." << endl; - boundaryTensor(srcImageRange(grey), destImage(boundarytensor), tscale); - - FImage boundarystrength(nw, nh), cornerness(nw, nh); - FVector2Image edgeness(nw,nh); - - tensorTrace(srcImageRange(boundarytensor), destImage(boundarystrength)); - tensorToEdgeCorner(srcImageRange(boundarytensor), destImage(edgeness), destImage(cornerness)); - - //for(int h = 0; h < nh; h++){ - // for(int w = 0; w < nw; w++){ - // TinyVector<float, 2> value = edgeness(w,h); - // cout << w << "," << h << ":\t" << value[0] << " " << value[1] << endl; - // } - //} - - string output = path; - output.append("boundarystrength.jpg"); - exportImage(srcImageRange(boundarystrength), ImageExportInfo(output.c_str()).setPixelType("UINT8")); - output = path; - output.append("cornerstrength.jpg"); - exportImage(srcImageRange(cornerness), ImageExportInfo(output.c_str()).setPixelType("UINT8")); - - detect_edge(grey, cornerness, edgeness, filename, path, format); - - if (lines.size()) map_points(); - } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-26 15:56:01 UTC (rev 4105) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-26 23:47:54 UTC (rev 4106) @@ -7,13 +7,13 @@ double line_length_squared(int, int, int, int); bool compare_xy (const vigra::Point2D,const vigra::Point2D); bool compare_yx (const vigra::Point2D,const vigra::Point2D); -//void ransac(std::vector<vigra::Point2D>&); +void resize_image(vigra::UInt16RGBImage&, int&, int&); void find_ann(std::vector<vigra::Point2D>&, vigra::FVector2Image&, unsigned int&); -void plot_inliers(vigra::BImage& image, int); -void extract_coords(vigra::BImage&, vigra::FVector2Image&, int); +void sort_inliers(std::vector<vigra::Point2D>&); +void plot_inliers(vigra::BImage& image, std::vector<vigra::Point2D>&, int); +void extract_coords(vigra::BImage&, std::vector<vigra::Point2D>&); void nuke_corners(vigra::BImage&, vigra::FImage&, std::string&); -//void sub_image(vigra::BImage& image); -void detect_edge(vigra::BImage&, vigra::FImage&, vigra::FVector2Image&, std::string&, std::string&, std::string&); +void detect_edge(vigra::BImage&, std::string&, std::string&, std::string&, vigra::BImage&); void process_image(std::string&); #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-27 16:20:52
|
Revision: 4117 http://hugin.svn.sourceforge.net/hugin/?rev=4117&view=rev Author: blimbo Date: 2009-07-27 16:20:44 +0000 (Mon, 27 Jul 2009) Log Message: ----------- Function to write/read lines to/from file. Added other lens models but not quite working yet Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-27 14:56:20 UTC (rev 4116) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-27 16:20:44 UTC (rev 4117) @@ -29,6 +29,7 @@ unsigned int lens_type = 1; unsigned int current_line = 0; unsigned int optimise_centre = 0; +unsigned int lens_model = 1; double sensor_width = 0; double sensor_height = 0; double original_width = 0; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-27 14:56:20 UTC (rev 4116) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-27 16:20:44 UTC (rev 4117) @@ -12,6 +12,7 @@ extern unsigned int lens_type; extern unsigned int current_line; extern unsigned int optimise_centre; +extern unsigned int lens_model; extern double sensor_width; extern double sensor_height; extern double original_width; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-27 14:56:20 UTC (rev 4116) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-27 16:20:44 UTC (rev 4117) @@ -21,57 +21,15 @@ #include <fstream> #include <vector> #include <string> -#include <sys/stat.h> #include "Globals.h" #include "ProcessImage.h" - +#include "vigra/diff2d.hxx" #include "MapPoints.h" using namespace std; #define VERSION 0.1 -bool fileexists(string strFilename) { - - struct stat stFileInfo; - bool blnReturn; - int intStat; - - // Attempt to get the file attributes - intStat = stat(strFilename.c_str(),&stFileInfo); - if(intStat == 0) { - - blnReturn = true; - }else{ - - blnReturn = false; - } - - return(blnReturn); -} - -static void tokenize(const string& str, vector<string>& tokens, const string& delimiters = " "){ - - // Skip delimiters at beginning - string::size_type lastPos = str.find_first_not_of(delimiters, 0); - - // Find first non-delimiter - string::size_type pos = str.find_first_of(delimiters, lastPos); - - while (string::npos != pos || string::npos != lastPos){ - - // Found a token, add it to the vector - tokens.push_back(str.substr(lastPos, pos - lastPos)); - - // Skip delimiters. Note the not_of - lastPos = str.find_first_not_of(delimiters, pos); - - // Find next non-delimiter - pos = str.find_first_of(delimiters, lastPos); - } - -} - static void parse_pto(string& f,vector<string>& images,vector<string>& pto_file_top,vector<string>& pto_file_cps,vector<string>& pto_file_end, unsigned int& image_number){ @@ -296,8 +254,9 @@ cout << endl << "Version " << VERSION << endl; cout << endl << "Usage: calibrate_lens [options] image1 image2.." << endl << endl; cout << "Options:" << endl << endl; - cout << " -p <filename> Input Hugin PTO file." << endl; + cout << " -p <filename> Input Hugin PTO file." << endl; cout << " -i <int> Image in Hugin PTO file to process. Default 0" << endl; + cout << " -j <filename> Input file containing line data." << endl; //cout << " -c <int> Control points to add to PTO file per line. Default 10." << endl; cout << " -e <0|1> Edge detector. 0 = Canny (default) 1 = Shen-Castan." << endl; cout << " -d <int> Maximum dimension for re-sized image prior to processing. Default 1600." << endl; @@ -317,6 +276,11 @@ cout << " -l <int> Lens type. 1 = Rectilinear (default)" << endl; cout << " 2 = Equal-area fisheye" << endl; cout << " 3 = Equal-angle fisheye" << endl; + + cout << " -x <int> Lens model.1 = R = u + p2 * u^2 + p4 * u^4 (default)" << endl; + cout << " 2 = R = a * u^4 + b * u^3 + c * u^2 (Panotools)" << endl; + cout << " 3 = R = k * 2 * tan(A/2) + (1 - k) * 2 * sin(A/2) (universal fisheye)" << endl; + //cout << " -i <0|1> Generate intermediate images. Default 1" << endl; cout << " -t <0|1> Optimise image centre. Default 0" << endl; cout << " -v <0|1> Verbose. Default 0" << endl; @@ -326,12 +290,144 @@ } +void write_lines_to_file(string& filename1, string& filename2){ + + // Create output file name + string output = path; + vector<string> tokens; + + if (filename1 == filename2){ + // *nix file paths + if (filename2.find("/") < filename2.length() || filename2.substr(0, 1) == ("/")){ + tokenize(filename2, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename2, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } + output.append(".lines"); + }else{ + // *nix file paths + if (filename1.find("/") < filename1.length() || filename1.substr(0, 1) == ("/")){ + tokenize(filename1, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename1, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } + output.append("-"); + // *nix file paths + if (filename2.find("/") < filename2.length() || filename2.substr(0, 1) == ("/")){ + tokenize(filename2, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename2, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } + output.append(".lines"); + } + + + // File to write to + ofstream out; + out.open (output.c_str()); + + if(!out.good()){ + cout << "Couldn't write lines to file " << output << endl << endl; + exit(1); + }else{ + cout << "Writing lines to file " << output << endl << endl; + } + + out << "# Lens type:\t\t\t" << lens_type << endl; + out << "# Size factor:\t\t\t" << sizefactor << endl; + out << "# Crop factor:\t\t\t" << cropFactor << endl; + out << "# Focal length (mm):\t\t" << focal_length << endl; + out << "# Focal length (pixels):\t" << focal_length_pixels << endl; + + for (int i = 0; i < lines.size(); i++){ + for (int j = 0; j < lines[i].size(); j++){ + out << i+1 << "\t" << lines[i][j]->x << ","<< lines[i][j]->y << endl; + } + } + out.close(); + +} + +void parse_lines_file(string& lines_file){ + + ifstream is(lines_file.c_str()); + + // Check to make sure the stream is ok + if(!is.good()){ + cout << "Cannot open file "<< lines_file << endl << endl; + exit(1); + }else{ + cout << "Reading input file " << lines_file << "..." << endl << endl; + } + + string line; + char ch[150]; + unsigned int l,lt,x,y; + float fl,sf,flp,flmm,cf; + + // Get line from stream + while(getline(is,line)){ + + // copy the string to a character array + strcpy(ch, line.c_str()); + + if(sscanf(ch, "%d %d%*c%d", &l,&x,&y) == 3){ + + if(lines.size() < l){ + vector<vigra::Point2D> tmp; + lines.push_back(tmp); + } + lines[l-1].push_back(vigra::Point2D((int)x,(int)y)); + //cout << "Added pixel " << x << "," << y << " to line " << l << endl; + + }else if (sscanf(ch, "# Focal length (pixels): %e", &fl) == 1){ + focal_length_pixels = fl; + cout << "Found focal length (pixels):\t" << fl << endl; + }else if(sscanf(ch, "# Lens type: %d", <) == 1){ + cout << "Found lens type:\t\t" << lt << endl; + lens_type = lt; + }else if(sscanf(ch, "# Size factor: %f", &sf) == 1){ + cout << "Found size factor:\t\t" << sf << endl; + sizefactor = sf; + }else if(sscanf(ch, "# Crop factor: %f", &cf) == 1){ + cout << "Found crop factor:\t\t" << cf << endl; + cropFactor = cf; + }else if(sscanf(ch, "# Focal length (mm): %f", &flmm) == 1){ + cout << "Found focal length (mm):\t" << flmm << endl; + focal_length = flmm; + }else if(sscanf(ch, "# Focal length (pixels): %f", &flp) == 1){ + cout << "Found focal length (pixels):\t\t" << flp << endl; + focal_length_pixels = flp; + } + } + is.close(); + cout << endl; + + for (int i = 0; i < lines.size(); i++){ + cout << "Found line " << i+1 << ". Pixels:\t\t" << lines[i].size() << endl; + } + cout << endl; + +} + int main(int argc, const char* argv[]){ + cout << endl << "Lens calibration tool" << endl; + cout << endl << "Version " << VERSION << endl << endl; + unsigned int i = 1; unsigned int pto_image = 0; unsigned int cps_per_line = 10; - string pto_file = (""),output_pto = (""); + string pto_file = (""),output_pto = (""),lines_file = (""); vector<string> images,pto_file_top,pto_file_cps,pto_file_end; // Deal with arguments @@ -350,11 +446,13 @@ case 'h' : {usage();} case 'o' : {path = argv[i]; break;} case 'p' : {pto_file = argv[i]; break;} + case 'j' : {lines_file = argv[i]; break;} case 'i' : {pto_image = atoi(argv[i]); break;} //case 'c' : {cps_per_line = atoi(argv[i]); break;} //case 'f' : {format = argv[i]; break;} case 'e' : {detector = atoi(argv[i]); break;} - case 'g' : {gap_limit = atoi(argv[i]); break;} + case 'g' : {gap_limit = atoi(argv[i]); break;} + case 'x' : {lens_model = atoi(argv[i]); break;} case 't' : {optimise_centre = atoi(argv[i]); break;} case 'v' : {verbose = atoi(argv[i]); break;} case 'd' : {resize_dimension = atoi(argv[i]); break;} @@ -396,35 +494,55 @@ } } + if (lines_file != ("")){ + parse_lines_file(lines_file); + } + //images.push_back("/home/tnugent/src/gsoc2009_lenscalibration/src/lens_calibrate/dsc_0040.jpg"); + //images.push_back("/home/tnugent/src/gsoc2009_lenscalibration/src/lens_calibrate/dsc_0163.jpg"); - if (!images.size()){ + if (!images.size() && lines.size() == 0){ //cout << "No images provided!" << endl << endl; usage(); } - cout << endl << "Lens calibration tool" << endl; - cout << endl << "Version " << VERSION << endl << endl; - - for(i = 0; i < images.size();i++){ - + int plotted = 0; + for(i = 0; i < images.size();i++){ ifstream ifile(images[i].c_str()); if (!ifile){ cout << "File " << images[i] << " doesn't exist." << endl << endl; exit(1); } cout << "Processing image " << images[i].c_str() << endl << endl; - process_image(images[i]); + process_image(images[i],plotted); } - cout << "Found "<< lines.size() <<" lines"<<endl; + cout << "Found "<< lines.size() <<" lines."<< endl << endl; int n_params = 2; if (lens_type == 2) ++n_params; - if(optimise_centre) n_params += 2; + if (optimise_centre) n_params += 2; - if (lines.size() >= n_params ) map_points(); - else{ + /* + for (int i = 0; i < lines.size(); i++){ + for (int j = 0; j < lines[i].size(); j++){ + cout << "_" << i << "," << lines[i][j]->x << "," << lines[i][j]->y << endl; + } + } + cout << endl; + */ + + if (lines.size() >= n_params ){ + // Write lines to output file + if (images.size()){ + write_lines_to_file(images[0],images[images.size()-1]); + }else{ + string tmp = ("all_lines.txt"); + write_lines_to_file(tmp,tmp); + } + // Map points and optimise parameters + map_points(); + }else{ cout << "Not enough lines to fit "<< n_params <<" parameters."<<endl; return 3; } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-27 14:56:20 UTC (rev 4116) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-27 16:20:44 UTC (rev 4117) @@ -69,16 +69,29 @@ double x_centre = 0; double y_centre = 0; - if (lens_type == 2){ - if(optimise_centre){ + + if (lens_model == 2){ + if(optimise_centre){ x_centre = p[3]; - y_centre = p[4]; - } + y_centre = p[4]; + } + }else if (lens_model == 3){ + if(optimise_centre){ + x_centre = p[1]; + y_centre = p[2]; + } }else{ - if(optimise_centre){ - x_centre = p[2]; - y_centre = p[3]; - } + if (lens_type == 2){ + if(optimise_centre){ + x_centre = p[3]; + y_centre = p[4]; + } + }else{ + if(optimise_centre){ + x_centre = p[2]; + y_centre = p[3]; + } + } } for (unsigned int l = 0; l < lines.size(); l++){ @@ -109,7 +122,6 @@ //cout << "(x,y)\t(" << x_point << "," << y_point << ")" << endl; // r - distance of a point from the center of projection, in pixels - //double r = PointPointDist(x_point,y_point,x_centre,y_centre); double r = sqrt(x_point * x_point + y_point * y_point); // u = r / f; @@ -117,19 +129,37 @@ // R - distance of a point from the center of projection, // corrected for barrel distortion, unitless, or radians - // (1 - p2 - p4) is for normalisation - // p2 = p[0], p4 = [1] - double R = (1 - p[0] - p[1]) * u + p[0] * (u*u) + p[1] * (u*u*u*u); + double R = 0; + + if (lens_model == 2){ + + // Panotools + // R = a * u^4 + b * u^3 + c * u^2 + R = p[0] * (u*u*u*u) + p[1] * (u*u*u) + p[2] * (u*u); + + }else if (lens_model == 3){ + + // Universal fisheye + //R = k * 2 * tan(A/2) + (1 - k) * 2 * sin(A/2) + //R = p[0] * 2 * tan(A/2) + (1 - p[0]) * 2 * sin(A/2); + + }else{ + // Default + //R = u + p2 * u^2 + p4 * u^4 + // (1 - p2 - p4) is for normalisation + // p2 = p[0], p4 = [1] + R = (1 - p[0] - p[1]) * u + p[0] * (u*u) + p[1] * (u*u*u*u); + } // a - angular distance of a point from the center of projection, in radians double a; if (lens_type == 2){ // k - equal-area type fisheye design parameter, initial value of 2 - double k = p[3]; + double k = p[2]; a = k * asin( R / k ); /* - cout << "k:\t" << p[3] << endl; + cout << "k:\t" << p[2] << endl; cout << "r/k:\t" << R/k << endl; cout << "asin(r/k):\t" << asin( R / k ) << endl; cout << "a:\t" << a << endl; @@ -177,7 +207,7 @@ cout << norm.z << endl << endl; */ - // Comput straigthness error + // Compute straigthness error double ssq = 0; for(unsigned int i = 1; i < npnts - 1; i++){ // Add square of dot product of that point with norm @@ -199,61 +229,130 @@ void map_points(){ + if (lens_model == 2){ + cout << "Panotools lens model" << endl; + }else if (lens_model == 3){ + cout << "Universal fisheye lens model" << endl; + }else{ + cout << "Default lens model" << endl; + } + int iterations = 1000; double info[LM_INFO_SZ]; // Set up initial parameters int m = 5; double * p = new double[m]; - - //p[0] = focal_length_pixels; - p[0] = 0; // p2 - p[1] = 0; // p4 - if (lens_type == 2){ - p[2] = 2; // k - if(optimise_centre){ - p[3] = 0; // x_center; - p[4] = 0; // y_center; - }else{ - m = 3; - } - }else{ - if(optimise_centre){ - m = 4; - p[2] = 0; // x_center; - p[3] = 0; // y_center; - }else{ - m = 2; - } - } - // Set up measurement vector int n = lines.size(); double * x = new double[n]; for (unsigned int i = 0; i < n; i++){ x[i] = 0; + } + + if(lens_model == 2){ + + // Panotools + // R = a * u^4 + b * u^3 + c * u^2 + + // What should starting values be? + p[0] = 1; // a + p[1] = 1; // b + p[2] = 1; // c + m = 3; + + if(optimise_centre){ + p[3] = 0; // x_center; + p[4] = 0; // y_center; + m = 5; + } + + }else if (lens_model == 3){ + + // Universal fisheye + // R = k * 2 * tan(A/2) + (1 - k) * 2 * sin(A/2) + + p[0] = 0; // k + m = 1; + + if(optimise_centre){ + p[1] = 0; // x_center; + p[2] = 0; // y_center; + m = 3; + } + + }else{ + + p[0] = 0; // p2 + p[1] = 0; // p4 + + if (lens_type == 2){ + p[2] = 2; // k + if(optimise_centre){ + p[3] = 0; // x_center; + p[4] = 0; // y_center; + }else{ + m = 3; + } + }else{ + if(optimise_centre){ + m = 4; + p[2] = 0; // x_center; + p[3] = 0; // y_center; + }else{ + m = 2; + } + } } + + int ret = dlevmar_dif(&Mapto3d, &visf, p, x, m, n, iterations, NULL, info, NULL, NULL, NULL); printf("\nLevenberg-Marquardt returned in %g iter, reason %g\nSolution:\n", info[5], info[6]); - //cout << "Focal length:\t\t" << p[0] << endl; - cout << "p2:\t\t\t" << p[0] << endl; - cout << "p4:\t\t\t" << p[1] << endl; + + if(lens_model == 2){ - if (lens_type == 2){ - cout << "k:\t\t\t" << p[2] << endl; - if(optimise_centre){ + cout << "a:\t\t\t" << p[0] << endl; + cout << "b:\t\t\t" << p[1] << endl; + cout << "c:\t\t\t" << p[2] << endl; + + if(optimise_centre){ cout << "x centre:\t\t" << p[3] << endl; - cout << "y centre\t\t" << p[4] << endl; - } - }else{ + cout << "y centre\t\t" << p[4] << endl; + } + + + }else if(lens_model == 3){ + + cout << "k:\t\t\t" << p[0] << endl; + if(optimise_centre){ - cout << "x centre:\t\t" << p[2] << endl; - cout << "y centre\t\t" << p[3] << endl; + cout << "x centre:\t\t" << p[1] << endl; + cout << "y centre\t\t" << p[2] << endl; } + + }else{ + + cout << "p2:\t\t\t" << p[0] << endl; + cout << "p4:\t\t\t" << p[1] << endl; + + if (lens_type == 2){ + cout << "k:\t\t\t" << p[2] << endl; + if(optimise_centre){ + cout << "x centre:\t\t" << p[3] << endl; + cout << "y centre\t\t" << p[4] << endl; + } + }else{ + if(optimise_centre){ + cout << "x centre:\t\t" << p[2] << endl; + cout << "y centre\t\t" << p[3] << endl; + } + } } + + for (unsigned int i = 0; i < n; i++){ cout << "Line " << i+1 << " error:\t\t" << line_errors[i] << endl; } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-27 14:56:20 UTC (rev 4116) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-27 16:20:44 UTC (rev 4117) @@ -27,7 +27,6 @@ #include <exiv2/image.hpp> #endif - #include "vigra/impex.hxx" #include "vigra/stdimage.hxx" #include "vigra/edgedetection.hxx" @@ -38,6 +37,7 @@ #include "vigra/diff2d.hxx" #include <vigra/rgbvalue.hxx> #include <vigra/utilities.hxx> +#include <sys/stat.h> #include "Globals.h" #include "ProcessImage.h" #include "MapPoints.h" @@ -68,6 +68,47 @@ return (i->x<j->x); } +bool fileexists(string strFilename) { + + struct stat stFileInfo; + bool blnReturn; + int intStat; + + // Attempt to get the file attributes + intStat = stat(strFilename.c_str(),&stFileInfo); + if(intStat == 0) { + + blnReturn = true; + }else{ + + blnReturn = false; + } + + return(blnReturn); +} + +void tokenize(const string& str, vector<string>& tokens, const string& delimiters = " "){ + + // Skip delimiters at beginning + string::size_type lastPos = str.find_first_not_of(delimiters, 0); + + // Find first non-delimiter + string::size_type pos = str.find_first_of(delimiters, lastPos); + + while (string::npos != pos || string::npos != lastPos){ + + // Found a token, add it to the vector + tokens.push_back(str.substr(lastPos, pos - lastPos)); + + // Skip delimiters. Note the not_of + lastPos = str.find_first_not_of(delimiters, pos); + + // Find next non-delimiter + pos = str.find_first_of(delimiters, lastPos); + } + +} + void sort_inliers(vector<Point2D>& inliers){ unsigned int top = 0; @@ -94,14 +135,14 @@ } } -void plot_inliers(BImage& image, vector<Point2D>& inliers, int i){ +void plot_inliers(string& filename, BImage& image, vector<Point2D>& inliers, int i){ vigra::BRGBImage tmp(image.width(),image.height()); vigra::initImage(srcIterRange(tmp.upperLeft(), tmp.upperLeft() + vigra::Diff2D(image.width(),image.height())), RGB(255,255,255) ); - cout << "Plotting line " << i << ". Pixels:\t" << inliers.size() << endl << endl; + for (unsigned int il = 0; il < inliers.size(); il++){ /* @@ -123,16 +164,29 @@ } if (generate_images){ - // Export slice to file + string output = path; - output.append("inliers"); + vector<string> tokens; + + // *nix file paths + if (filename.find("/") < filename.length() || filename.substr(0, 1) == ("/")){ + tokenize(filename, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } + output.append("_line_"); stringstream ii; ii << i; output.append(ii.str()); - //output.append("inliers"); - output.append(".jpg"); - exportImage(srcImageRange(tmp), ImageExportInfo(output.c_str()).setPixelType("UINT8")); - //exportImage(srcImageRange(tmp), output.c_str().setPixelType("UINT8")); + output.append(format); + + if(!fileexists(output)){ + cout << "Plotting line " << i << ". Pixels:\t" << inliers.size() << endl; + exportImage(srcImageRange(tmp), ImageExportInfo(output.c_str()).setPixelType("UINT8")); + } } } @@ -146,11 +200,14 @@ queryPt = annAllocPt(dim,0); // Allocate query point srand(time(0)); int queryidx = rand() % coords.size(); + queryPt[0] = coords[queryidx]->x; queryPt[1] = coords[queryidx]->y; double orientation_scale = 1; double orientation_threshold = 0.2; + // Set high to disable + orientation_threshold = 1000; // Add direction as 3rd dimension double first_o; @@ -353,7 +410,7 @@ } } -void nuke_corners(BImage& image, FImage& corners, string& file){ +void nuke_corners(BImage& image, FImage& corners, string& filename){ for (unsigned int h = 0; h < corners.height(); h++){ for (unsigned int w = 0; w < corners.width(); w++){ @@ -388,10 +445,8 @@ //cout << value[0] << "\t(" << w << "," << h << ")" << endl; } } - } + } - - /* // Smooth with hourglass filter FVector2Image gradient(image.width(),image.height()); @@ -418,22 +473,29 @@ if (generate_images){ - // Create output file name string output = path; - //if (file.substr(file.length()-4,1) == (".")){ - // output.append(file.substr(0,file.length()-4)); - //}else{ - // output.append(file.substr(0,file.length()-4)); - //} - //output.append("_no_corners"); - output.append("edges_minus_corners"); + vector<string> tokens; + + // *nix file paths + if (filename.find("/") < filename.length() || filename.substr(0, 1) == ("/")){ + tokenize(filename, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } + output.append("_edges_minus_corners"); output.append(format); - cout << "Writing " << output << endl << endl; - exportImage(srcImageRange(image), ImageExportInfo(output.c_str()).setPixelType("UINT8")); + + if(!fileexists(output)){ + cout << "Writing " << output << endl << endl; + exportImage(srcImageRange(image), ImageExportInfo(output.c_str()).setPixelType("UINT8")); + } } } -void detect_edge(BImage& image, string& file, string& path, string& format, BImage& edge_image){ +void detect_edge(BImage& image, string& filename, string& path, string& format, BImage& edge_image){ try{ // Paint output image white @@ -452,17 +514,20 @@ } if (generate_images){ - // Create output file name + string output = path; - - //if (file.substr(file.length()-4,1) == (".")){ - // output.append(file.substr(0,file.length()-4)); - //}else{ - // output.append(file.substr(0,file.length()-4)); - //} - //output.append("_threshold"); - output.append("edges_threshold_"); - + vector<string> tokens; + + // *nix file paths + if (filename.find("/") < filename.length() || filename.substr(0, 1) == ("/")){ + tokenize(filename, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } + output.append("_edges_threshold_"); stringstream dt; dt << threshold; output.append(dt.str()); @@ -472,8 +537,10 @@ output.append(ds.str()); output.append(format); - cout << "Writing " << output << endl; - exportImage(srcImageRange(edge_image), output.c_str()); + if(!fileexists(output)){ + cout << "Writing " << output << endl; + exportImage(srcImageRange(edge_image), output.c_str()); + } } } catch (StdException & e){ @@ -789,8 +856,21 @@ } } -void process_image(string& filename){ +bool compare_line_length(vector<vigra::Point2D> l1, vector<vigra::Point2D> l2){ + // Compare by line length + //return(line_length_squared(l1[0].x,l1[0].y,l1[l1.size()-1].x,l1[l1.size()-1].y) > line_length_squared(l2[0].x,l2[0].y,l2[l2.size()-1].x,l2[l2.size()-1].y)); + + // Compare by number of pixels + return(l1.size() > l2.size()); +} + +void sort_lines_by_length(){ + sort(lines.begin(), lines.end(), compare_line_length); +} + +void process_image(string& filename, int& plotted){ + ImageImportInfo info(filename.c_str()); UInt16RGBImage in(info.width(), info.height()); @@ -850,15 +930,27 @@ find_ann(coords, edgeness, inliers, good_lines); if(inliers.size()){ sort_inliers(inliers); - plot_inliers(image,inliers,good_lines); lines.push_back(inliers); inliers.clear(); } if(verbose) cout << "Remaining coords:\t" << coords.size() << "\t(" << 100*((double)coords.size()/intital_coords_size) << " %)" << endl << endl; } + + // Sort lines by distance between first and last point or number of pixels + sort_lines_by_length(); + + + if (good_lines == 0){ cout << "No lines found!" << endl; + }else{ + // Create image for each line + for (int i = plotted; i < lines.size(); i++){ + plot_inliers(filename, image, lines[i],i+1); + plotted++; + } + cout << endl; } } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-27 14:56:20 UTC (rev 4116) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-27 16:20:44 UTC (rev 4117) @@ -7,13 +7,17 @@ double line_length_squared(int, int, int, int); bool compare_xy (const vigra::Point2D,const vigra::Point2D); bool compare_yx (const vigra::Point2D,const vigra::Point2D); +bool fileexists(std::string); +void tokenize(const std::string&, std::vector<std::string>&, const std::string&); void resize_image(vigra::UInt16RGBImage&, int&, int&); void find_ann(std::vector<vigra::Point2D>&, vigra::FVector2Image&, unsigned int&); void sort_inliers(std::vector<vigra::Point2D>&); -void plot_inliers(vigra::BImage& image, std::vector<vigra::Point2D>&, int); +void plot_inliers(std::string&, vigra::BImage& image, std::vector<vigra::Point2D>&, int); void extract_coords(vigra::BImage&, std::vector<vigra::Point2D>&); void nuke_corners(vigra::BImage&, vigra::FImage&, std::string&); void detect_edge(vigra::BImage&, std::string&, std::string&, std::string&, vigra::BImage&); -void process_image(std::string&); +void process_image(std::string&,int&); +void sort_lines_by_length(); +bool compare_line_length(std::vector<vigra::Point2D>, std::vector<vigra::Point2D>); #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-27 22:59:55
|
Revision: 4119 http://hugin.svn.sourceforge.net/hugin/?rev=4119&view=rev Author: blimbo Date: 2009-07-27 22:59:48 +0000 (Mon, 27 Jul 2009) Log Message: ----------- Fixed bug reading/writing to file. No longer use random starting point in ANN search. Other bug fixes Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-27 20:51:48 UTC (rev 4118) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-27 22:59:48 UTC (rev 4119) @@ -18,6 +18,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include <string.h> #include <fstream> #include <vector> #include <string> @@ -347,7 +348,8 @@ out << "# Crop factor:\t\t\t" << cropFactor << endl; out << "# Focal length (mm):\t\t" << focal_length << endl; out << "# Focal length (pixels):\t" << focal_length_pixels << endl; - + out << "# Original width:\t\t" << original_width << endl; + out << "# Original height:\t\t" << original_height << endl; for (int i = 0; i < lines.size(); i++){ for (int j = 0; j < lines[i].size(); j++){ out << i+1 << "\t" << lines[i][j]->x << ","<< lines[i][j]->y << endl; @@ -371,7 +373,7 @@ string line; char ch[150]; - unsigned int l,lt,x,y; + unsigned int l,lt,x,y,ow,oh; float fl,sf,flp,flmm,cf; // Get line from stream @@ -407,6 +409,12 @@ }else if(sscanf(ch, "# Focal length (pixels): %f", &flp) == 1){ cout << "Found focal length (pixels):\t\t" << flp << endl; focal_length_pixels = flp; + }else if(sscanf(ch, "# Original height: %d", &oh) == 1){ + cout << "Found original height:\t\t" << oh << endl; + original_height = oh; + }else if(sscanf(ch, "# Original width: %d", &ow) == 1){ + cout << "Found original width:\t\t" << ow << endl; + original_width = ow; } } is.close(); @@ -494,6 +502,8 @@ } } + //lines_file= "/home/tnugent/src/gsoc2009_lenscalibration/src/lens_calibrate/output/dsc_0040.lines"; + if (lines_file != ("")){ parse_lines_file(lines_file); } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-27 20:51:48 UTC (rev 4118) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-27 22:59:48 UTC (rev 4119) @@ -22,6 +22,7 @@ #include <iostream> #include <stdio.h> #include <math.h> +#include <cstdlib> #include <levmar/lm.h> #include "Globals.h" @@ -94,10 +95,11 @@ } } - for (unsigned int l = 0; l < lines.size(); l++){ - - //cout << "Optimising line " << l+1 << "..." << endl; + for (unsigned int l = 0; l < lines.size(); l++){ + int npnts = lines[l].size(); + + //cout << "Optimising line " << l+1 << " - points: " << npnts << endl; //XYZPoint mapped_point[lines[current_line].size()]; XYZPoint * mapped_point = new XYZPoint[npnts]; @@ -135,7 +137,7 @@ // Panotools // R = a * u^4 + b * u^3 + c * u^2 - R = p[0] * (u*u*u*u) + p[1] * (u*u*u) + p[2] * (u*u); + //R = p[0] * (u*u*u*u) + p[1] * (u*u*u) + p[2] * (u*u); }else if (lens_model == 3){ @@ -144,6 +146,10 @@ //R = p[0] * 2 * tan(A/2) + (1 - p[0]) * 2 * sin(A/2); }else{ + + //cout << "p2:\t" << p[0] << endl; + //cout << "p4:\t" << p[1] << endl; + // Default //R = u + p2 * u^2 + p4 * u^4 // (1 - p2 - p4) is for normalisation @@ -184,6 +190,10 @@ mapped_point[i] = Point; /* + cout << "x:\t" << lines[l][i]->x << endl; + cout << "y:\t" << lines[l][i]->y << endl; + cout << "x_point:\t" << x_point << endl; + cout << "y_point:\t" << y_point << endl; cout << "r:\t" << r << endl; cout << "u:\t" << u << endl; cout << "R:\t" << R << endl; @@ -193,8 +203,7 @@ double check = (Point.x*Point.x + Point.y*Point.y + Point.z*Point.z); cout << "Unit vector?\t" << check << endl; cout << l+1 << "\t" << i << "\t(" << Point.x << "," << Point.y << "," << Point.z << ")" << endl; - */ - + */ } // Vector cross product of the end points - this is the normal to the estimated plane @@ -306,10 +315,14 @@ } } - - int ret = dlevmar_dif(&Mapto3d, &visf, p, x, m, n, iterations, NULL, info, NULL, NULL, NULL); + /* + cout << "m:\t\t\t" << m << endl; + cout << "n:\t\t\t" << n << endl; + cout << "iterations:\t\t" << iterations << endl; + */ + printf("\nLevenberg-Marquardt returned in %g iter, reason %g\nSolution:\n", info[5], info[6]); if(lens_model == 2){ Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-27 20:51:48 UTC (rev 4118) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-27 22:59:48 UTC (rev 4119) @@ -52,12 +52,10 @@ typedef vigra::BRGBImage::PixelType RGB; -double line_length_squared(int x1,int y1,int x2,int y2){ - +double line_length_squared(int& x1, int& y1, int& x2, int& y2){ int d1 = x1 - x2; int d2 = y1 - y2; return(d1*d1+d2*d2); - } bool compare_yx (const vigra::Point2D i,const vigra::Point2D j){ @@ -198,9 +196,9 @@ ANNpoint queryPt; // Query point queryPt = annAllocPt(dim,0); // Allocate query point - srand(time(0)); - int queryidx = rand() % coords.size(); - + //srand(time(0)); + //int queryidx = rand() % coords.size(); + int queryidx = 0; queryPt[0] = coords[queryidx]->x; queryPt[1] = coords[queryidx]->y; @@ -234,8 +232,10 @@ int cont = 1; int rev = 0; double previous_length = 0; - int first_line_end_x = first_x, first_line_end_y = first_y; - + //int first_line_end_x = first_x, first_line_end_y = first_y; + int first_line_end_x = -1, first_line_end_y = -1; + int second_line_end_x = -1, second_line_end_y = -1; + if(verbose) cout << "Query Pixel\tNN Pixel\tIndex\tDistance\tOrientation diff" << endl; while (cont){ @@ -280,8 +280,11 @@ //kdTree = new ANNkd_tree(dataPts,nPts,dim); kdTree->annkSearch(queryPt,k,nnIdx,dists,eps); - dists[0] = sqrt(dists[0]); - double this_length = line_length_squared(first_x,first_y,close_neighbors[nnIdx[0]]->x,close_neighbors[nnIdx[0]]->y); + dists[0] = sqrt(dists[0]); + int x2 = close_neighbors[nnIdx[0]]->x; + int y2 = close_neighbors[nnIdx[0]]->y; + + double this_length = line_length_squared(first_x,first_y,x2,y2); double orientation_diff = abs(queryPt[2] - dataPts[nnIdx[0]][2]); //double orientation_diff = abs(first_o - dataPts[nnIdx[0]][2]); @@ -294,8 +297,18 @@ if (rev == 0){ if(verbose) cout << "End of line reached. Returning to inital query pixel..." << endl; - first_line_end_x = close_neighbors[nnIdx[0]]->x; - first_line_end_y = close_neighbors[nnIdx[0]]->y; + if(verbose) cout << "Setting line end point to " << close_neighbors[nnIdx[0]]->x << "," << close_neighbors[nnIdx[0]]->y << endl; + + if (first_line_end_x == -1 && first_line_end_y == -1){ + first_line_end_x = close_neighbors[nnIdx[0]]->x; + first_line_end_y = close_neighbors[nnIdx[0]]->y; + }else{ + second_line_end_x = close_neighbors[nnIdx[0]]->x; + second_line_end_y = close_neighbors[nnIdx[0]]->y; + } + + //first_line_end_x = close_neighbors[nnIdx[0]]->x; + //first_line_end_y = close_neighbors[nnIdx[0]]->y; queryPt[0] = first_x; queryPt[1] = first_y; @@ -356,8 +369,20 @@ if (rev == 0){ if(verbose) cout << "No more pixels in this region. Returning to inital query pixel..." << endl; if (inliers.size()){ - first_line_end_x = inliers[inliers.size()-1]->x; - first_line_end_y = inliers[inliers.size()-1]->y; + + //if(verbose) cout << "Setting line end point to " << inliers[inliers.size()-1]->x << "," << inliers[inliers.size()-1]->y << endl; + + + if (first_line_end_x == -1 && first_line_end_y == -1){ + first_line_end_x = inliers[inliers.size()-1]->x; + first_line_end_y = inliers[inliers.size()-1]->y; + }else{ + second_line_end_x = inliers[inliers.size()-1]->x; + second_line_end_y = inliers[inliers.size()-1]->y; + } + + //first_line_end_x = inliers[inliers.size()-1]->x; + //first_line_end_y = inliers[inliers.size()-1]->y; queryPt[0] = first_x; queryPt[1] = first_y; @@ -367,10 +392,32 @@ rev = 1; }else{ + + //if(verbose) cout << "Setting line end point to " << queryPt[0] << "," << queryPt[1] << endl; + + if (first_line_end_x == -1 && first_line_end_y == -1){ + first_line_end_x = queryPt[0]; + first_line_end_y = queryPt[1]; + }else{ + second_line_end_x = queryPt[0]; + second_line_end_y = queryPt[1]; + } + if(verbose) cout << "No more pixels." << endl; cont = 0; } }else{ + + //if(verbose) cout << "Setting line end point to " << queryPt[0] << "," << queryPt[1] << endl; + + if (first_line_end_x == -1 && first_line_end_y == -1){ + first_line_end_x = queryPt[0]; + first_line_end_y = queryPt[1]; + }else{ + second_line_end_x = queryPt[0]; + second_line_end_y = queryPt[1]; + } + if(verbose) cout << "No more pixels in this region." << endl; cont = 0; } @@ -379,13 +426,20 @@ } annClose(); - double length = line_length_squared(first_line_end_x, first_line_end_y,inliers[inliers.size()-1]->x,inliers[inliers.size()-1]->y); + //int x2 = inliers[inliers.size()-1]->x; + //int y2 = inliers[inliers.size()-1]->y; + //double length_sq = line_length_squared(first_line_end_x, first_line_end_y,x2,y2); + double length_sq = line_length_squared(first_line_end_x,first_line_end_y,second_line_end_x,second_line_end_y); - if(verbose) cout << endl << "Measuring distance from " << first_line_end_x << "," << first_line_end_y << " to " << inliers[inliers.size()-1]->x << "," << - inliers[inliers.size()-1]->y <<endl; - if(verbose) cout << "Length squared:\t" << length << "\t"; + if(verbose) cout << endl << "Measuring distance from " << first_line_end_x << "," << first_line_end_y << " to " << second_line_end_x << "," << + second_line_end_y <<endl; + + //if(verbose) cout << endl << "Measuring distance from " << first_line_end_x << "," << first_line_end_y << " to " << inliers[inliers.size()-1]->x << "," << + //inliers[inliers.size()-1]->y <<endl; + + if(verbose) cout << "Length squared:\t" << length_sq << "\t"; - if(length >= min_line_length_squared){ + if(length_sq >= min_line_length_squared){ good_lines++; if(verbose) cout << "Above theshold (" << min_line_length_squared << ")" << endl; }else{ Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-27 20:51:48 UTC (rev 4118) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-27 22:59:48 UTC (rev 4119) @@ -4,7 +4,7 @@ #include "vigra/impex.hxx" #include "vigra/diff2d.hxx" -double line_length_squared(int, int, int, int); +double line_length_squared(int&, int&, int&, int&); bool compare_xy (const vigra::Point2D,const vigra::Point2D); bool compare_yx (const vigra::Point2D,const vigra::Point2D); bool fileexists(std::string); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-28 16:49:14
|
Revision: 4121 http://hugin.svn.sourceforge.net/hugin/?rev=4121&view=rev Author: blimbo Date: 2009-07-28 16:49:03 +0000 (Tue, 28 Jul 2009) Log Message: ----------- Small bugfixes, compiler warnings etc. Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-28 05:29:08 UTC (rev 4120) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-28 16:49:03 UTC (rev 4121) @@ -361,8 +361,7 @@ void parse_lines_file(string& lines_file){ - ifstream is(lines_file.c_str()); - + ifstream is(lines_file.c_str()); // Check to make sure the stream is ok if(!is.good()){ cout << "Cannot open file "<< lines_file << endl << endl; @@ -378,24 +377,27 @@ // Get line from stream while(getline(is,line)){ - // copy the string to a character array - strcpy(ch, line.c_str()); - - if(sscanf(ch, "%d %d%*c%d", &l,&x,&y) == 3){ - + strcpy(ch, line.c_str()); + if(sscanf(ch, "%d %d%*c%d", &l,&x,&y) == 3){ if(lines.size() < l){ vector<vigra::Point2D> tmp; lines.push_back(tmp); } lines[l-1].push_back(vigra::Point2D((int)x,(int)y)); - //cout << "Added pixel " << x << "," << y << " to line " << l << endl; - }else if (sscanf(ch, "# Focal length (pixels): %e", &fl) == 1){ focal_length_pixels = fl; cout << "Found focal length (pixels):\t" << fl << endl; }else if(sscanf(ch, "# Lens type: %d", <) == 1){ - cout << "Found lens type:\t\t" << lt << endl; + cout << "Found lens type:\t\t"; + if (lt == 2){ + cout << "Equal-area fisheye"; + }else if(lt == 3){ + cout << "Equal-angle fisheye"; + }else{ + cout << "Rectilinear"; + } + cout << endl; lens_type = lt; }else if(sscanf(ch, "# Size factor: %f", &sf) == 1){ cout << "Found size factor:\t\t" << sf << endl; @@ -419,12 +421,10 @@ } is.close(); cout << endl; - for (int i = 0; i < lines.size(); i++){ cout << "Found line " << i+1 << ". Pixels:\t\t" << lines[i].size() << endl; } cout << endl; - } int main(int argc, const char* argv[]){ @@ -546,9 +546,6 @@ // Write lines to output file if (images.size()){ write_lines_to_file(images[0],images[images.size()-1]); - }else{ - string tmp = ("all_lines.txt"); - write_lines_to_file(tmp,tmp); } // Map points and optimise parameters map_points(); Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-28 05:29:08 UTC (rev 4120) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-28 16:49:03 UTC (rev 4121) @@ -239,11 +239,11 @@ void map_points(){ if (lens_model == 2){ - cout << "Panotools lens model" << endl; + cout << "Using Panotools lens model" << endl; }else if (lens_model == 3){ - cout << "Universal fisheye lens model" << endl; + cout << "Using universal fisheye lens model" << endl; }else{ - cout << "Default lens model" << endl; + cout << "Using default lens model" << endl; } int iterations = 1000; @@ -323,7 +323,7 @@ cout << "iterations:\t\t" << iterations << endl; */ - printf("\nLevenberg-Marquardt returned in %g iter, reason %g\nSolution:\n", info[5], info[6]); + printf("\nLevenberg-Marquardt returned in %g iterations, reason %g\nSolution:\n", info[5], info[6]); if(lens_model == 2){ Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-28 05:29:08 UTC (rev 4120) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-28 16:49:03 UTC (rev 4121) @@ -396,11 +396,11 @@ //if(verbose) cout << "Setting line end point to " << queryPt[0] << "," << queryPt[1] << endl; if (first_line_end_x == -1 && first_line_end_y == -1){ - first_line_end_x = queryPt[0]; - first_line_end_y = queryPt[1]; + first_line_end_x = (int)queryPt[0]; + first_line_end_y = (int)queryPt[1]; }else{ - second_line_end_x = queryPt[0]; - second_line_end_y = queryPt[1]; + second_line_end_x = (int)queryPt[0]; + second_line_end_y = (int)queryPt[1]; } if(verbose) cout << "No more pixels." << endl; @@ -411,11 +411,11 @@ //if(verbose) cout << "Setting line end point to " << queryPt[0] << "," << queryPt[1] << endl; if (first_line_end_x == -1 && first_line_end_y == -1){ - first_line_end_x = queryPt[0]; - first_line_end_y = queryPt[1]; + first_line_end_x = (int)queryPt[0]; + first_line_end_y = (int)queryPt[1]; }else{ - second_line_end_x = queryPt[0]; - second_line_end_y = queryPt[1]; + second_line_end_x = (int)queryPt[0]; + second_line_end_y = (int)queryPt[1]; } if(verbose) cout << "No more pixels in this region." << endl; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-28 05:29:08 UTC (rev 4120) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-28 16:49:03 UTC (rev 4121) @@ -16,7 +16,7 @@ void extract_coords(vigra::BImage&, std::vector<vigra::Point2D>&); void nuke_corners(vigra::BImage&, vigra::FImage&, std::string&); void detect_edge(vigra::BImage&, std::string&, std::string&, std::string&, vigra::BImage&); -void process_image(std::string&,int&); +void process_image(std::string&, int&); void sort_lines_by_length(); bool compare_line_length(std::vector<vigra::Point2D>, std::vector<vigra::Point2D>); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-29 23:05:19
|
Revision: 4126 http://hugin.svn.sourceforge.net/hugin/?rev=4126&view=rev Author: blimbo Date: 2009-07-29 23:05:12 +0000 (Wed, 29 Jul 2009) Log Message: ----------- Minor changes, inv_radial function Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-29 18:19:16 UTC (rev 4125) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-07-29 23:05:12 UTC (rev 4126) @@ -110,7 +110,44 @@ y_src = y_dest * scale; return 1; } +/* +int inv_radial( double& x_dest, double& y_dest, double& x_src, double& y_src, double *p){ + // params: double coefficients[4] + // param values + //i: 0 => 1.000000 = 1-(a+b+c) + //i: 1 => 0.000000 = c === p[2] + //i: 2 => 0.000000 = b === p[1] + //i: 3 => 0.000000 = a === p[0] + //i: 4 => 250.000000 scale??? + //i: 5 => 1000.000000 ??? + + register double rs, rd, f, scale; + int iter = 0; + + rd = (sqrt( x_dest*x_dest + y_dest*y_dest )) / ((double*)params)[4]; // Normalized + + rs = rd; + f = (((((double*)params)[3] * rs + ((double*)params)[2]) * rs + + ((double*)params)[1]) * rs + ((double*)params)[0]) * rs; + + while( abs(f - rd) > R_EPS && iter++ < MAXITER ) + { + rs = rs - (f - rd) / ((( 4 * ((double*)params)[3] * rs + 3 * ((double*)params)[2]) * rs + + 2 * ((double*)params)[1]) * rs + ((double*)params)[0]); + + f = (((((double*)params)[3] * rs + ((double*)params)[2]) * rs + + ((double*)params)[1]) * rs + ((double*)params)[0]) * rs; + } + + scale = rs / rd; +// printf("scale = %lg iter = %d\n", scale,iter); + + x_src = x_dest * scale ; + y_src = y_dest * scale ; + return 1; +} +*/ int rect_sphere_tp(double& x_dest,double& y_dest, double& x_src, double& y_src){ // params: double distanceparam Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-29 18:19:16 UTC (rev 4125) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-29 23:05:12 UTC (rev 4126) @@ -997,7 +997,7 @@ if (good_lines == 0){ - cout << "No lines found!" << endl; + cout << "No lines found!" << endl << endl; }else{ // Create image for each line for (int i = plotted; i < lines.size(); i++){ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-30 17:17:15
|
Revision: 4129 http://hugin.svn.sourceforge.net/hugin/?rev=4129&view=rev Author: blimbo Date: 2009-07-30 17:17:06 +0000 (Thu, 30 Jul 2009) Log Message: ----------- Playing with BT edgeness output, fixed point sorting, fixed multiple images issues Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-30 05:48:37 UTC (rev 4128) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-30 17:17:06 UTC (rev 4129) @@ -264,12 +264,12 @@ //cout << " -f <string> Output file format. Default .JPG" << endl; cout << " -o <path> Output path. Default output/" << endl; //cout << " -s <float> Edge detector scale. Default 2" << endl; - //cout << " -t <float> Edge detector threshold. Default 8" << endl; + cout << " -t <float> Edge detector threshold. Default 8" << endl; //cout << " -b <float> Boundary tensor scale. Default 1.45" << endl; cout << " -g <int> Gap in pixels permitted within a line. Default 4" << endl; cout << " -m <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; //cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; - //cout << " -y <float> Corner threshold. Default 200" << endl; + cout << " -y <float> Corner threshold. Default 200" << endl; //cout << " -i <float> Pixel density in pixels/inch. Default 4000" << endl; cout << " -f <float> Focal length (mm). Read from EXIF data." << endl; cout << " -c <int> Crop factor. Read/calculated from EXIF data." << endl; @@ -283,7 +283,7 @@ cout << " 3 = R = k * 2 * tan(A/2) + (1 - k) * 2 * sin(A/2) (universal fisheye)" << endl; //cout << " -i <0|1> Generate intermediate images. Default 1" << endl; - cout << " -t <0|1> Optimise image centre. Default 0" << endl; + cout << " -z <0|1> Optimise image centre. Default 0" << endl; cout << " -v <0|1> Verbose. Default 0" << endl; cout << " -h Print usage." << endl; cout << endl; @@ -461,14 +461,14 @@ case 'e' : {detector = atoi(argv[i]); break;} case 'g' : {gap_limit = atoi(argv[i]); break;} case 'x' : {lens_model = atoi(argv[i]); break;} - case 't' : {optimise_centre = atoi(argv[i]); break;} + case 'z' : {optimise_centre = atoi(argv[i]); break;} case 'v' : {verbose = atoi(argv[i]); break;} case 'd' : {resize_dimension = atoi(argv[i]); break;} //case 's' : {scale = atof(argv[i]); break;} case 's' : {cropFactor = 24.0/atof(argv[i]); break;} case 'b' : {tscale = atof(argv[i]); break;} case 'a' : {a = atof(argv[i]); break;} - //case 't' : {threshold = atof(argv[i]); break;} + case 't' : {threshold = atof(argv[i]); break;} case 'y' : {corner_threshold = atof(argv[i]); break;} case 'm' : {length_threshold = atof(argv[i]); break;} case 'c' : {cropFactor = atof(argv[i]); break;} @@ -550,7 +550,7 @@ // Map points and optimise parameters map_points(); }else{ - cout << "Not enough lines to fit "<< n_params <<" parameters."<<endl; + cout << "Not enough lines to fit "<< n_params <<" parameters. "<< endl << endl; return 3; } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-30 05:48:37 UTC (rev 4128) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-30 17:17:06 UTC (rev 4129) @@ -59,11 +59,19 @@ } bool compare_yx (const vigra::Point2D i,const vigra::Point2D j){ - return (j->x<i->x); + if(j->x == i->x){ + return (j->y<i->y); + }else{ + return (j->x<i->x); + } } bool compare_xy (const vigra::Point2D i,const vigra::Point2D j){ - return (i->x<j->x); + if(i->x == j->x){ + return (i->y<j->y); + }else{ + return (i->x<j->x); + } } bool fileexists(string strFilename) { @@ -139,12 +147,12 @@ vigra::initImage(srcIterRange(tmp.upperLeft(), tmp.upperLeft() + vigra::Diff2D(image.width(),image.height())), RGB(255,255,255) ); - for (unsigned int il = 0; il < inliers.size(); il++){ /* - // Careful, this might segfault if the box goes off the image.. + // Careful, this might segfault if the box goes off the image.. remove -3 and change + // +3 to +1 to avoid this if(il == 0 )vigra::initImage(srcIterRange(tmp.upperLeft() + vigra::Diff2D(inliers[il]->x-3, inliers[il]->y-3), tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+3, inliers[il]->y+3)), @@ -155,7 +163,7 @@ tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+3, inliers[il]->y+3)), RGB(0,255,0) ); */ - + vigra::initImage(srcIterRange(tmp.upperLeft() + vigra::Diff2D(inliers[il]->x, inliers[il]->y), tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+1, inliers[il]->y+1)), RGB(255,0,0) ); @@ -253,7 +261,35 @@ vector<Point2D> close_neighbors; vector<int> coords_index; for (unsigned int c = 0; c < coords.size(); c++){ - if(coords[c]->x > queryPt[0]-gap_limit && coords[c]->x < queryPt[0]+gap_limit){ + + /* + // Fix problem with wrapping around + double min_x,max_x,min_y,max_y; + + if ((queryPt[0]-gap_limit) < 0){ + min_x = 0; + }else{ + min_x = queryPt[0]-gap_limit; + } + if ((queryPt[0]+gap_limit) > edgeness.width()){ + max_x = edgeness.width(); + }else{ + max_x = queryPt[0]+gap_limit; + } + + if ((queryPt[1]-gap_limit) < 0){ + min_y = 0; + }else{ + min_y = queryPt[1]-gap_limit; + } + if ((queryPt[1]+gap_limit) > edgeness.height()){ + max_y = edgeness.height(); + }else{ + max_y = queryPt[1]+gap_limit; + } + */ + + if(coords[c]->x > queryPt[0]-gap_limit && coords[c]->x < queryPt[0]+gap_limit){ if(coords[c]->y > queryPt[1]-gap_limit && coords[c]->y < queryPt[1]+gap_limit){ close_neighbors.push_back(coords[c]); coords_index.push_back(c); @@ -466,6 +502,8 @@ void nuke_corners(BImage& image, FImage& corners, string& filename){ + cout << "Removing corners..." << endl; + for (unsigned int h = 0; h < corners.height(); h++){ for (unsigned int w = 0; w < corners.width(); w++){ @@ -549,13 +587,13 @@ } } -void detect_edge(BImage& image, string& filename, string& path, string& format, BImage& edge_image){ +void detect_edge(BImage& image, string& filename, BImage& edge_image){ try{ // Paint output image white edge_image = 255; - cout << "Detecting edges..." << endl << endl; + cout << "Detecting edges..." << endl; if(detector){ // Call Shen-Castan detector algorithm @@ -602,7 +640,7 @@ } } -void generate_boundary_tensor(BImage& image, FVector2Image& edgeness, FImage& cornerness){ +void generate_boundary_tensor(BImage& image, FVector2Image& edgeness, FImage& cornerness, string& filename){ // Get cornerness from edge detection output // Create image of appropriate size for boundary tensor @@ -613,6 +651,59 @@ boundaryTensor(srcImageRange(image), destImage(boundarytensor), tscale); tensorToEdgeCorner(srcImageRange(boundarytensor), destImage(edgeness), destImage(cornerness)); + + //FImage boundarystrength(image.width(), image.height()); + //tensorTrace(srcImageRange(boundarytensor), destImage(boundarystrength)); + + BRGBImage tb_edgness(image.width(), image.height()); + tb_edgness = 255; + + for(int h = 0; h < edgeness.height(); h++){ + for(int w = 0; w < edgeness.width(); w++){ + TinyVector<float, 2> value = edgeness(w,h); + // This theshold -> command line option? + if (value[0] > 800){ + vigra::initImage(srcIterRange(tb_edgness.upperLeft() + Diff2D(w, h), + tb_edgness.upperLeft() + vigra::Diff2D(w+1, h+1)), + RGB(0,0,0) ); + //cout << w << "," << h << ":\t" << value[0] << endl; + } + } + } + + if (generate_images){ + + string output = path; + vector<string> tokens; + + // *nix file paths + if (filename.find("/") < filename.length() || filename.substr(0, 1) == ("/")){ + tokenize(filename, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } + + string edgeness_filename = output; + string cornerness_filename = output; + + edgeness_filename.append("_bt_edgeness"); + edgeness_filename.append(format); + if(!fileexists(edgeness_filename)){ + cout << "Writing " << edgeness_filename << endl; + exportImage(srcImageRange(tb_edgness), ImageExportInfo(edgeness_filename.c_str()).setPixelType("UINT8")); + } + + cornerness_filename.append("_bt_cornerness"); + cornerness_filename.append(format); + if(!fileexists(cornerness_filename)){ + cout << "Writing " << cornerness_filename << endl; + exportImage(srcImageRange(cornerness), ImageExportInfo(cornerness_filename.c_str()).setPixelType("UINT8")); + } + + } } #ifdef HUGIN_USE_EXIV2 @@ -648,7 +739,7 @@ if(lens_type == 2) cout << "Equal-area fisheye lens" << endl; if(lens_type == 3) cout << "Equal-angle fisheye lens" << endl; - cout << "Crop factor:\t\t\t" << cropFactor << endl; + if (cropFactor) cout << "Crop factor:\t\t\t" << cropFactor << endl; double pixels_per_mm = 0; if (cropFactor != 0){ @@ -670,19 +761,19 @@ cout << "Pixel density (pixels/mm):\t" << pixels_per_mm << endl; }else{ // Need command line param - cout << "Could not identify crop factor from EXIF data. Please provide it as a command line parameter with the -c flag." << endl; + cout << endl << "Could not identify crop factor from EXIF data. Please provide it as a command line parameter with the -c flag." << endl << endl; exit(1); } if (focal_length != 0){ - focal_length_pixels = focal_length*pixels_per_mm; + focal_length_pixels = focal_length*pixels_per_mm; cout << "Focal length (mm):\t\t" << focal_length << endl; cout << "Focal length (pixels):\t\t" << focal_length_pixels << endl << endl; }else{ // Need command line param - cout << "Could not identify focal length from EXIF data. Please provide it as a command line parameter with the -f flag." << endl; + cout << endl << "Could not identify focal length from EXIF data. Please provide it as a command line parameter with the -f flag." << endl << endl; exit(1); } @@ -838,24 +929,38 @@ float efocal_length35 = 0; getExiv2Value(exifData,"Exif.Photo.FocalLengthIn35mmFilm",efocal_length35); + double new_focal_length,new_cropFactor; + //The various methods to detmine crop factor if (efocal_length > 0 && cropFactor > 0) { // user provided crop factor - focal_length = efocal_length; + new_focal_length = efocal_length; }else if (efocal_length35 > 0 && efocal_length > 0) { - cropFactor = efocal_length35 / efocal_length; - focal_length = efocal_length; + new_cropFactor = efocal_length35 / efocal_length; + new_focal_length = efocal_length; }else if (efocal_length35 > 0) { // 35 mm equiv focal length available, crop factor unknown. // do not ask for crop factor, assume 1. Probably a full frame sensor - cropFactor = 1; - focal_length = efocal_length35; + new_cropFactor = 1; + new_focal_length = efocal_length35; }else if (efocal_length > 0 && cropFactor <= 0) { // need to redo, this time with crop - focal_length = efocal_length; - cropFactor = 0; + new_focal_length = efocal_length; + new_cropFactor = 0; } + if(focal_length && focal_length != new_focal_length){ + cout << "Warning! This image appears to have a different focal length from the previous one!" << endl << endl; + }else{ + focal_length = new_focal_length; + } + + if(cropFactor && cropFactor != new_cropFactor){ + cout << "Waring! This image appears to have a different crop factor from the previous one!" << endl << endl; + }else{ + cropFactor = new_cropFactor; + } + /* cout << "Width:\t\t" << width << endl; cout << "Height:\t\t" << height << endl; @@ -933,14 +1038,27 @@ int nw = info.width(), nh = info.height(); + // If this is the 2nd or subsequent image + if(original_width && original_height && nw != original_width && nh != original_height){ + // Allow for switching between portrait and landscape + if (nh != original_width && nw != original_height){ + cout << "Warning! This image appears to have different dimensions from the previous one!" << endl << endl; + } + } + original_width = info.width(); original_height = info.height(); + int exif_ok = get_exif_data(filename); + + /* if (focal_length && cropFactor){ calculate_focal_length_pixels(); }else{ int exif_ok = get_exif_data(filename); } + */ + if (nw > nh){ min_line_length_squared = (length_threshold*nw)*(length_threshold*nw); @@ -961,10 +1079,10 @@ vector<Point2D> coords, inliers; // Run Canny edge detector - detect_edge(grey, filename, path, format, image); + detect_edge(grey, filename, image); // Generate boundary tensor - generate_boundary_tensor(image, edgeness, cornerness); + generate_boundary_tensor(image, edgeness, cornerness, filename); // Remove corners nuke_corners(image, cornerness, filename); @@ -992,7 +1110,8 @@ } // Sort lines by distance between first and last point or number of pixels - sort_lines_by_length(); + // Problem if we're doing multiple images + // Sort_lines_by_length(); @@ -1001,6 +1120,7 @@ }else{ // Create image for each line for (int i = plotted; i < lines.size(); i++){ + //cout << "plotted = " << plotted << " --- " << " line.size() = " << lines.size() << " --- i = " << i << endl; plot_inliers(filename, image, lines[i],i+1); plotted++; } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-30 05:48:37 UTC (rev 4128) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-07-30 17:17:06 UTC (rev 4129) @@ -15,9 +15,10 @@ void plot_inliers(std::string&, vigra::BImage& image, std::vector<vigra::Point2D>&, int); void extract_coords(vigra::BImage&, std::vector<vigra::Point2D>&); void nuke_corners(vigra::BImage&, vigra::FImage&, std::string&); -void detect_edge(vigra::BImage&, std::string&, std::string&, std::string&, vigra::BImage&); +void detect_edge(vigra::BImage&, std::string&, vigra::BImage&); void process_image(std::string&, int&); void sort_lines_by_length(); bool compare_line_length(std::vector<vigra::Point2D>, std::vector<vigra::Point2D>); +void generate_boundary_tensor(vigra::BImage&, vigra::FVector2Image&, vigra::FImage&, std::string&); #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-07-31 15:05:25
|
Revision: 4135 http://hugin.svn.sourceforge.net/hugin/?rev=4135&view=rev Author: blimbo Date: 2009-07-31 15:05:11 +0000 (Fri, 31 Jul 2009) Log Message: ----------- BT edge finder implememnted Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-31 13:45:39 UTC (rev 4134) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-07-31 15:05:11 UTC (rev 4135) @@ -42,13 +42,14 @@ //std::string path = (""); std::string format = (".jpg"); double sizefactor = 1; -double threshold = 8; +double threshold = 4; +double bt_threshold = 75; double length_threshold = 0.3; double min_line_length_squared; double scale = 2; double tscale = 1.45; double a = 140.0; -double corner_threshold = 200; +double corner_threshold = 150; unsigned int gap_limit = 4; unsigned int vertical_slices = 12; unsigned int horizontal_slices = 8; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-31 13:45:39 UTC (rev 4134) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-07-31 15:05:11 UTC (rev 4135) @@ -25,6 +25,7 @@ extern std::string format; extern double sizefactor; extern double threshold; +extern double bt_threshold; extern double length_threshold; extern double min_line_length_squared; extern double scale; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-31 13:45:39 UTC (rev 4134) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-07-31 15:05:11 UTC (rev 4135) @@ -84,7 +84,9 @@ if (fileexists(imagename)){ // Put filenames into a vector - if(current == image_number) images.push_back(imagename); + //if(current == image_number) images.push_back(imagename); + // Put all filenames into a vector + images.push_back(imagename); // Seach for the image if we can't find it, using path of PTO file }else{ @@ -161,7 +163,7 @@ } -static void write_pto(string& output_pto,vector<string>& pto_file_top,vector<string>& pto_file_cps,vector<string>& pto_file_end, unsigned int& pto_image, unsigned int& cps_per_line){ +static void write_pto(string& output_pto,vector<string>& pto_file_top,vector<string>& pto_file_cps,vector<string>& pto_file_end, unsigned int& pto_image, unsigned int& cps_per_line, map<int,int>& lines_to_image_number){ // File to write to ofstream out; @@ -186,8 +188,27 @@ double invert_size_factor = 1.0/sizefactor; for (unsigned int l = 0; l < lines.size(); l++){ - unsigned int line_count = l+3; + unsigned int line_count = l+3; + double interval = lines[l].size()/cps_per_line; + + for(int i = 0; i < cps_per_line; i++){ + int start = i * (int)interval; + int stop = (i+1) * (int)interval; + + //cout << l << ":" << i << " - " << start << ": " << lines[l][start]->x << " - " << start << ":" << lines[l][start]->y << endl; + //cout << l << ":" << i << " - " << stop << ": " << lines[l][start]->x << " - " << stop << ":" << lines[l][stop]->y << endl << endl; + + double x1 = lines[l][start]->x*invert_size_factor; + double y1 = lines[l][start]->y*invert_size_factor; + double x2 = lines[l][stop]->x*invert_size_factor; + double y2 = lines[l][stop]->y*invert_size_factor; + + out << "c n" << lines_to_image_number[l] << " N" << lines_to_image_number[l] << " x" << x1 << " y" << y1; + out << " X" << x2 << " Y" << y2 << " t" << line_count << endl; + } + + /* int d1 = abs(lines[l][0]->x - lines[l][lines[l].size()-1]->x); int d2 = abs(lines[l][0]->y - lines[l][lines[l].size()-1]->y); @@ -204,7 +225,7 @@ if (y){ //cout << start <<endl; if(start){ - out << "c n" << pto_image << " N" << pto_image << " x" << nx + out << "c n" << lines_to_image_number[l] << " N" << lines_to_image_number[l] << " x" << nx << " y" << ny; start = 0; }else{ @@ -227,7 +248,7 @@ if (x){ //cout << start <<endl; if(start){ - out << "c n" << pto_image << " N" << pto_image << " x" << nx + out << "c n" << lines_to_image_number[l] << " N" << lines_to_image_number[l] << " x" << nx << " y" << ny; start = 0; }else{ @@ -237,6 +258,7 @@ } } } + */ } // Print bottom of file @@ -248,49 +270,6 @@ } -static void usage(){ - - // Print usage and exit - cout << endl << "Lens calibration tool" << endl; - cout << endl << "Version " << VERSION << endl; - cout << endl << "Usage: calibrate_lens [options] image1 image2.." << endl << endl; - cout << "Options:" << endl << endl; - cout << " -p <filename> Input Hugin PTO file." << endl; - cout << " -i <int> Image in Hugin PTO file to process. Default 0" << endl; - cout << " -j <filename> Input file containing line data." << endl; - //cout << " -c <int> Control points to add to PTO file per line. Default 10." << endl; - cout << " -e <0|1> Edge detector. 0 = Canny (default) 1 = Shen-Castan." << endl; - cout << " -d <int> Maximum dimension for re-sized image prior to processing. Default 1600." << endl; - //cout << " -f <string> Output file format. Default .JPG" << endl; - cout << " -o <path> Output path. Default output/" << endl; - //cout << " -s <float> Edge detector scale. Default 2" << endl; - cout << " -t <float> Edge detector threshold. Default 8" << endl; - //cout << " -b <float> Boundary tensor scale. Default 1.45" << endl; - cout << " -g <int> Gap in pixels permitted within a line. Default 4" << endl; - cout << " -m <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; - //cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; - cout << " -y <float> Corner threshold. Default 200" << endl; - //cout << " -i <float> Pixel density in pixels/inch. Default 4000" << endl; - cout << " -f <float> Focal length (mm). Read from EXIF data." << endl; - cout << " -c <int> Crop factor. Read/calculated from EXIF data." << endl; - cout << " -s <float> Shortest dimension of sensor (mm), used to calculate crop factor." << endl; - cout << " -l <int> Lens type. 1 = Rectilinear (default)" << endl; - cout << " 2 = Equal-area fisheye" << endl; - cout << " 3 = Equal-angle fisheye" << endl; - - cout << " -x <int> Lens model.1 = R = u + p2 * u^2 + p4 * u^4 (default)" << endl; - cout << " 2 = R = a * u^4 + b * u^3 + c * u^2 (Panotools)" << endl; - cout << " 3 = R = k * 2 * tan(A/2) + (1 - k) * 2 * sin(A/2) (universal fisheye)" << endl; - - //cout << " -i <0|1> Generate intermediate images. Default 1" << endl; - cout << " -z <0|1> Optimise image centre. Default 0" << endl; - cout << " -v <0|1> Verbose. Default 0" << endl; - cout << " -h Print usage." << endl; - cout << endl; - exit(1); - -} - void write_lines_to_file(string& filename1, string& filename2){ // Create output file name @@ -427,6 +406,52 @@ cout << endl; } +static void usage(){ + + // Print usage and exit + cout << endl << "Lens calibration tool" << endl; + cout << endl << "Version " << VERSION << endl; + cout << endl << "Usage: calibrate_lens [options] image1 image2.." << endl << endl; + cout << "Options:" << endl << endl; + cout << " -p <filename> Input Hugin PTO file." << endl; + cout << " -i <int> Image in Hugin PTO file to process. Default 0" << endl; + cout << " -j <filename> Input file containing line data." << endl; + //cout << " -c <int> Control points to add to PTO file per line. Default 10." << endl; + cout << " -e <int> Edge detector. 1 = Canny (default)" << endl; + cout << " 2 = Shen-Castan" << endl; + cout << " 3 = Boundary tensor" << endl; + cout << " -d <int> Maximum dimension for re-sized image prior to processing. Default 1600." << endl; + //cout << " -f <string> Output file format. Default .JPG" << endl; + cout << " -o <path> Output path. Default output/" << endl; + //cout << " -s <float> Edge detector scale. Default 2" << endl; + cout << " -t <float> Edge detector threshold. Default 4" << endl; + //cout << " -b <float> Boundary tensor scale. Default 1.45" << endl; + cout << " -b <float> Boundary tensor threshold. Default 75" << endl; + cout << " -g <int> Gap in pixels permitted within a line. Default 4" << endl; + cout << " -m <float> Minimum line length as a fraction of longest dimension. Default 0.3" << endl; + //cout << " -m <float> Sigma parameter for hourglass filter. Default 1.4" << endl; + cout << " -y <float> Corner threshold. Default 150" << endl; + //cout << " -i <float> Pixel density in pixels/inch. Default 4000" << endl; + cout << " -f <float> Focal length (mm). Read from EXIF data." << endl; + cout << " -c <int> Crop factor. Read/calculated from EXIF data." << endl; + cout << " -s <float> Shortest dimension of sensor (mm), used to calculate crop factor." << endl; + cout << " -l <int> Lens type. 1 = Rectilinear (default)" << endl; + cout << " 2 = Equal-area fisheye" << endl; + cout << " 3 = Equal-angle fisheye" << endl; + + cout << " -x <int> Lens model. 1 = R = u + p2 * u^2 + p4 * u^4 (default)" << endl; + cout << " 2 = R = a * u^4 + b * u^3 + c * u^2 (Panotools)" << endl; + cout << " 3 = R = k * 2 * tan(A/2) + (1 - k) * 2 * sin(A/2) (universal fisheye)" << endl; + + //cout << " -i <0|1> Generate intermediate images. Default 1" << endl; + cout << " -z <0|1> Optimise image centre. Default 0" << endl; + cout << " -v <0|1> Verbose. Default 0" << endl; + cout << " -h Print usage." << endl; + cout << endl; + exit(1); + +} + int main(int argc, const char* argv[]){ cout << endl << "Lens calibration tool" << endl; @@ -437,6 +462,7 @@ unsigned int cps_per_line = 10; string pto_file = (""),output_pto = (""),lines_file = (""); vector<string> images,pto_file_top,pto_file_cps,pto_file_end; + map<int,int> lines_to_image_number; // Deal with arguments while(i < argc){ @@ -466,9 +492,10 @@ case 'd' : {resize_dimension = atoi(argv[i]); break;} //case 's' : {scale = atof(argv[i]); break;} case 's' : {cropFactor = 24.0/atof(argv[i]); break;} - case 'b' : {tscale = atof(argv[i]); break;} + //case 'b' : {tscale = atof(argv[i]); break;} case 'a' : {a = atof(argv[i]); break;} case 't' : {threshold = atof(argv[i]); break;} + case 'b' : {bt_threshold = atof(argv[i]); break;} case 'y' : {corner_threshold = atof(argv[i]); break;} case 'm' : {length_threshold = atof(argv[i]); break;} case 'c' : {cropFactor = atof(argv[i]); break;} @@ -524,7 +551,15 @@ exit(1); } cout << "Processing image " << images[i].c_str() << endl << endl; - process_image(images[i],plotted); + int previous = plotted; + process_image(images[i],plotted); + + // Use this map for writing lines to PTO file + for(int j = previous; j < plotted; j++){ + lines_to_image_number[j] = i; + //cout << "Line " << j << " img no.:" << i << endl; + } + previous = plotted; } cout << "Found "<< lines.size() <<" lines."<< endl << endl; @@ -556,8 +591,8 @@ if (pto_file != ("")){ - write_pto(output_pto,pto_file_top,pto_file_cps,pto_file_end,pto_image,cps_per_line); - cout << "Written file " << output_pto << endl; + write_pto(output_pto,pto_file_top,pto_file_cps,pto_file_end,pto_image,cps_per_line,lines_to_image_number); + cout << endl << "Written file " << output_pto << endl; } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-31 13:45:39 UTC (rev 4134) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-07-31 15:05:11 UTC (rev 4135) @@ -60,15 +60,16 @@ bool compare_yx (const vigra::Point2D i,const vigra::Point2D j){ if(j->x == i->x){ - return (j->y<i->y); + return (j->y>i->y); }else{ return (j->x<i->x); } } bool compare_xy (const vigra::Point2D i,const vigra::Point2D j){ + if(i->x == j->x){ - return (i->y<j->y); + return (i->y>j->y); }else{ return (i->x<j->x); } @@ -117,6 +118,9 @@ void sort_inliers(vector<Point2D>& inliers){ + sort(inliers.begin(), inliers.end(), compare_xy); + + /* unsigned int top = 0; unsigned int bottom = 100000; unsigned int left = 100000; @@ -139,6 +143,7 @@ }else{ sort(inliers.begin(), inliers.end(), compare_yx); } + */ } void plot_inliers(string& filename, BImage& image, vector<Point2D>& inliers, int i){ @@ -189,14 +194,14 @@ output.append(ii.str()); output.append(format); - if(!fileexists(output)){ + //if(!fileexists(output)){ cout << "Plotting line " << i << ". Pixels:\t" << inliers.size() << endl; exportImage(srcImageRange(tmp), ImageExportInfo(output.c_str()).setPixelType("UINT8")); - } + //} } } -void find_ann(vector<Point2D>& coords, FVector2Image& edgeness, vector<Point2D>& inliers, unsigned int& good_lines){ +void find_ann(vector<Point2D>& coords, FVector2Image& edgeness, vector<Point2D>& inliers, unsigned int& good_lines, vector<vector<Point2D> >& short_segments){ int k = 1; // Number of nearest neighbours int dim = 3; // Dimensions @@ -479,6 +484,10 @@ good_lines++; if(verbose) cout << "Above theshold (" << min_line_length_squared << ")" << endl; }else{ + // Collect shorter segments + if(length_sq >= min_line_length_squared/2){ + short_segments.push_back(inliers); + } inliers.clear(); if(verbose) cout << "Below theshold (" << min_line_length_squared << ")" << endl; } @@ -580,10 +589,10 @@ output.append("_edges_minus_corners"); output.append(format); - if(!fileexists(output)){ + //if(!fileexists(output)){ cout << "Writing " << output << endl << endl; exportImage(srcImageRange(image), ImageExportInfo(output.c_str()).setPixelType("UINT8")); - } + //} } } @@ -595,7 +604,7 @@ cout << "Detecting edges..." << endl; - if(detector){ + if(detector == 2){ // Call Shen-Castan detector algorithm differenceOfExponentialEdgeImage(srcImageRange(image), destImage(edge_image), scale, threshold, 0); @@ -629,10 +638,10 @@ output.append(ds.str()); output.append(format); - if(!fileexists(output)){ + //if(!fileexists(output)){ cout << "Writing " << output << endl; exportImage(srcImageRange(edge_image), output.c_str()); - } + //} } } catch (StdException & e){ @@ -655,59 +664,74 @@ //FImage boundarystrength(image.width(), image.height()); //tensorTrace(srcImageRange(boundarytensor), destImage(boundarystrength)); - BRGBImage tb_edgness(image.width(), image.height()); - tb_edgness = 255; - for(int h = 0; h < edgeness.height(); h++){ - for(int w = 0; w < edgeness.width(); w++){ - TinyVector<float, 2> value = edgeness(w,h); - // This theshold -> command line option? - if (value[0] > 800){ - vigra::initImage(srcIterRange(tb_edgness.upperLeft() + Diff2D(w, h), - tb_edgness.upperLeft() + vigra::Diff2D(w+1, h+1)), - RGB(0,0,0) ); - //cout << w << "," << h << ":\t" << value[0] << endl; - } + //int bt_edge_threshold = 30; + //for (int i = 30; i < 71; i++){ + + BImage tb_edgness(image.width(), image.height()); + tb_edgness = 255; + + for(int h = 0; h < edgeness.height(); h++){ + for(int w = 0; w < edgeness.width(); w++){ + TinyVector<float, 2> value = edgeness(w,h); + + //if (value[0] > bt_edge_threshold){ + if (value[0] > bt_threshold){ + vigra::initImage(srcIterRange(tb_edgness.upperLeft() + Diff2D(w, h), + tb_edgness.upperLeft() + vigra::Diff2D(w+1, h+1)), + BImage::PixelType(0) ); + //cout << w << "," << h << ":\t" << value[0] << endl; + } + } } - } + // Use this output for edges rather than Canny + //if(tb_edge_threshold == bt_threshold && detector == 3) image = tb_edgness; + if(detector == 3) image = tb_edgness; - if (generate_images){ + if (generate_images){ - string output = path; - vector<string> tokens; + string output = path; + vector<string> tokens; - // *nix file paths - if (filename.find("/") < filename.length() || filename.substr(0, 1) == ("/")){ - tokenize(filename, tokens, "/"); - output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); - // Windows file paths - }else{ - tokenize(filename, tokens, "\\"); - output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); - } + // *nix file paths + if (filename.find("/") < filename.length() || filename.substr(0, 1) == ("/")){ + tokenize(filename, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } - string edgeness_filename = output; - string cornerness_filename = output; + string edgeness_filename = output; + string cornerness_filename = output; - edgeness_filename.append("_bt_edgeness"); - edgeness_filename.append(format); - if(!fileexists(edgeness_filename)){ - cout << "Writing " << edgeness_filename << endl; - exportImage(srcImageRange(tb_edgness), ImageExportInfo(edgeness_filename.c_str()).setPixelType("UINT8")); - } + cornerness_filename.append("_bt_cornerness"); + cornerness_filename.append(format); + //if(!fileexists(cornerness_filename)){ + cout << "Writing " << cornerness_filename << endl; + exportImage(srcImageRange(cornerness), ImageExportInfo(cornerness_filename.c_str()).setPixelType("UINT8")); + //} - cornerness_filename.append("_bt_cornerness"); - cornerness_filename.append(format); - if(!fileexists(cornerness_filename)){ - cout << "Writing " << cornerness_filename << endl; - exportImage(srcImageRange(cornerness), ImageExportInfo(cornerness_filename.c_str()).setPixelType("UINT8")); + edgeness_filename.append("_bt_edgeness_"); + + stringstream dt; + //dt << bt_edge_threshold; + dt << bt_threshold; + edgeness_filename.append(dt.str()); + + edgeness_filename.append(format); + //if(!fileexists(edgeness_filename)){ + cout << "Writing " << edgeness_filename << endl; + exportImage(srcImageRange(tb_edgness), ImageExportInfo(edgeness_filename.c_str()).setPixelType("UINT8")); + //} + } - - } + + //tb_edge_threshold++; + //} } -#ifdef HUGIN_USE_EXIV2 - bool getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, long & value){ Exiv2::ExifKey key(keyName); Exiv2::ExifData::iterator itr = exifData.findKey(key); @@ -731,7 +755,6 @@ return false; } } -#endif // HUGIN_USE_EXIV2 void calculate_focal_length_pixels(){ @@ -1028,6 +1051,35 @@ sort(lines.begin(), lines.end(), compare_line_length); } +void join_short_segments(vector<vector<Point2D> >& short_segments){ + + for(int i = 0; i < short_segments.size(); i++){ + + unsigned int top = 0; + unsigned int bottom = 100000; + unsigned int left = 100000; + unsigned int right = 0; + + for (unsigned int il = 0; il < short_segments[i].size(); il++){ + + if(short_segments[i][il]->x < left) left = short_segments[i][il]->x; + if(short_segments[i][il]->x > right) right = short_segments[i][il]->x; + if(short_segments[i][il]->y < bottom) bottom = short_segments[i][il]->y; + if(short_segments[i][il]->y > top) top = short_segments[i][il]->y; + + cout << short_segments[i][il]->x << "," << short_segments[i][il]->y << endl; + + } + + cout << "Gradient = " << (right-left)/(top-bottom) << endl; + + } + + + + +} + void process_image(string& filename, int& plotted){ ImageImportInfo info(filename.c_str()); @@ -1079,7 +1131,11 @@ vector<Point2D> coords, inliers; // Run Canny edge detector - detect_edge(grey, filename, image); + if(detector != 3){ + detect_edge(grey, filename, image); + }else{ + image = grey; + } // Generate boundary tensor generate_boundary_tensor(image, edgeness, cornerness, filename); @@ -1093,13 +1149,17 @@ unsigned int intital_coords_size = coords.size(); if(verbose) cout << "Initial 'edge' pixel count:\t" << coords.size() << endl << endl; + + cout << "Detecting lines..." << endl << endl; + + vector<vector<Point2D> > short_segments; // Get 10 strongest lines unsigned int good_lines = 0; while (good_lines < 10 && coords.size() > 1){ if(verbose) cout << "Searching for line " << good_lines+1 << ":" << endl; if(verbose) cout << "=====================" << endl << endl; - find_ann(coords, edgeness, inliers, good_lines); + find_ann(coords, edgeness, inliers, good_lines, short_segments); if(inliers.size()){ sort_inliers(inliers); lines.push_back(inliers); @@ -1109,6 +1169,11 @@ } + + //cout << "Size of short segments:\t" << short_segments.size() << endl << endl; + //join_short_segments(short_segments); + short_segments.clear(); + // Sort lines by distance between first and last point or number of pixels // Problem if we're doing multiple images // Sort_lines_by_length(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-08-04 17:41:19
|
Revision: 4166 http://hugin.svn.sourceforge.net/hugin/?rev=4166&view=rev Author: blimbo Date: 2009-08-04 17:41:08 +0000 (Tue, 04 Aug 2009) Log Message: ----------- Segment joiner working ok Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-08-04 14:47:41 UTC (rev 4165) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-08-04 17:41:08 UTC (rev 4166) @@ -543,7 +543,7 @@ } //images.push_back("/home/tnugent/src/gsoc2009_lenscalibration/src/lens_calibrate/dsc_0040.jpg"); - //images.push_back("/home/tnugent/src/gsoc2009_lenscalibration/src/lens_calibrate/dsc_0163.jpg"); + //images.push_back("/home/tnugent/src/gsoc2009_lenscalibration/src/lens_calibrate/IMG_2207.JPG"); if (images.size() == 0 && lines.size() == 0){ //cout << "No images provided!" << endl << endl; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-04 14:47:41 UTC (rev 4165) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-04 17:41:08 UTC (rev 4166) @@ -1070,188 +1070,253 @@ sort(lines.begin(), lines.end(), compare_line_length); } -double gradient(vector<Point2D>& a){ - double d1 = a[0]->x - a[a.size()-1]->x; - double d2 = a[0]->y - a[a.size()-1]->y; - double grad = d2/d1; - - //cout << a[0]->x << " - " << a[a.size()-1]->x << " = " << d1 << endl; - //cout << a[0]->y<< " - " << a[a.size()-1]->y <<" = " << d2 << endl; - //cout << "Gradient:\t" << grad << endl << endl; - - return(grad); -} - double point_line_length_squared(Point2D& a, Point2D& b){ int d1 = a->x - b->x; int d2 = a->y - b->y; - - //cout << a->x << " - " << b->x << " = " << d1 << endl; //cout << a->y<< " - " << b->y <<" = " << d2 << endl; //cout << "Dist^2:\t" << (d1*d1+d2*d2) << endl << endl; - return(d1*d1+d2*d2); } -int smallest_x_value(vector<Point2D>& a){ - int smallest = 100000000; - for(int i = 0; i < a.size(); i++){ - if(a[i]->x < smallest) smallest = a[i]->x; - } - return(smallest); +int min_x_index(vector<Point2D>& a){ + int smallest = 100000000; + int index = 0; + for(int i = 0; i < a.size(); i++){ + if(a[i]->x < smallest){ + smallest = a[i]->x; + index = i; + } + } + return(index); } -int largest_x_value(vector<Point2D>& a){ - int largest = -100000; - for(int i = 0; i < a.size(); i++){ - if(a[i]->x > largest) largest = a[i]->x; - } - return(largest); +int max_x_index(vector<Point2D>& a){ + int largest = -100000000; + int index = 0; + for(int i = 0; i < a.size(); i++){ + if(a[i]->x > largest){ + largest = a[i]->x; + index = i; + } + } + return(index); } -int smallest_y_value(vector<Point2D>& a){ - int smallest = 100000000; - for(int i = 0; i < a.size(); i++){ - if(a[i]->y < smallest) smallest = a[i]->y; - } - return(smallest); +int min_y_index(vector<Point2D>& a){ + int smallest = 100000000; + int index = 0; + for(int i = 0; i < a.size(); i++){ + if(a[i]->y < smallest){ + smallest = a[i]->y; + index = i; + } + } + return(index); } -int largest_y_value(vector<Point2D>& a){ - int largest = -100000; - for(int i = 0; i < a.size(); i++){ - if(a[i]->y > largest) largest = a[i]->y; - } - return(largest); +int max_y_index(vector<Point2D>& a){ + int largest = -100000000; + int index = 0; + for(int i = 0; i < a.size(); i++){ + if(a[i]->y > largest){ + largest = a[i]->y; + index = i; + } + } + return(index); } -void join_short_segments(vector<vector<Point2D> >& short_segments, BImage& image){ +double gradient(vector<Point2D>& a){ + + int max_x = max_x_index(a); + int min_x = min_x_index(a); + int max_y = max_y_index(a); + int min_y = min_y_index(a); + double d1 = a[max_x]->x - a[min_x]->x; + double d2 = a[max_y]->y - a[min_y]->y; + double grad = d2/d1; + + //cout << a[0]->x << " - " << a[a.size()-1]->x << " = " << d1 << endl; + //cout << a[0]->y<< " - " << a[a.size()-1]->y <<" = " << d2 << endl; + //cout << "Gradient:\t" << grad << endl << endl; + + return(grad); +} - string seg("segment_"); - string jseg("joined_segment_"); +void join_short_segments(vector<vector<Point2D> >& short_segments, unsigned int& good_lines, BImage& image){ - //for(int i = 0; i < short_segments.size(); i++){ - // plot_inliers(seg, image, short_segments[i], i); - //} + string jseg("joined_"); + string seg("seg_"); + int js = 0; + int limit = 800; + + /* + for(int i = 0; i < short_segments.size(); i++){ + plot_inliers(seg, image, short_segments[i], i); + cout << "Gradient:\t" << gradient(short_segments[i]) << endl; + } + */ - int js = 0; - int tmp_i = 0; - int limit = 1000; - for(int i = 0; i < short_segments.size(); i++){ + vector<Point2D> joined_segs; + map<double,int> closest_index; + //map<int,int> other_dimension; + int count = 0, original_line_size = 0; + while(short_segments.size() > 0){ - int oi_x_max = largest_x_value(short_segments[i]); - int oi_x_min = smallest_x_value(short_segments[i]); - int oi_y_max = largest_y_value(short_segments[i]); - int oi_y_min = smallest_y_value(short_segments[i]); - - for(int j = 0; j < short_segments.size(); j++){ - - cout << "Lines " << i << " vs " << j << endl; - - double a = point_line_length_squared(short_segments[i][0],short_segments[j][0]); - double b = point_line_length_squared(short_segments[i][0],short_segments[j][short_segments[j].size()-1]); - double c = point_line_length_squared(short_segments[i][short_segments[i].size()-1],short_segments[j][0]); - double d = point_line_length_squared(short_segments[i][short_segments[i].size()-1],short_segments[j][short_segments[j].size()-1]); + // Of the close segments found, add the closest segment to joined_segs + if(closest_index.size()){ + int j = 0; + map<double,int>::iterator it_h1; + for (it_h1 = closest_index.begin(); it_h1 != closest_index.end(); it_h1++){ + if(!j){ + //cout << js << " Dist:\t" << (*it_h1).first<< endl; + //cout << "Other dimension:\t" << other_dimension[j] << endl; + j = (*it_h1).second; + } + } + + for(int k = 0; k < short_segments[j].size(); k++){ + joined_segs.push_back(short_segments[j][k]); + } + short_segments.erase(short_segments.begin()+j); + closest_index.clear(); + //other_dimension.clear(); + }else{ + joined_segs = short_segments[0]; + original_line_size = joined_segs.size(); + short_segments.erase(short_segments.begin()); + } - int i_x_max = largest_x_value(short_segments[i]); - int i_x_min = smallest_x_value(short_segments[i]); - int i_y_max = largest_y_value(short_segments[i]); - int i_y_min = smallest_y_value(short_segments[i]); + for(int j = 0; j < short_segments.size(); j++){ + + //plot_inliers(seg, image, short_segments[j], j); + //cout << "Lines " << count << " vs " << j << endl; - int j_x_max = largest_x_value(short_segments[j]); - int j_x_min = smallest_x_value(short_segments[j]); - int j_y_max = largest_y_value(short_segments[j]); - int j_y_min = smallest_y_value(short_segments[j]); - - if(j_x_max==oi_x_max && j_y_max==oi_y_max && j_x_min==oi_x_min && j_y_min==oi_y_min){ - break; + // Get indexes of max/min x and y points + int i_x_max = max_x_index(joined_segs); + int i_x_min = min_x_index(joined_segs); + int i_y_max = max_y_index(joined_segs); + int i_y_min = min_y_index(joined_segs); + int j_x_max = max_x_index(short_segments[j]); + int j_x_min = min_x_index(short_segments[j]); + int j_y_max = max_y_index(short_segments[j]); + int j_y_min = min_y_index(short_segments[j]); + + //printf("i: x_min: %d y_min: %d --- x_max: %d y_max: %d\n",joined_segs[i_x_min]->x,joined_segs[i_y_min]->y,joined_segs[i_x_max]->x,joined_segs[i_y_max]->y); + //printf("j: x_min: %d y_min: %d --- x_max: %d y_max: %d\n",short_segments[j][j_x_min]->x,short_segments[j][j_y_min]->y,short_segments[j][j_x_max]->x,short_segments[j][j_y_max]->y); + + // Check to see if lines overlap on x or y axes + int overlaps = 0; + int i_horiz = 0, j_horiz = 0;; + //int other_dim_diff; + if(abs(joined_segs[i_x_max]->x - joined_segs[i_x_min]->x) > abs(joined_segs[i_y_max]->y - joined_segs[i_y_min]->y)){ + i_horiz = 1; + // Horizontal line + if (joined_segs[i_x_max]->x > short_segments[j][j_x_max]->x){ + if(short_segments[j][j_x_max]->x > joined_segs[i_x_min]->x) overlaps = 1; + + //other_dim_diff = abs(short_segments[j][j_x_max]->y - joined_segs[i_x_min]->x); + + }else{ + if(joined_segs[i_x_max]->x > short_segments[j][j_x_min]->x) overlaps = 1; + + //other_dim_diff = abs(joined_segs[i_x_max]->y - short_segments[j][j_x_min]->y); + } }else{ - - //printf("ixmax: %d ixmin: %d iymax: %d iymin: %d\n",i_x_max,i_x_min,i_y_max,i_y_min); - //printf("jxmax: %d jxmin: %d jymax: %d jymin: %d\n",j_x_max,j_x_min,j_y_max,j_y_min); + // Vertical line + if (joined_segs[i_y_max]->y > short_segments[j][j_y_max]->y){ + if(short_segments[j][j_y_max]->y > joined_segs[i_y_min]->y) overlaps = 1; + + //other_dim_diff = abs(short_segments[j][j_y_max]->x - joined_segs[i_y_min]->x); - if (a < limit || b < limit || c < limit || d < limit){ - - int overlaps = 0; - if(abs(i_x_max - i_x_min) > abs(i_y_max - i_x_min)){ - // Horizontal line - if (i_x_max > j_x_max){ - if(j_x_max > i_x_min) overlaps = 1; - if(i_x_min < j_x_min) overlaps = 1; - - }else{ - if(i_x_max > j_x_min) overlaps = 1; - if(j_x_min < i_x_min) overlaps = 1; - - } }else{ - // Vertical line - if (i_y_max > j_y_max){ - if(j_y_max > i_y_min) overlaps = 1; - if(i_y_min < j_y_min) overlaps = 1; + if(joined_segs[i_y_max]->y > short_segments[j][j_y_min]->y) overlaps = 1; + + //other_dim_diff = abs(joined_segs[i_y_max]->x - short_segments[j][j_y_min]->x); + + } + } + if(abs(short_segments[j][j_x_max]->x - short_segments[j][j_x_min]->x) > abs(short_segments[j][j_y_max]->y - short_segments[j][j_y_min]->y)){ + j_horiz = 1; + } + + // Make sure both lines appear to be horizontal or vertical + if(i_horiz == j_horiz){ + // Measure this distance between the nearest points of the two segments + double dist; + if(!overlaps){ + if(i_horiz){ + if (joined_segs[i_x_max]->x > short_segments[j][j_x_max]->x){ + dist = point_line_length_squared(joined_segs[i_x_min],short_segments[j][j_x_max]); + }else{ + dist = point_line_length_squared(short_segments[j][j_x_min],joined_segs[i_x_max]); + } }else{ - if(i_y_max > j_y_min) overlaps = 1; - if(j_y_min < i_y_min) overlaps = 1; - } + if (joined_segs[i_y_max]->y > short_segments[j][j_y_max]->y){ + dist = point_line_length_squared(joined_segs[i_y_min],short_segments[j][j_y_max]); + }else{ + dist = point_line_length_squared(short_segments[j][j_y_min],joined_segs[i_y_max]); + } + } } - - if(!overlaps){ - - double grad_i = gradient(short_segments[i]); - double grad_j = gradient(short_segments[j]); + // Add this segment index to closest_index if it doesn't overlap and is close enough + if(!overlaps && dist < limit){ + // Check to make sure segment gradients are similar + double grad_i = gradient(joined_segs); + double grad_j = gradient(short_segments[j]); - if(grad_j >= (grad_i*0.75) && grad_j <= (grad_i*1.25)){ - - //printf("Segement i end points Y= %d and %d\n",largest_y_value(short_segments[i]),smallest_y_value(short_segments[i])); - //printf("Segement i end points X= %d and %d\n",largest_x_value(short_segments[i]),smallest_x_value(short_segments[i])); - - cout << "Combining " << tmp_i << " with " << tmp_i+1 << endl; - //plot_inliers(seg, image, short_segments[i], tmp_i); - tmp_i++; - //plot_inliers(seg, image, short_segments[j], tmp_i); - tmp_i++; - - cout << "J " << j << " size " << short_segments[j].size() << endl; - - for(int k = 0; k < short_segments[j].size(); k++){ - short_segments[i].push_back(short_segments[j][k]); - } + if(abs(abs(grad_j)-abs(grad_i)) < 0.5){ + //cout << "OK " << js << " - gradient diff:\t" << abs(grad_j-grad_i) << endl; + //cout << grad_i << " vs " << grad_j << endl << endl; + //cout << a << endl << b << endl << c << endl << d << endl << endl; + // Add to map, we'll combine the closest segment to joined_segs - short_segments.erase(short_segments.begin()+j); - j = 0; + //if (other_dim_diff < 40){ + closest_index[dist] = j; + // other_dimension[j] = other_dim_diff; + //} - //printf("--Segement i end points Y= %d and %d\n",largest_y_value(short_segments[i]),smallest_y_value(short_segments[i])); - //printf("--Segement i end points X= %d and %d\n",largest_x_value(short_segments[i]),smallest_x_value(short_segments[i])); - - plot_inliers(jseg, image, short_segments[i], js); - js++; + //plot_inliers(jseg, image, joined_segs, js); + //js++; + }else{ + //cout << "Gradients differ too much:\t" << abs(abs(grad_j)-abs(grad_i)) << endl; + //cout << grad_i << " vs " << grad_j << endl << endl; + } + }else{ + if (dist > limit){ + //cout << "Dist " << dist << " > " << limit << endl << endl; }else{ - cout << "Gradients differ by more than 25%" << endl << endl; - } - }else{ - cout << "Lines overlap." << endl << endl; + //cout << "Lines overlap." << endl << endl; + } } }else{ - cout << "Lines too far away:\t" << i << " vs " << j << endl << endl; - //cout << a << endl << b << endl << c << endl << d << endl; + //cout << "Lines don't seem to have the same orientation." << endl << endl; } - - + } + + // Add joined_seq to lines vector if it's long enough + if(joined_segs.size() > original_line_size && closest_index.size() == 0){ + double length_sq; + int i_x_max = max_x_index(joined_segs); + int i_x_min = min_x_index(joined_segs); + int i_y_max = max_y_index(joined_segs); + int i_y_min = min_y_index(joined_segs); + if(abs(i_x_max - i_x_min) > abs(i_y_max - i_y_min)){ + length_sq = point_line_length_squared(joined_segs[i_x_max],joined_segs[i_x_min]); + }else{ + length_sq = point_line_length_squared(joined_segs[i_y_max],joined_segs[i_y_min]); + } + if(length_sq >= min_line_length_squared){ + //plot_inliers(jseg, image, joined_segs, js); + lines.push_back(joined_segs); + good_lines++; + js++; + }else{ + //plot_inliers(jseg, image, joined_segs, js); } - - } - } - - for(int i = 0; i < short_segments.size(); i++){ - double length_sq = point_line_length_squared(short_segments[i][0],short_segments[i][short_segments[i].size()-1]); - if(length_sq >= min_line_length_squared){ - //plot_inliers(jseg, image, short_segments[i], js); - //js++; - } - //plot_inliers(jseg, image, short_segments[i], js); - //js++; - } - + } + count++; + } } void process_image(string& filename, int& plotted){ @@ -1275,15 +1340,14 @@ original_width = info.width(); original_height = info.height(); - int exif_ok = get_exif_data(filename); - - /* + //int exif_ok = get_exif_data(filename); + if (focal_length && cropFactor){ calculate_focal_length_pixels(); }else{ int exif_ok = get_exif_data(filename); } - */ + if (nw > nh){ @@ -1343,7 +1407,10 @@ } - //join_short_segments(short_segments,image); + if(short_segments.size()){ + cout << "Joining segments..." << endl << endl; + join_short_segments(short_segments,good_lines,image); + } short_segments.clear(); // Sort lines by distance between first and last point or number of pixels This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-08-05 18:02:30
|
Revision: 4172 http://hugin.svn.sourceforge.net/hugin/?rev=4172&view=rev Author: blimbo Date: 2009-08-05 18:02:23 +0000 (Wed, 05 Aug 2009) Log Message: ----------- Segment joining function works well, added vertical line straightener for Bruno - try ./calibrate_lens -w 1 vertical_rotate_test_7.3.jpg Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/CMakeLists.txt hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h Added Paths: ----------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/vertical_rotate_test_7.3.jpg Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/CMakeLists.txt =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/CMakeLists.txt 2009-08-05 17:45:43 UTC (rev 4171) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/CMakeLists.txt 2009-08-05 18:02:23 UTC (rev 4172) @@ -1,13 +1,9 @@ ADD_EXECUTABLE(calibrate_lens Main.cpp Globals.cpp -#PointLineDist.cpp MapPoints.cpp ProcessImage.cpp -#LineParamEstimator.cpp -#PolynomialEstimator.cpp -#SplineEstimator.cpp -#Spline.cpp +Straighten.cpp lensFunc.cpp HermiteSpline.c ) Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-08-05 17:45:43 UTC (rev 4171) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-08-05 18:02:23 UTC (rev 4172) @@ -30,6 +30,7 @@ unsigned int current_line = 0; unsigned int optimise_centre = 1; unsigned int poly_type = 1; +unsigned int straighten_verts = 0; double sensor_width = 0; double sensor_height = 0; double original_width = 0; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-08-05 17:45:43 UTC (rev 4171) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-08-05 18:02:23 UTC (rev 4172) @@ -13,6 +13,7 @@ extern unsigned int current_line; extern unsigned int optimise_centre; extern unsigned int poly_type; +extern unsigned int straighten_verts; extern double sensor_width; extern double sensor_height; extern double original_width; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-08-05 17:45:43 UTC (rev 4171) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-08-05 18:02:23 UTC (rev 4172) @@ -26,6 +26,7 @@ #include "ProcessImage.h" #include "vigra/diff2d.hxx" #include "MapPoints.h" +#include "Straighten.h" using namespace std; @@ -452,6 +453,7 @@ //cout << " -i <0|1> Generate intermediate images. Default 1" << endl; cout << " -z <0|1> Optimise image centre. Default 1" << endl; + cout << " -w <0|1> Straighten image using vertical lines. Skips lens optimisation. Default 0" << endl; cout << " -v <0|1> Verbose. Default 0" << endl; cout << " -h Print usage." << endl; cout << endl; @@ -496,6 +498,7 @@ case 'x' : {poly_type = atoi(argv[i]); break;} case 'z' : {optimise_centre = atoi(argv[i]); break;} case 'v' : {verbose = atoi(argv[i]); break;} + case 'w' : {straighten_verts = atoi(argv[i]); break;} case 'd' : {resize_dimension = atoi(argv[i]); break;} //case 's' : {scale = atof(argv[i]); break;} case 's' : {cropFactor = 24.0/atof(argv[i]); break;} @@ -580,18 +583,29 @@ /* for (int i = 0; i < lines.size(); i++){ for (int j = 0; j < lines[i].size(); j++){ cout << "_" << i << "," << lines[i][j]->x << "," << lines[i][j]->y << endl; } } cout << endl; */ - if (lines.size() >= n_params ){ - // Write lines to output file - if (images.size()){ - write_lines_to_file(images[0],images[images.size()-1]); - } - // Map points and optimise parameters - map_points(); - }else{ - cout << "Not enough lines to fit "<< n_params <<" parameters. "<< endl << endl; - return 3; + + if(!straighten_verts){ + + if (lines.size() >= n_params ){ + // Write lines to output file + if (images.size()){ + write_lines_to_file(images[0],images[images.size()-1]); + } + // Map points and optimise parameters + map_points(); + }else{ + cout << "Not enough lines to fit "<< n_params <<" parameters. "<< endl << endl; + return 3; + } } + // Attempt to straighten image + if (lines.size() && straighten_verts){ + double angle = straighten(); + cout << "Rotate image by " << angle << " degrees." << endl; + } + + if (pto_file != ("")){ write_pto(output_pto,pto_file_top,pto_file_cps,pto_file_end,pto_image,cps_per_line,lines_to_image_number); cout << endl << "Written file " << output_pto << endl; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-05 17:45:43 UTC (rev 4171) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-05 18:02:23 UTC (rev 4172) @@ -508,7 +508,7 @@ if(verbose) cout << "Above theshold (" << min_line_length_squared << ")" << endl; }else{ // Collect shorter segments - if(length_sq >= min_line_length_squared/10){ + if(length_sq >= min_line_length_squared/20){ short_segments.push_back(inliers); } inliers.clear(); @@ -802,8 +802,10 @@ cout << "Pixel density (pixels/mm):\t" << pixels_per_mm << endl; }else{ // Need command line param - cout << endl << "Could not identify crop factor from EXIF data. Please provide it as a command line parameter with the -c flag." << endl << endl; - exit(1); + if(!straighten_verts){ + cout << endl << "Could not identify crop factor from EXIF data. Please provide it as a command line parameter with the -c flag." << endl << endl; + exit(1); + } } if (focal_length != 0){ @@ -814,8 +816,10 @@ cout << "Focal length (pixels):\t\t" << focal_length_pixels << endl << endl; }else{ // Need command line param - cout << endl << "Could not identify focal length from EXIF data. Please provide it as a command line parameter with the -f flag." << endl << endl; - exit(1); + if(!straighten_verts){ + cout << endl << "Could not identify focal length from EXIF data. Please provide it as a command line parameter with the -f flag." << endl << endl; + exit(1); + } } } @@ -843,22 +847,28 @@ try { image = Exiv2::ImageFactory::open(filename.c_str()); }catch(...) { - cout << "Error opening file " << filename << endl; - cout << "Please provide crop factor and focal length values via command line parameters." << endl << endl; - exit(1); + if(!straighten_verts){ + cout << "Error opening file " << filename << endl; + cout << "Please provide crop factor and focal length values via command line parameters." << endl << endl; + exit(1); + } } if (image.get() == 0) { - cout << "Unable to open file " << filename << " to read EXIF data." << endl; - cout << "Please provide crop factor and focal length values via command line parameters." << endl << endl; - exit(1); + if(!straighten_verts){ + cout << "Unable to open file " << filename << " to read EXIF data." << endl; + cout << "Please provide crop factor and focal length values via command line parameters." << endl << endl; + exit(1); + } } image->readMetadata(); Exiv2::ExifData &exifData = image->exifData(); if (exifData.empty()) { - cout << "Unable to read EXIF data from file " << filename << endl; - cout << "Please provide crop factor and focal length values via command line parameters." << endl << endl; - exit(1); + if(!straighten_verts){ + cout << "Unable to read EXIF data from file " << filename << endl; + cout << "Please provide crop factor and focal length values via command line parameters." << endl << endl; + exit(1); + } } long eWidth = 0; @@ -1135,44 +1145,59 @@ double d1 = a[max_x]->x - a[min_x]->x; double d2 = a[max_y]->y - a[min_y]->y; double grad = d2/d1; + return(grad); +} + +double inv_gradient(vector<Point2D>& a){ - //cout << a[0]->x << " - " << a[a.size()-1]->x << " = " << d1 << endl; - //cout << a[0]->y<< " - " << a[a.size()-1]->y <<" = " << d2 << endl; - //cout << "Gradient:\t" << grad << endl << endl; - + int max_x = max_x_index(a); + int min_x = min_x_index(a); + int max_y = max_y_index(a); + int min_y = min_y_index(a); + double d1 = a[max_x]->x - a[min_x]->x; + double d2 = a[max_y]->y - a[min_y]->y; + double grad = d1/d2; return(grad); } void join_short_segments(vector<vector<Point2D> >& short_segments, unsigned int& good_lines, BImage& image){ + /* string jseg("joined_"); - string seg("seg_"); - int js = 0; - int limit = 800; - - /* + string seg("seg_"); for(int i = 0; i < short_segments.size(); i++){ plot_inliers(seg, image, short_segments[i], i); - cout << "Gradient:\t" << gradient(short_segments[i]) << endl; + //cout << "Gradient:\t" << gradient(short_segments[i]) << endl; } */ + int js = 0; + + // Distance squared that two segments can be separated by + int limit = 1000; + + // Max difference allowed between gradients of two lines + double gradient_diff = 0.5; + + // For horizontal lines, max difference in y coordinate between closest points + // and in x coordinate for vertical lines + double diff = 4; + vector<Point2D> joined_segs; map<double,int> closest_index; - //map<int,int> other_dimension; int count = 0, original_line_size = 0; - while(short_segments.size() > 0){ + while(short_segments.size()){ // Of the close segments found, add the closest segment to joined_segs if(closest_index.size()){ - int j = 0; + int j = 0, c = 0; map<double,int>::iterator it_h1; for (it_h1 = closest_index.begin(); it_h1 != closest_index.end(); it_h1++){ - if(!j){ + if(!c){ //cout << js << " Dist:\t" << (*it_h1).first<< endl; - //cout << "Other dimension:\t" << other_dimension[j] << endl; j = (*it_h1).second; } + c++; } for(int k = 0; k < short_segments[j].size(); k++){ @@ -1180,7 +1205,6 @@ } short_segments.erase(short_segments.begin()+j); closest_index.clear(); - //other_dimension.clear(); }else{ joined_segs = short_segments[0]; original_line_size = joined_segs.size(); @@ -1202,37 +1226,30 @@ int j_y_max = max_y_index(short_segments[j]); int j_y_min = min_y_index(short_segments[j]); - //printf("i: x_min: %d y_min: %d --- x_max: %d y_max: %d\n",joined_segs[i_x_min]->x,joined_segs[i_y_min]->y,joined_segs[i_x_max]->x,joined_segs[i_y_max]->y); - //printf("j: x_min: %d y_min: %d --- x_max: %d y_max: %d\n",short_segments[j][j_x_min]->x,short_segments[j][j_y_min]->y,short_segments[j][j_x_max]->x,short_segments[j][j_y_max]->y); - // Check to see if lines overlap on x or y axes int overlaps = 0; int i_horiz = 0, j_horiz = 0;; - //int other_dim_diff; + int other_dim_diff; if(abs(joined_segs[i_x_max]->x - joined_segs[i_x_min]->x) > abs(joined_segs[i_y_max]->y - joined_segs[i_y_min]->y)){ i_horiz = 1; // Horizontal line if (joined_segs[i_x_max]->x > short_segments[j][j_x_max]->x){ if(short_segments[j][j_x_max]->x > joined_segs[i_x_min]->x) overlaps = 1; - - //other_dim_diff = abs(short_segments[j][j_x_max]->y - joined_segs[i_x_min]->x); + other_dim_diff = abs(short_segments[j][j_x_max]->y - joined_segs[i_x_min]->y); }else{ if(joined_segs[i_x_max]->x > short_segments[j][j_x_min]->x) overlaps = 1; - - //other_dim_diff = abs(joined_segs[i_x_max]->y - short_segments[j][j_x_min]->y); + other_dim_diff = abs(joined_segs[i_x_max]->y - short_segments[j][j_x_min]->y); } }else{ // Vertical line if (joined_segs[i_y_max]->y > short_segments[j][j_y_max]->y){ - if(short_segments[j][j_y_max]->y > joined_segs[i_y_min]->y) overlaps = 1; - - //other_dim_diff = abs(short_segments[j][j_y_max]->x - joined_segs[i_y_min]->x); + if(short_segments[j][j_y_max]->y > joined_segs[i_y_min]->y) overlaps = 1; + other_dim_diff = abs(short_segments[j][j_y_max]->x - joined_segs[i_y_min]->x); }else{ - if(joined_segs[i_y_max]->y > short_segments[j][j_y_min]->y) overlaps = 1; - - //other_dim_diff = abs(joined_segs[i_y_max]->x - short_segments[j][j_y_min]->x); + if(joined_segs[i_y_max]->y > short_segments[j][j_y_min]->y) overlaps = 1; + other_dim_diff = abs(joined_segs[i_y_max]->x - short_segments[j][j_y_min]->x); } } @@ -1262,19 +1279,36 @@ // Add this segment index to closest_index if it doesn't overlap and is close enough if(!overlaps && dist < limit){ // Check to make sure segment gradients are similar - double grad_i = gradient(joined_segs); - double grad_j = gradient(short_segments[j]); + // Differences in vertical line gradients can be huge so invert them + double grad_i,grad_j; + if(i_horiz == 1){ + grad_i = gradient(joined_segs); + grad_j = gradient(short_segments[j]); + }else{ + grad_i = inv_gradient(joined_segs); + grad_j = inv_gradient(short_segments[j]); + } + - if(abs(abs(grad_j)-abs(grad_i)) < 0.5){ + if(abs(abs(grad_j)-abs(grad_i)) < gradient_diff){ //cout << "OK " << js << " - gradient diff:\t" << abs(grad_j-grad_i) << endl; //cout << grad_i << " vs " << grad_j << endl << endl; //cout << a << endl << b << endl << c << endl << d << endl << endl; // Add to map, we'll combine the closest segment to joined_segs + + //closest_index[dist] = j; + + if(other_dim_diff <= diff){ + closest_index[(double)other_dim_diff] = j; + } - //if (other_dim_diff < 40){ - closest_index[dist] = j; - // other_dimension[j] = other_dim_diff; - //} + /* + printf("i: x_min: %d y_min: %d --- x_max: %d y_max: %d\n",joined_segs[i_x_min]->x,joined_segs[i_y_min]->y,joined_segs[i_x_max]->x,joined_segs[i_y_max]->y); + printf("j: x_min: %d y_min: %d --- x_max: %d y_max: %d\n",short_segments[j][j_x_min]->x,short_segments[j][j_y_min]->y,short_segments[j][j_x_max]->x,short_segments[j][j_y_max]->y); + cout << "other_dimension:\t" << other_dim_diff << endl; + cout << "gradients:\t" << grad_i << " vs " << grad_j << endl; + cout << "dist:\t" << dist << "--------------" << endl << endl; + */ //plot_inliers(jseg, image, joined_segs, js); //js++; @@ -1311,8 +1345,6 @@ lines.push_back(joined_segs); good_lines++; js++; - }else{ - //plot_inliers(jseg, image, joined_segs, js); } } count++; @@ -1347,9 +1379,7 @@ }else{ int exif_ok = get_exif_data(filename); } - - - + if (nw > nh){ min_line_length_squared = (length_threshold*nw)*(length_threshold*nw); }else{ Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-08-05 17:45:43 UTC (rev 4171) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.h 2009-08-05 18:02:23 UTC (rev 4172) @@ -19,5 +19,9 @@ void process_image(std::string&, int&);void sort_lines_by_length(); bool compare_line_length(std::vector<vigra::Point2D>, std::vector<vigra::Point2D>); void generate_boundary_tensor(vigra::BImage&, vigra::FVector2Image&, vigra::FImage&, std::string&); +int min_x_index(std::vector<vigra::Point2D>&); +int max_x_index(std::vector<vigra::Point2D>&); +int min_y_index(std::vector<vigra::Point2D>&); +int max_y_index(std::vector<vigra::Point2D>&); #endif Added: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/vertical_rotate_test_7.3.jpg =================================================================== (Binary files differ) Property changes on: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/vertical_rotate_test_7.3.jpg ___________________________________________________________________ Added: svn:mime-type + application/octet-stream This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-08-05 20:28:58
|
Revision: 4173 http://hugin.svn.sourceforge.net/hugin/?rev=4173&view=rev Author: blimbo Date: 2009-08-05 20:28:49 +0000 (Wed, 05 Aug 2009) Log Message: ----------- Added missing files Added Paths: ----------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.h Added: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.cpp (rev 0) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.cpp 2009-08-05 20:28:49 UTC (rev 4173) @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2009 by Tim Nugent * + * tim...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <map> +#include "Globals.h" +#include "ProcessImage.h" + +using namespace std; + +double straighten(){ + + double invert_size_factor = 1.0/sizefactor; + double best_angle = 0, best_score = 10000000; + map<double,double> best_rotation; + + cout << "Finding optimal rotation angle..." << endl; + for(double angle = -90; angle < 90; angle += 0.25){ + + double radians = angle*(M_PI/180); + //cout << "Degrees:\t" << angle << "\tRadians:\t" << radians << endl; + double total_x_diff = 0; + + for(int i = 0; i < lines.size(); i++){ + + // Get indexes of max/min x and y points + int i_x_max = max_x_index(lines[i]); + int i_x_min = min_x_index(lines[i]); + int i_y_max = max_y_index(lines[i]); + int i_y_min = min_y_index(lines[i]); + int x_diff = lines[i][i_x_max]->x - lines[i][i_x_min]->x; + int y_diff = lines[i][i_y_max]->y - lines[i][i_y_min]->y; + + // Vertical line + if(y_diff > x_diff){ + + // Index for coords of top of line + double y_max_y = invert_size_factor * lines[i][i_y_max]->y; + double y_max_x = invert_size_factor * lines[i][i_y_max]->x; + // Index for coords of bottom of line + double y_min_y = invert_size_factor * lines[i][i_y_min]->y; + double y_min_x = invert_size_factor * lines[i][i_y_min]->x; + + // Move so 0,0 is centre (of rotation) + y_max_y -= original_height/2; + y_max_y *= -1; + y_max_x -= original_width/2; + + y_min_y -= original_height/2; + y_min_y *= -1; + y_min_x -= original_width/2; + + // New position after rotating + double rotated_y_max_x = (y_max_x * cos(radians)) - (y_max_y * sin(radians)); + + // New position after rotating + double rotated_y_min_x = (y_min_x * cos(radians)) - (y_min_y * sin(radians)); + + total_x_diff += fabs(rotated_y_max_x-rotated_y_min_x); + } + } + + //cout << angle << "\tTotal:\t" << total_x_diff << endl; + + best_rotation[angle] = total_x_diff; + total_x_diff = 0; + } + for(double angle = -90; angle < 90; angle += 0.25){ + //cout << angle << "\tdegrees - Score:\t" << best_rotation[angle] << endl; + if(best_rotation[angle] < best_score){ + best_score = best_rotation[angle]; + best_angle = angle; + } + } + cout << endl; + return(-best_angle); +} Added: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.h (rev 0) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.h 2009-08-05 20:28:49 UTC (rev 4173) @@ -0,0 +1,6 @@ +#ifndef STRAIGHTEN_H +#define STRAIGHTEN_H + +double straighten(); + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-08-06 15:00:20
|
Revision: 4177 http://hugin.svn.sourceforge.net/hugin/?rev=4177&view=rev Author: blimbo Date: 2009-08-06 15:00:12 +0000 (Thu, 06 Aug 2009) Log Message: ----------- Added ShortStraw Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-08-06 14:48:02 UTC (rev 4176) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-08-06 15:00:12 UTC (rev 4177) @@ -30,6 +30,7 @@ unsigned int current_line = 0; unsigned int optimise_centre = 1; unsigned int poly_type = 1; +unsigned int ss = 0; unsigned int straighten_verts = 0; double sensor_width = 0; double sensor_height = 0; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-08-06 14:48:02 UTC (rev 4176) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-08-06 15:00:12 UTC (rev 4177) @@ -14,6 +14,7 @@ extern unsigned int optimise_centre; extern unsigned int poly_type; extern unsigned int straighten_verts; +extern unsigned int ss; extern double sensor_width; extern double sensor_height; extern double original_width; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-08-06 14:48:02 UTC (rev 4176) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-08-06 15:00:12 UTC (rev 4177) @@ -424,7 +424,8 @@ cout << " -e <int> Edge detector. 1 = Canny (default)" << endl; cout << " 2 = Shen-Castan" << endl; cout << " 3 = Boundary tensor" << endl; - cout << " -d <int> Maximum dimension for re-sized image prior to processing. Default 1600." << endl; + cout << " -a <int> Use ShortStraw algorithm instead of boundary tensor. Default 0" << endl; + cout << " -d <int> Maximum dimension for re-sized image prior to processing. Default 1600" << endl; //cout << " -f <string> Output file format. Default .JPG" << endl; cout << " -o <path> Output path. Default output/" << endl; //cout << " -s <float> Edge detector scale. Default 2" << endl; @@ -437,7 +438,7 @@ cout << " -y <float> Corner threshold. Default 150" << endl; //cout << " -i <float> Pixel density in pixels/inch. Default 4000" << endl; cout << " -f <float> Focal length (mm). Read from EXIF data." << endl; - cout << " -c <int> Crop factor. Read/calculated from EXIF data." << endl; + cout << " -c <float Crop factor. Read/calculated from EXIF data." << endl; cout << " -s <float> Shortest dimension of sensor (mm), used to calculate crop factor." << endl; cout << " -l <int> Lens model 1 = Rectilinear (default)" << endl; cout << " 2 = Equal-area fisheye" << endl; @@ -503,7 +504,8 @@ //case 's' : {scale = atof(argv[i]); break;} case 's' : {cropFactor = 24.0/atof(argv[i]); break;} //case 'b' : {tscale = atof(argv[i]); break;} - case 'a' : {a = atof(argv[i]); break;} + //case 'a' : {a = atof(argv[i]); break;} + case 'a' : {ss = atoi(argv[i]); break;} case 't' : {threshold = atof(argv[i]); break;} case 'b' : {bt_threshold = atof(argv[i]); break;} case 'y' : {corner_threshold = atof(argv[i]); break;} @@ -580,10 +582,7 @@ cout << "Found "<< lines.size() <<" lines."<< endl << endl; int n_params = 2; if (lens_type == 2) ++n_params; if (optimise_centre) n_params += 2; - /* for (int i = 0; i < lines.size(); i++){ - for (int j = 0; j < lines[i].size(); j++){ - cout << "_" << i << "," << lines[i][j]->x << "," << lines[i][j]->y << endl; } } cout << endl; */ - + if(!straighten_verts){ if (lines.size() >= n_params ){ @@ -610,8 +609,7 @@ write_pto(output_pto,pto_file_top,pto_file_cps,pto_file_end,pto_image,cps_per_line,lines_to_image_number); cout << endl << "Written file " << output_pto << endl; } - - cout << endl; + //cout << endl; return(1); } Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-06 14:48:02 UTC (rev 4176) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-06 15:00:12 UTC (rev 4177) @@ -1081,11 +1081,10 @@ } double point_line_length_squared(Point2D& a, Point2D& b){ + //cout << a->x << " - " << b->x << " = " << a->x - b->x << endl; + //cout << a->y<< " - " << b->y <<" = " << a->y - b->y << endl; int d1 = a->x - b->x; int d2 = a->y - b->y; - //cout << a->x << " - " << b->x << " = " << d1 << endl; - //cout << a->y<< " - " << b->y <<" = " << d2 << endl; - //cout << "Dist^2:\t" << (d1*d1+d2*d2) << endl << endl; return(d1*d1+d2*d2); } @@ -1351,6 +1350,236 @@ } } + +double path_distance(vector<Point2D>& coords, int& a, int& b){ + double d = 0; + for (unsigned int i = a; i < b; i++){ + //cout <<"From path_dist - point_line_length_squared " << i << "-" << i+1 << endl; + //if(a < coords.size() && b < coords.size()){ + + d += point_line_length_squared(coords[i],coords[i+1]); + //}else{ + // cout << a << "-" << b << " path_dist, size = " << coords.size() << " " << i << " " << i+1<< " : " << coords[i]->x << "-" << coords[i]->y << "--->" << coords[i+1]->x << "," << coords[i+1]->y << endl; + // d += point_line_length_squared(coords[i],coords[i+1]); + //} + } + return(d); +} + + +bool is_line(vector<Point2D>& coords, int& a, int& b){ + double threshold = 0.95; + //cout <<"From is_line - point_line_length_squared " << a << "-" << b << endl; + double distance = sqrt(point_line_length_squared(coords[a],coords[b])); + double path_dist = path_distance(coords,a,b); + if(distance/path_dist > threshold){ + return(true); + }else{ + return(false); + } +} + +int halfway_corners(vector<double>& straws, int& a, int& b){ + int quarter = (b-a)/4; + int MinIndex; + double MinValue = 100000000; + for (unsigned int i = a+quarter; i < b-quarter; i++){ + if(straws[i] < MinValue){ + MinValue = straws[i]; + MinIndex = i; + } + } + return(MinIndex); +} + +double sample_spacing(vector<Point2D>& coords){ + int x_max = max_x_index(coords); + int x_min = min_x_index(coords); + int y_max = max_y_index(coords); + int y_min = min_y_index(coords); + Point2D top_left(coords[x_min]->x,coords[y_min]->y); + Point2D bottom_right(coords[x_max]->x,coords[y_max]->y); + return(sqrt(point_line_length_squared(top_left,bottom_right)/40.0)); +} + +void resample(vector<Point2D>& coords, vector<Point2D>& resampled, double& s){ + double D = 0; + resampled.push_back(coords[0]); + for (unsigned int i = 1; i < coords.size(); i++){ + double d = sqrt(point_line_length_squared(coords[i-1],coords[i])); + if (d+D >= s){ + Point2D q; + // Need to cast to int + q.x = (int)(coords[i-1]->x + ((s-D)/d) * (coords[i]->x - coords[i-1]->x)); + q.y = (int)(coords[i-1]->y + ((s-D)/d) * (coords[i]->y - coords[i-1]->y)); + resampled.push_back(q); + vector<Point2D>::iterator it = coords.begin();; + coords.insert(it+i,q); + D = 0; + }else{ + D += d; + } + } +} + +void short_straw(BImage& image, vector<Point2D>& coords, string& filename){ + + vector<Point2D> coords_original = coords;; + vector<Point2D> points; + + // Resample points? + if(0){ + cout << "Resampling points.." << endl; + double s = sample_spacing(coords); + vector<Point2D> resampled; + resample(coords,resampled,s); + points = resampled; + }else{ + points = coords; + } + + vector<int> corners,processed_corners; + corners.push_back(0); + int w = 3; + vector<double> straws, sorted_straws; + + for (unsigned int i = w; i < points.size() - w; i++){ + straws.push_back(sqrt(point_line_length_squared(points[i-w],points[i+w]))); + } + sorted_straws = straws; + sort (sorted_straws.begin(),sorted_straws.end()); + + double median_t; + int middle_one,middle_two; + + if ((sorted_straws.size() % 2) == 0){ + middle_one = (sorted_straws.size()/2); + middle_two = (sorted_straws.size()/2)+1; + median_t = (sorted_straws[middle_one-1] + sorted_straws[middle_two-1])/2; + }else{ + middle_one = (sorted_straws.size()/2)+1; + median_t = sorted_straws[middle_one-1]; + } + median_t *= 0.95; + + double localMin; + int localMinIndex; + // Get corners + for (unsigned int i = w; i < points.size() - w; i++){ + if(straws[i] < median_t){ + localMin = 100000000; + localMinIndex = i; + while(i < straws.size() && straws[i] < median_t){ + if(straws[i] < localMin){ + localMin = straws[i]; + localMinIndex = i; + } + i++; + } + corners.push_back(localMinIndex); + } + } + //corners.push_back(points.size()); + + if(0){ + + // Post-process corners + cout << "Post-processing corners..." << endl; + bool cont = false; + while(!cont){ + cont = true; + for (unsigned int i = 1; i < corners.size(); i++){ + cout << i << "/" << corners.size() << endl; + int c1 = corners[i-1]; + int c2 = corners[i]; + if(!is_line(points,c1,c2)){ + int newcorner = halfway_corners(straws,c1,c2); + vector<int>::iterator it = corners.begin(); + corners.insert(it+i,newcorner); + cont = false; + } + } + } + cout << " Retaining good corners..." << endl; + for (unsigned int i = 1; i <corners.size()-1; i++){ + int c1 = corners[i-1]; + int c2 = corners[i+1]; + if(!is_line(points,c1,c2)){ + processed_corners.push_back(i); + } + } + corners = processed_corners; + } + + // Write files/remove corners + BImage ss_corners(image.width(), image.height()); + ss_corners = 255; + + for (unsigned int i = w; i < corners.size() - w; i++){ + + int w = coords_original[corners[i]]->x; + int h = coords_original[corners[i]]->y; + + // Change the size of the box to draw around corner pixel + int size = 3; + int left = w-size; + int top = h-size; + int right = w+size; + int bottom = h+size; + + if(left<0) left = 0; + if(right>image.width()) right = image.width(); + if(top<0) top = 0; + if(bottom > image.height()) bottom = image.height(); + + // Draw a white box around the corner pixel + // in the edge image + vigra::initImage(srcIterRange(ss_corners.upperLeft() + + vigra::Diff2D(left, top), + ss_corners.upperLeft() + vigra::Diff2D(right, bottom)), + 0 ); + + vigra::initImage(srcIterRange(image.upperLeft() + + vigra::Diff2D(left, top), + image.upperLeft() + vigra::Diff2D(right, bottom)), + 255 ); + + } + + if (generate_images){ + + string output = path; + vector<string> tokens; + + // *nix file paths + if (filename.find("/") < filename.length() || filename.substr(0, 1) == ("/")){ + tokenize(filename, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } + string output_minus_ss_corners = output; + output.append("_short_straw_corners"); + output.append(format); + + //if(!fileexists(output)){ + cout << "Writing " << output << endl; + exportImage(srcImageRange(ss_corners), ImageExportInfo(output.c_str()).setPixelType("UINT8")); + //} + + + output_minus_ss_corners.append("_minus_short_straw_corners"); + output_minus_ss_corners.append(format); + + //if(!fileexists(output)){ + cout << "Writing " << output_minus_ss_corners << endl << endl; + exportImage(srcImageRange(image), ImageExportInfo(output_minus_ss_corners.c_str()).setPixelType("UINT8")); + //} + } +} + void process_image(string& filename, int& plotted){ ImageImportInfo info(filename.c_str()); @@ -1405,15 +1634,22 @@ image = grey; } - // Generate boundary tensor - generate_boundary_tensor(image, edgeness, cornerness, filename); + // Run short straw corner finding algorithm + if(ss){ + cout << "Running ShortStraw corner finder..." << endl; + extract_coords(image, coords); + short_straw(image, coords, filename); + coords.clear(); + }else{ + // Generate boundary tensor + generate_boundary_tensor(image, edgeness, cornerness, filename); + // Remove corners + nuke_corners(image, cornerness, filename); + } - // Remove corners - nuke_corners(image, cornerness, filename); - // Get coordinates extract_coords(image, coords); - + unsigned int intital_coords_size = coords.size(); if(verbose) cout << "Initial 'edge' pixel count:\t" << coords.size() << endl << endl; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.cpp 2009-08-06 14:48:02 UTC (rev 4176) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Straighten.cpp 2009-08-06 15:00:12 UTC (rev 4177) @@ -28,7 +28,7 @@ double invert_size_factor = 1.0/sizefactor; double best_angle = 0, best_score = 10000000; - map<double,double> best_rotation; + //map<double,double> best_rotation; cout << "Finding optimal rotation angle..." << endl; for(double angle = -90; angle < 90; angle += 0.25){ @@ -77,17 +77,18 @@ } //cout << angle << "\tTotal:\t" << total_x_diff << endl; - - best_rotation[angle] = total_x_diff; + + if(total_x_diff < best_score){ + best_score = total_x_diff; + best_angle = angle; + } + //best_rotation[angle] = total_x_diff; total_x_diff = 0; } - for(double angle = -90; angle < 90; angle += 0.25){ - //cout << angle << "\tdegrees - Score:\t" << best_rotation[angle] << endl; - if(best_rotation[angle] < best_score){ - best_score = best_rotation[angle]; - best_angle = angle; - } - } - cout << endl; + //for(double angle = -90; angle < 90; angle += 0.25){ + // cout << angle << "\tdegrees - Score:\t" << best_rotation[angle] << endl; + + //} + //cout << endl; return(-best_angle); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tks...@us...> - 2009-08-09 03:23:14
|
Revision: 4188 http://hugin.svn.sourceforge.net/hugin/?rev=4188&view=rev Author: tksharpless Date: 2009-08-09 03:23:05 +0000 (Sun, 09 Aug 2009) Log Message: ----------- Add fast low level line finder -- not quite right yet. Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp Added Paths: ----------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.h Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-08 22:25:32 UTC (rev 4187) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-09 03:23:05 UTC (rev 4188) @@ -43,6 +43,8 @@ #include "MapPoints.h" #include <ANN/ANN.h> +#include "find_N8_lines.h" + #if _MSC_VER //def _WIN32 #include <time.h> #endif @@ -213,6 +215,52 @@ } } +void plot_lines(string& filename, BImage& image, vector<vector<Point2D>>& lines, + int i, int j ){ + + vigra::BRGBImage tmp(image.width(),image.height()); + vigra::initImage(srcIterRange(tmp.upperLeft(), + tmp.upperLeft() + vigra::Diff2D(image.width(),image.height())), + RGB(255,255,255) ); + for( unsigned iln = i; iln < j; iln++ ){ + vector<Point2D> & inliers = lines.at( iln ); + for (unsigned int il = 0; il < inliers.size(); il++){ + vigra::initImage(srcIterRange(tmp.upperLeft() + vigra::Diff2D(inliers[il]->x, inliers[il]->y), + tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+1, inliers[il]->y+1)), + RGB(255,0,0) ); + + // Make end point green + if(il == 0 || il == inliers.size()-1)vigra::initImage(srcIterRange(tmp.upperLeft() + + vigra::Diff2D(inliers[il]->x, inliers[il]->y), + tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+1, inliers[il]->y+1)), + RGB(0,255,0) ); + + } + } + + string output = path; + vector<string> tokens; + + // *nix file paths + if (filename.find("/") < filename.length() || filename.substr(0, 1) == ("/")){ + tokenize(filename, tokens, "/"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + // Windows file paths + }else{ + tokenize(filename, tokens, "\\"); + output.append(tokens[tokens.size()-1].substr(0,tokens[tokens.size()-1].length()-4)); + } + output.append("_line_"); + stringstream ii; + ii << i+1 <<"-"<<j+1; + output.append(ii.str()); + output.append(format); + + cout << "Plotting lines " << i+1 << " thru " << j+1 << endl; + exportImage(srcImageRange(tmp), ImageExportInfo(output.c_str()).setPixelType("UINT8")); + +} + void find_ann(vector<Point2D>& coords, FVector2Image& edgeness, vector<Point2D>& inliers, unsigned int& good_lines, vector<vector<Point2D> >& short_segments){ int k = 1; // Number of nearest neighbours @@ -679,7 +727,7 @@ // Calculate the boundary tensor cout << "Calculating boundary tensor..." << endl; - boundaryTensor(srcImageRange(image), destImage(boundarytensor), tscale); + boundaryTensor1(srcImageRange(image), destImage(boundarytensor), tscale); tensorToEdgeCorner(srcImageRange(boundarytensor), destImage(edgeness), destImage(cornerness)); @@ -1622,6 +1670,7 @@ min_line_length_squared = (length_threshold*nh)*(length_threshold*nh); } + // Resize image resize_image(in, nw, nh); @@ -1629,10 +1678,7 @@ BImage grey(nw, nh); copyImage(srcImageRange(in, RGBToGrayAccessor<RGBValue<UInt16> >()), destImage(grey)); - BImage image(nw, nh); - FVector2Image edgeness(nw,nh); - FImage cornerness(nw, nh); - vector<Point2D> coords, inliers; + BImage image(nw, nh); // Run Canny edge detector if(detector != 3){ @@ -1640,7 +1686,39 @@ }else{ image = grey; } - +#if 1 // test find_N8_lines + + bool saveimages = true; // write debug pix + int lmin = 32; + double CtoAmin = 0.99; + + cout<<" edgeMap2linePts(saveimages "<<saveimages<<"): "; + int nsegs = edgeMap2linePts( image, saveimages ); + cout<<nsegs<<" segments"<<endl; + + cout<<" linePts2lineList(lmin "<<lmin<<" CtoAmin "<<CtoAmin<<") : "; + int nlines = linePts2lineList( image, lmin, CtoAmin, lines ); + cout<<nlines<<" lines"<<endl; + + if (nlines == 0){ + cout << "No lines found!" << endl << endl; + }else{ + cout << nlines << " lines found" << endl; + + int llp = lines.size() - 1; + plot_lines(filename, image, lines, plotted, llp ); + plotted = llp; + cout << endl; + } + + + +#else // original + + FVector2Image edgeness(nw,nh); + FImage cornerness(nw, nh); + vector<Point2D> coords, inliers; + // Run short straw corner finding algorithm if(ss){ cout << "Running ShortStraw corner finder..." << endl; @@ -1689,7 +1767,7 @@ // Sort lines by distance between first and last point or number of pixels // Problem if we're doing multiple images // Sort_lines_by_length(); - + if (good_lines == 0){ cout << "No lines found!" << endl << endl; }else{ @@ -1701,4 +1779,5 @@ } cout << endl; } +#endif // testing find_N8_lines } Added: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.cpp (rev 0) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.cpp 2009-08-09 03:23:05 UTC (rev 4188) @@ -0,0 +1,445 @@ +/* find_N8_lines.cpp + + find straightish, non-crossing lines in an edge map, + using 8-neighborhood operations. + + The input imge should be black edges on white background. + Y runs down, X right in normal viewing orientation. + + edgeMap2linePts() converts the edge map image into a line + points map: all white except for connected groups of points + that belong to unbranched line segments without sharp corners. + Returns number of segments. + + linePts2lineList() converts a line map image to a list of + lines that meet some selection criteria. The line list is a + vector of vectors of integer x,y pairs in vigra Point2D + sructs. The list vector is passed by caller, the point + vectors are created here. Returns the number of lines added. + + The line selection criteria are minimum size (in points ) and + a curvature limit, expressed as a chord/arc ratio (C/A is + 1 for a perfectly straight line and 0 for a closed curve). + minCtoA is the minimum acceptable for a whole line. Lines + in the input image will be broken into sections that don't + violate this criterion, by splitting at points of maximum + curvature. + +*/ +#include <assert.h> + +#include "find_N8_lines.h" +#include "vigra/impex.hxx" // debug image save + +using namespace vigra; +using namespace std; + +int +edgeMap2linePts( BImage & edge, bool save_images ){ + + int width = edge.width(), + height = edge.height(); + + BImage line( width, height ); + +// debug statistics + unsigned int npnts = 0, nends = 0, nmids = 0, + nelb = 0, nnhisto[15]; + for(int i = 0; i < 15; i++ ) nnhisto[i] = 0; + + BImage::traverser eul, lul; + +// erase border pixels of edge image + eul = edge.upperLeft(); + for(int x = 0; x < width; x++ ){ + eul(x,0) = N8_bg; + eul(x,height-1) = N8_bg; + } + for(int y = 1; y < height-1; y++ ){ + eul(0,y) = N8_bg; + eul(width-1,y) = N8_bg; + } + +/* first pass erases "elbow" points from edge image, + leaving only diagonal connections. An elbow point + has one horizontal and one vertical neighbor, and no + more than 4 neighbors in all. + +*/ + eul = edge.upperLeft() + Diff2D( 1, 1 ); + for(int y=1; y<height-1; ++y, ++eul.y ) + { + BImage::traverser ix = eul; + for(int x=1; x<width-1; ++x, ++ix.x ) + { + // center must be an edge point + if( *ix != N8_bg ){ + ++npnts; + int n = 0, z1 = 0, z2 = 0; + int nh = 0, nv = 0, nu = 0, nd = 0; + if( ix( 1, 0 ) != N8_bg ) ++nh, ++n; + if( ix( 1, -1 ) != N8_bg ) ++nu, ++n; + if( ix( 0, -1 ) != N8_bg ) ++nv, ++n; + if( ix( -1, -1 ) != N8_bg ) ++nd, ++n; + if( ix( -1, 0 ) != N8_bg ) ++nh, ++n; + if( ix( -1, 1 ) != N8_bg ) ++nu, ++n; + if( ix( 0, 1 ) != N8_bg ) ++nv, ++n; + if( ix( 1, 1 ) != N8_bg ) ++nd, ++n; + + ++nnhisto[n+1]; + + if( nh == 1 && nv == 1 && n > 1 && n < 5 ){ + ++nelb; + *ix = N8_bg; // clear this point + } + } + else ++nnhisto[0]; + } + } + + if( save_images ){ + ImageExportInfo eei( "output/zapElbows.tif" ); + eei.setCompression( "" ); + exportImage(srcImageRange(edge), eei ); + } + +/* second pass copies center points of 3x3 regions having line-like + configurations, to the temp image, marked with the orientation of + the inferred line. As a result of pass 1, these points will have + not more than 2 marked neighbors, in an oblique configuration. + Orientation codes 1 to 8 correspond to 22.5 degree increments + from horizontal. We multiply these by 20 to make the differences + visible on a debug image. + +*/ + eul = (edge.upperLeft() + Diff2D(1,1)); + lul = (line.upperLeft() + Diff2D(1,1)); + line.init(N8_bg); + + for(int y=1; y<height-1; ++y, ++eul.y, ++lul.y) + { + BImage::traverser ix = eul; + BImage::traverser ox = lul; + for(int x=1; x<width-1; ++x, ++ix.x, ++ox.x) + { + if( *ix != N8_bg ){ + int n = 0; + int nh = 0, nv = 0, nu = 0, nd = 0; + + if( ix( 1, 0 ) != N8_bg ) ++nh, ++n; + if( ix( 1, -1 ) != N8_bg ) ++nu, ++n; + if( ix( 0, -1 ) != N8_bg ) ++nv, ++n; + if( ix( -1, -1 ) != N8_bg ) ++nd, ++n; + if( ix( -1, 0 ) != N8_bg ) ++nh, ++n; + if( ix( -1, 1 ) != N8_bg ) ++nu, ++n; + if( ix( 0, 1 ) != N8_bg ) ++nv, ++n; + if( ix( 1, 1 ) != N8_bg ) ++nd, ++n; + + // mark the output pixel + int code = 0; + if( n == 1 ){ + if( nh ) code = 1; + else if( nu ) code = 3; + else if( nv ) code = 5; + else code = 7; + } else if( n == 2 ){ + if( nh == 2 ) code = 1; + else if( nu == 2 ) code = 3; + else if( nv == 2 ) code = 5; + else if( nd == 2 ) code = 7; + else if( nh && nu ) code = 2; + else if( nh && nd ) code = 8; + else if( nv && nu ) code = 4; + else if( nv && nd ) code = 6; + } + assert( code < 9 ); + *ox = code ? code : N8_bg; + } + } + } + + if( save_images ){ + ImageExportInfo eei( "output/orientLines.tif" ); + eei.setCompression( "" ); + exportImage(srcImageRange(line), eei ); + } + +/* 3rd pass erases points in the temp image having 2 neighbors whose + orientations differ by more than one unit. This breaks corners. + +*/ + lul = (line.upperLeft() + Diff2D(1,1)); + + for(int y=1; y<height-1; ++y, ++lul.y) + { + BImage::traverser ix = lul; + for(int x=1; x<width-1; ++x, ++ix.x ) + { + int c = *ix; + if( c != N8_bg ){ + assert( c > 0 && c < 9 ); + int n = 0, omin = 9, omax = 0; + NeighborhoodCirculator<BImage::traverser, EightNeighborCode> + circulator(ix), + end(circulator); + do { + int nc = *circulator; + if( nc != N8_bg ){ + //// nc /= 20; + assert( nc > 0 && nc < 9 ); + if( nc < omin ) omin = nc; + if( nc > omax ) omax = nc; + ++n; + } + } while(++circulator != end); + // mark the pixel + if( n == 2 ){ + int d = omax - omin; + assert( d < 8 ); + if( d > 4 ) + d = 7 - d; + if ( d > 1 ) + *ix = N8_bg; + } + } + } + } + + if( save_images ){ + ImageExportInfo eei( "output/bustCorners.tif" ); + eei.setCompression( "" ); + exportImage(srcImageRange(line), eei ); + } + +/* 4th pass changes marks in temp image from orientation to + end = 1, interior = 2, and erases isolated points. +*/ + lul = (line.upperLeft() + Diff2D(1,1)); + + for(int y=1; y<height-1; ++y, ++lul.y) + { + BImage::traverser ix = lul; + for(int x=1; x<width-1; ++x, ++ix.x ) + { + int c = *ix; + if( c != N8_bg ){ + int n = 0; + NeighborhoodCirculator<BImage::traverser, EightNeighborCode> + circulator(ix), + end(circulator); + do { + int nc = *circulator; + if( nc != N8_bg ){ + ++n; + } + } while(++circulator != end); + // mark the pixel + if( n == 0 ) *ix = N8_bg; + else if( n == 1 ) *ix = 1; + else *ix = 2; + } + } + } + +/* 5th pass copies line points to edge image, skipping end points that are + neighbors of end points (this removes 2-point lines). End points are + marked N8_end, interior points N8_mid. + +*/ + lul = (line.upperLeft() + Diff2D(1,1)); + eul = (edge.upperLeft() + Diff2D(1,1)); // rewind edge + edge.init(N8_bg); + + for(int y=1; y<height-1; ++y, ++lul.y, ++eul.y ) + { + BImage::traverser ox = eul; + BImage::traverser ix = lul; + for(int x=1; x<width-1; ++x, ++ix.x, ++ox.x ) + { + int c = *ix; + if( c != N8_bg ){ + int n = 0; + NeighborhoodCirculator<BImage::traverser, EightNeighborCode> + circulator(ix), + end(circulator); + do { + int nc = *circulator; + if( nc != N8_bg ){ + ++n; + if( c == 1 && nc == 1 ) c = 0; //skip + } + } while(++circulator != end); + + // mark the pixel + if( c ){ + if( n == 1 ){ + *ox = N8_end; + ++nends; + } else { + *ox = N8_mid; + ++nmids; + } + } + } + } + } + + if( save_images ){ + ImageExportInfo eei( "output/cleanLines.tif" ); + eei.setCompression( "" ); + exportImage(srcImageRange(edge), eei ); + } + + return nends/2 ; +} + +// chain-code distance +static float ccdist( int dx, int dy ){ + dx = abs(dx); dy = abs(dy); + return float(max(dx,dy)) + float(0.41421 * min(dx,dy)); +} + +int +linePts2lineList( BImage & img, + int minsize, + double minCtoA, // chord/arc threshold + vector<vector<Point2D>> & lines + ) +{ + + static Diff2D offs[8] = { + Diff2D( 1, 0 ), + Diff2D( 1, -1 ), + Diff2D( 0, -1 ), + Diff2D( -1, -1 ), + Diff2D( -1, 0 ), + Diff2D( -1, 1 ), + Diff2D( 0, 1 ), + Diff2D( 1, 1 ) + }; + + int width = img.width(), + height = img.height(); + + double minCtoAfound = 1; + + int nadd = 0, nrejL = 0, nrejQ = 0, nrejC = 0; + + BImage::traverser ul(img.upperLeft() + Diff2D( 1, 1 )); + for(int y=1; y<height-1; ++y, ++ul.y) + { + BImage::traverser ix = ul; + for(int x=1; x<width-1; ++x, ++ix.x ) + { + int cd = *ix; // point code + if( cd == N8_end ){ // new line... + // trace and erase the line + BImage::traverser tr = ix; + Point2D pos( x, y ); + vector<Point2D> pts; + pts.push_back(pos); + *tr = N8_bg; + int dir; + Diff2D dif; + do { + for( dir = 0; dir < 8; dir++ ){ + dif = offs[dir]; + if( tr[dif] != N8_bg ) break; + } + assert( dir < 8 ); + tr += dif; + pos += dif; + pts.push_back(pos); + cd = *tr; + *tr = N8_bg; + } while( cd != N8_end ); + // validate the point list + bool ok = true; + if( pts.size() < minsize ){ + ok = false; + ++nrejL; + } else if( minCtoA > 0 ){ + int ncopy = 0, nskip = 0; + /* curvature test + compute running chord and arc on a moderate span that depends on + segment size. Output segments where their ratio exceeds minCtoA. + */ + int ip = 0, np = pts.size(); + int span = np / 20; + if( span < 5 ){ span = np / 10; } + if( span < 5 ){ span = np / 5; } + if( span < 5 ){ span = np; } + + vector<Point2D> tmp; + float ccd[32]; // rolling interpoint chaincode distances + int isql = 0, isqr = 0; // left & rgt indices to same + int xl = pts.at( 0 ).x, + yl = pts.at( 0 ).y; + int dx = pts.at(span-1).x - xl, + dy = pts.at(span-1).y - yl; + float Chord = ccdist( dx, dy ); + float Arc = 0; + // fill 1st span's d's, initialize Dsq + for( isqr = 0; isqr < span-1; isqr++ ){ + register int x = pts.at( isqr + 1).x, + y = pts.at( isqr + 1 ).y; + float d = ccdist( x - xl, y - yl ); + ccd[isqr] = d; + Arc += d; + xl = x; yl = y; + } + // copy 1st span pnts if span is good + double c2a = Arc == 0 ? 1 : Chord / Arc; + if( c2a <minCtoAfound ) minCtoAfound = c2a; + if( c2a >= minCtoA ){ + for( int i = 0; i < span; i++ ){ + tmp.push_back(Point2D( pts.at(i).x, pts.at(i).y )); + } + } + + // roll span.... + for( ip = 1; ip < np - span; ip++ ){ + int irgt = ip + span - 1; + // update span + Arc -= ccd[isql]; + isql = (++isql)&31; + isqr = (++isqr)&31; + int x = pts.at( irgt ).x, + y = pts.at( irgt ).y; + float d = ccdist( x - xl, y - yl ); + ccd[isqr] = d; + Arc += d; + xl = x; yl = y; + x -= pts.at(ip).x; y -= pts.at(ip).y; + Chord = ccdist( x, y ); + /* if this span is good, copy right pnt + else flush tmp to lines if long enough + */ + c2a = Arc == 0 ? 1 : Chord / Arc; + if( c2a >= minCtoA ){ + ++ncopy; + tmp.push_back(Point2D( pts.at(irgt).x, pts.at(irgt).y )); + } else { + if( tmp.size() >= minsize ){ + ++nadd; + lines.push_back( tmp ); + } + tmp.clear(); + ++nskip; + } + } + // if the final span is good, copy & flush. + if( tmp.size() >= minsize ){ + ++nadd; + lines.push_back( tmp ); + } + } // end curvature test + else { // length ok, no curvature test + lines.push_back( pts ); + ++nadd; + } + } // end trace line + } // end x scan + } // end y scan + return nadd; +} Added: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.h (rev 0) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.h 2009-08-09 03:23:05 UTC (rev 4188) @@ -0,0 +1,40 @@ +/* find_N8_lines.h + + find straightish non-crossing lines in an edge map, + using 8-neighborhood operations. (Points on the edges + of the image cannot be line points). + + edgeMap2linePts() marks line point in an otherwise zero + BImage; end points = 1, interior points = 2. A threshold + on the edge map defines valid candidates. Returns the + number of segments, 0 if edge and line image sizes differ. + + linePts2lineList() converts a linePts image to a list of + all lines that meet some selection criteria. The line list + is a vector of pointers to N8_line objects created here; + the vector itself is passed in by caller. + Returns the number of lines added + +*/ + +#include <vector> +#include <vigra/stdimage.hxx> +#include <vigra/basicimage.hxx> +#include <vigra/pixelneighborhood.hxx> + +// colors used in lines image +#define N8_bg 255 +#define N8_end 1 +#define N8_mid 96 + +int +edgeMap2linePts( vigra::BImage & edge, bool save_images ); + +int +linePts2lineList( vigra::BImage & img, + int minsize, + double minCtoA, // chord/arc threshold + std::vector<std::vector<vigra::Point2D>> & lines + ); + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bl...@us...> - 2009-08-09 11:28:14
|
Revision: 4190 http://hugin.svn.sourceforge.net/hugin/?rev=4190&view=rev Author: blimbo Date: 2009-08-09 11:28:03 +0000 (Sun, 09 Aug 2009) Log Message: ----------- Doesn't check output dir, fixed > > error Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.h Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-08-09 08:55:11 UTC (rev 4189) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Main.cpp 2009-08-09 11:28:03 UTC (rev 4190) @@ -526,10 +526,12 @@ i++; } + /* if(!fileexists(path)){ cout << "Output path " << path << " doesn't exist. Using working directory." << endl << endl; path = (""); } + */ if (gap_limit < 2) gap_limit = 2; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-09 08:55:11 UTC (rev 4189) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-09 11:28:03 UTC (rev 4190) @@ -215,7 +215,7 @@ } } -void plot_lines(string& filename, BImage& image, vector<vector<Point2D>>& lines, +void plot_lines(string& filename, BImage& image, vector<vector<Point2D> >& lines, int i, int j ){ vigra::BRGBImage tmp(image.width(),image.height()); @@ -1534,10 +1534,9 @@ corners.push_back(localMinIndex); } } - //corners.push_back(points.size()); + corners.push_back(points.size()-1); - if(0){ - + if(1){ // Post-process corners cout << "Post-processing corners..." << endl; bool cont = false; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.h 2009-08-09 08:55:11 UTC (rev 4189) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.h 2009-08-09 11:28:03 UTC (rev 4190) @@ -18,8 +18,8 @@ */ #include <vector> -#include <vigra/stdimage.hxx> -#include <vigra/basicimage.hxx> +#include <vigra/stdimage.hxx> +#include <vigra/basicimage.hxx> #include <vigra/pixelneighborhood.hxx> // colors used in lines image @@ -34,7 +34,7 @@ linePts2lineList( vigra::BImage & img, int minsize, double minCtoA, // chord/arc threshold - std::vector<std::vector<vigra::Point2D>> & lines + std::vector<std::vector<vigra::Point2D> > & lines ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tks...@us...> - 2009-08-11 18:00:23
|
Revision: 4196 http://hugin.svn.sourceforge.net/hugin/?rev=4196&view=rev Author: tksharpless Date: 2009-08-11 18:00:14 +0000 (Tue, 11 Aug 2009) Log Message: ----------- First usable cut of find_N8_lines with lineFilter fn. Need to add hook filter, all else looks good. Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.cpp Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-11 16:12:20 UTC (rev 4195) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/ProcessImage.cpp 2009-08-11 18:00:14 UTC (rev 4196) @@ -215,8 +215,7 @@ } } -void plot_lines(string& filename, BImage& image, vector<vector<Point2D> >& lines, - int i, int j ){ +void plot_lines(string& filename, BImage& image, vector< vector< Point2D > >& lines, int i, int j ){ vigra::BRGBImage tmp(image.width(),image.height()); vigra::initImage(srcIterRange(tmp.upperLeft(), @@ -1033,7 +1032,7 @@ float efocal_length35 = 0; getExiv2Value(exifData,"Exif.Photo.FocalLengthIn35mmFilm",efocal_length35); - double new_focal_length,new_cropFactor; + double new_focal_length = 0,new_cropFactor = 0; //The various methods to detmine crop factor if (efocal_length > 0 && cropFactor > 0) { @@ -1688,30 +1687,32 @@ #if 1 // test find_N8_lines bool saveimages = true; // write debug pix - int lmin = 32; - double CtoAmin = 0.99; + int lmin = int(sqrt(min_line_length_squared)); + double flpix = focal_length_pixels; cout<<" edgeMap2linePts(saveimages "<<saveimages<<"): "; int nsegs = edgeMap2linePts( image, saveimages ); cout<<nsegs<<" segments"<<endl; - cout<<" linePts2lineList(lmin "<<lmin<<" CtoAmin "<<CtoAmin<<") : "; - int nlines = linePts2lineList( image, lmin, CtoAmin, lines ); + cout<<" linePts2lineList(lmin "<<lmin<<" flpix "<<flpix<<") : "; + int nlines = linePts2lineList( image, lmin, flpix, lines ); cout<<nlines<<" lines"<<endl; if (nlines == 0){ cout << "No lines found!" << endl << endl; }else{ cout << nlines << " lines found" << endl; - +/* int llp = lines.size() - 1; plot_lines(filename, image, lines, plotted, llp ); plotted = llp; +*/ cout << endl; } + int good_lines; + good_lines = nlines; - #else // original FVector2Image edgeness(nw,nh); Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.cpp 2009-08-11 16:12:20 UTC (rev 4195) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/find_N8_lines.cpp 2009-08-11 18:00:14 UTC (rev 4196) @@ -17,14 +17,29 @@ sructs. The list vector is passed by caller, the point vectors are created here. Returns the number of lines added. - The line selection criteria are minimum size (in points ) and - a curvature limit, expressed as a chord/arc ratio (C/A is - 1 for a perfectly straight line and 0 for a closed curve). - minCtoA is the minimum acceptable for a whole line. Lines - in the input image will be broken into sections that don't - violate this criterion, by splitting at points of maximum - curvature. + There are 2 line selection parameters: + -- minimum size (in points ) + -- the assumed focal length (in pixels) of the lens + The maximum allowed overall curvature depends on the f.l. and + the position and orientation of the segment. This calculation + assumes the center of projection is in the center of the image. + Passing a longer f.l. makes the curvature limits smaller. For + rectilinear lenses, I suggest using a value 3 to 4 times the + actual lens f.l. + + Lines whose orientation is radial, or nearly so, are removed + as well, since they can contribute nothing to lens calibration. + + Note flpix == 0 disables the curvature & orientation tests. + + Besides the global curvature test, there are two local tests + to ensure that the curvature is nearly uniform along the line. + The first is a "corner test" that may split a line into smaller + segments while it is being traced. The second, part of the + curvature filter, just prunes the ends, if possible, giving + a single segment of nearly uniform curvature. + */ #include <assert.h> @@ -34,6 +49,35 @@ using namespace vigra; using namespace std; +static void plot_lines( vector< vector< Point2D > > lines, int wid, int hgt, char * fnm ){ +typedef vigra::BRGBImage::PixelType RGB; + int n = lines.size(); + if( n < 1 ) return; + vigra::BRGBImage tmp(wid, hgt); + vigra::initImage(srcIterRange(tmp.upperLeft(), + tmp.upperLeft() + vigra::Diff2D(wid, hgt)), + RGB(255,255,255) ); + for( unsigned iln = 0; iln < n; iln++ ){ + vector<Point2D> & inliers = lines.at( iln ); + for (unsigned int il = 0; il < inliers.size(); il++){ + vigra::initImage(srcIterRange(tmp.upperLeft() + vigra::Diff2D(inliers[il]->x, inliers[il]->y), + tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+1, inliers[il]->y+1)), + RGB(255,0,0) ); + + // Make end point green + if(il == 0 || il == inliers.size()-1)vigra::initImage(srcIterRange(tmp.upperLeft() + + vigra::Diff2D(inliers[il]->x, inliers[il]->y), + tmp.upperLeft() + vigra::Diff2D(inliers[il]->x+1, inliers[il]->y+1)), + RGB(0,255,0) ); + + } + } + + cout << " debug plot "<<fnm<<" "<<n<<" lines "<< endl; + exportImage(srcImageRange(tmp), ImageExportInfo(fnm).setPixelType("UINT8")); +} + + int edgeMap2linePts( BImage & edge, bool save_images ){ @@ -294,18 +338,157 @@ } // chain-code distance -static float ccdist( int dx, int dy ){ +inline float ccdist( int dx, int dy ){ dx = abs(dx); dy = abs(dy); return float(max(dx,dy)) + float(0.41421 * min(dx,dy)); } +// Euclidian distance +inline float eudist( int dx, int dy ){ + register float x = dx, y = dy; + return sqrt( x*x + y*y ); +} + +// chord and arc using chain code distance +static double CtoAcc( vector<Point2D> & pts, + int start, int count, + double & C, double & A){ + int n = pts.size() - start; + if( count > n ) count = n; + if( count < 3 ) return 1; + int xl = pts.at(start).x, yl = pts.at(start).y; + int xr = pts.at(start + count - 1).x, + yr = pts.at(start + count - 1).y; + C = ccdist( xr - xl, yr - yl ); + A = 0; + for(int i = start + 1; i < count; i++ ){ + xr = pts.at(i).x; yr = pts.at(i).y; + A += ccdist( xr - xl, yr - yl ); + xl = xr; yl = yr; + } + return C/A; +} + +// chord and arc using Euclidian distance +static double CtoAeu( vector<Point2D> & pts, + int start, int count, + double & C, double & A){ + int n = pts.size() - start; + if( count > n ) count = n; + if( count < 3 ) return 1; + int xl = pts.at(start).x, yl = pts.at(start).y; + int xr = pts.at(start + count - 1).x, + yr = pts.at(start + count - 1).y; + C = eudist( xr - xl, yr - yl ); + A = 0; + for(int i = start + 1; i < count; i++ ){ + xr = pts.at(i).x; yr = pts.at(i).y; + A += eudist( xr - xl, yr - yl ); + xl = xr; yl = yr; + } + return C/A; +} + +/* 3-point scalar curvature + positive clockwise +*/ +inline float scurv( Point2D & l, Point2D & m, Point2D & r ){ + return float(m.x - l.x) * float(r.y - l.y) + + float(m.y - l.y) * float(l.x - r.x ); +} + +/* 3-point float vector curvature + positive inward +*/ +inline void vcurv ( Point2D & l, Point2D & m, Point2D & r, + float & vx, float & vy ){ + vx = 0.5 * (l.x + r.x) - float( m.x ); + vy = 0.5 * (l.y + r.y) - float( m.y ); +} + + +/* final filter for line segments + input: a point list, a minimum size, the f.l. in pixels and + the projection center point. + output: the point list may contain a segment, of at least + mimimum size, having uniform curvature <= a limit that + depends on f.l., position and orientation. + return value is length of the pruned segment, or + 0 if rejectd on length or extreme initial curvature. + -1 if rejected on orientation + -2 if rejected on curvature + Note if a segment has multiple smooth parts, only the longest + one will survive. +*/ +static int lineFilter( vector< Point2D > & pts, + int lmin, + double flpix, + double xcen, double ycen + ){ +// cos( min angle from radius to chord ) +const double crcmin = 0.20; // about 11 degrees +// max ratio of actual to theoretical curvature +const double cvrmax = 3.0; + + double r90 = 1.57 * flpix; // 90 degree radius, pixels + double Rsqf = 2 * r90 * r90; + + int n = pts.size(); + // reject short segments + if( n < lmin ) + return 0; // too short + +/* orientation test */ + double sr90 = 1 / (1.57 * flpix); + // the full chord + double x0 = pts.at(0).x, + y0 = pts.at(0).y; + double dx = pts.at(n-1).x - x0, + dy = pts.at(n-1).y - y0; + double chord = sqrt( dx*dx + dy*dy ); + if( chord < 0.6 * n ) + return 0; // way too bent! + // the chord midpoint (in centered coords) + double ccx = x0 + 0.5 * dx - xcen, + ccy = y0 + 0.5 * dy - ycen; + double ccd = sqrt( ccx*ccx + ccy *ccy ); + // the arc center point in centered coords + // aka radius vector + double acx = pts.at(n/2).x - xcen, + acy = pts.at(n/2).y - ycen; + double acd = sqrt( acx*acx + acy*acy ); + // the curvature vector (points toward convex side) + double cvx = acx - ccx, + cvy = acy - ccy; + double cvd = sqrt( cvx*cvx + cvy*cvy ); + // cos( angle from radius to chord ) + double cosrc = fabs( acx * dy - acy * dx ) / (chord * acd); + if( fabs(cosrc) < crcmin ) + return -1; // too radial! + +/* curvature limit test */ + // curvature limit from lens model + double S = 1.2 * chord * cosrc / r90; // pseudo sine + double C = r90 * (1 - sqrt( 1 - S * S )); // corresp chord->arc dist + // curvature test + if( cvd / C > cvrmax ) + return -2; + +// for testing... + return n; +} + + int linePts2lineList( BImage & img, int minsize, - double minCtoA, // chord/arc threshold - vector<vector<Point2D>> & lines + double flpix, // focal length in pixels + vector< vector< Point2D > > & lines ) { + // debug data + vector< vector< Point2D > > badlen, badori, badcrv; + int nadd = 0, nrejL = 0; static Diff2D offs[8] = { Diff2D( 1, 0 ), @@ -318,13 +501,18 @@ Diff2D( 1, 1 ) }; +// corner filter parameters +const int span = 10; +const float maxacd = 1.4; + + if(minsize < span) minsize = span; // else bend filter fails + int width = img.width(), height = img.height(); + double xcen = 0.5 * width, + ycen = 0.5 * height; - double minCtoAfound = 1; - int nadd = 0, nrejL = 0, nrejQ = 0, nrejC = 0; - BImage::traverser ul(img.upperLeft() + Diff2D( 1, 1 )); for(int y=1; y<height-1; ++y, ++ul.y) { @@ -341,43 +529,46 @@ *tr = N8_bg; int dir; Diff2D dif; - do { + do { // scan the neighborhood for( dir = 0; dir < 8; dir++ ){ dif = offs[dir]; if( tr[dif] != N8_bg ) break; } assert( dir < 8 ); - tr += dif; - pos += dif; - pts.push_back(pos); - cd = *tr; - *tr = N8_bg; + tr += dif; // move to next point + cd = *tr; // pick up that pixel + *tr = N8_bg; // erase it from image + pos += dif; // update position + pts.push_back(pos); // add same to pointlist } while( cd != N8_end ); // validate the point list bool ok = true; if( pts.size() < minsize ){ ok = false; ++nrejL; - } else if( minCtoA > 0 ){ + } else if( flpix > 0 ){ int ncopy = 0, nskip = 0; - /* curvature test - compute running chord and arc on a moderate span that depends on - segment size. Output segments where their ratio exceeds minCtoA. + /* bend test + compute running chord and arc on a fixed span. + Output segments where their difference is small. + The parameters are set to pass some hooked lines + that will be cleaned up later. */ int ip = 0, np = pts.size(); - int span = np / 20; + + /* np / 20; if( span < 5 ){ span = np / 10; } if( span < 5 ){ span = np / 5; } if( span < 5 ){ span = np; } - + */ vector<Point2D> tmp; float ccd[32]; // rolling interpoint chaincode distances int isql = 0, isqr = 0; // left & rgt indices to same int xl = pts.at( 0 ).x, yl = pts.at( 0 ).y; - int dx = pts.at(span-1).x - xl, - dy = pts.at(span-1).y - yl; - float Chord = ccdist( dx, dy ); + float dx = pts.at(span-1).x - xl, + dy = pts.at(span-1).y - yl; + float Chord = sqrt(dx*dx + dy*dy); float Arc = 0; // fill 1st span's d's, initialize Dsq for( isqr = 0; isqr < span-1; isqr++ ){ @@ -389,9 +580,7 @@ xl = x; yl = y; } // copy 1st span pnts if span is good - double c2a = Arc == 0 ? 1 : Chord / Arc; - if( c2a <minCtoAfound ) minCtoAfound = c2a; - if( c2a >= minCtoA ){ + if( Arc - Chord <= maxacd ){ for( int i = 0; i < span; i++ ){ tmp.push_back(Point2D( pts.at(i).x, pts.at(i).y )); } @@ -410,29 +599,37 @@ ccd[isqr] = d; Arc += d; xl = x; yl = y; - x -= pts.at(ip).x; y -= pts.at(ip).y; - Chord = ccdist( x, y ); + dx = x - pts.at(ip).x; dy = y - pts.at(ip).y; + Chord = sqrt( dx*dx + dy*dy ); /* if this span is good, copy right pnt else flush tmp to lines if long enough */ - c2a = Arc == 0 ? 1 : Chord / Arc; - if( c2a >= minCtoA ){ + if( Arc - Chord <= maxacd ){ ++ncopy; tmp.push_back(Point2D( pts.at(irgt).x, pts.at(irgt).y )); } else { - if( tmp.size() >= minsize ){ + int q = lineFilter( tmp, minsize, flpix, xcen, ycen ); + if( q > 0 ){ ++nadd; lines.push_back( tmp ); - } + } + else if( q == 0 ) badlen.push_back( tmp ); + else if( q == -1 ) badori.push_back( tmp ); + else if( q == -2 ) badcrv.push_back( tmp ); + tmp.clear(); ++nskip; } } // if the final span is good, copy & flush. - if( tmp.size() >= minsize ){ + int q = lineFilter( tmp, minsize, flpix, xcen, ycen ); + if( q > 0 ){ ++nadd; lines.push_back( tmp ); } + else if( q == 0 ) badlen.push_back( tmp ); + else if( q == -1 ) badori.push_back( tmp ); + else if( q == -2 ) badcrv.push_back( tmp ); } // end curvature test else { // length ok, no curvature test lines.push_back( pts ); @@ -441,5 +638,13 @@ } // end trace line } // end x scan } // end y scan + +/* file debug images +*/ + plot_lines( lines, width, height, "dbg_goodlines.jpg"); + plot_lines( badlen, width, height, "dbg_badlen.jpg"); + plot_lines( badori, width, height, "dbg_badori.jpg"); + plot_lines( badcrv, width, height, "dbg_badcrv.jpg"); + return nadd; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <tks...@us...> - 2009-08-13 03:06:19
|
Revision: 4201 http://hugin.svn.sourceforge.net/hugin/?rev=4201&view=rev Author: tksharpless Date: 2009-08-13 03:06:10 +0000 (Thu, 13 Aug 2009) Log Message: ----------- Add a stable substitute for the radius polynomial to lensFunc -- now we can calibrate! Modified Paths: -------------- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/lensFunc.cpp hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/lensFunc.h Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-08-12 14:18:38 UTC (rev 4200) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.cpp 2009-08-13 03:06:10 UTC (rev 4201) @@ -29,7 +29,7 @@ unsigned int lens_type = 1; unsigned int current_line = 0; unsigned int optimise_centre = 1; -unsigned int poly_type = 1; +unsigned int poly_type = 2; unsigned int ss = 0; unsigned int straighten_verts = 0; double sensor_width = 0; @@ -64,3 +64,5 @@ double sigma = 1.4; double r = 140; std::map<int,double> line_errors; +std::map<int,double> line_weights; +double RMS_error = 0; Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-08-12 14:18:38 UTC (rev 4200) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/Globals.h 2009-08-13 03:06:10 UTC (rev 4201) @@ -43,5 +43,7 @@ extern double sigma; extern double r; extern std::map<int,double> line_errors; +extern std::map<int,double> line_weights; +extern double RMS_error; #endif Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-08-12 14:18:38 UTC (rev 4200) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/MapPoints.cpp 2009-08-13 03:06:10 UTC (rev 4201) @@ -52,6 +52,16 @@ XYZPoint( double X, double Y, double Z ) : x(X), y(Y), z(Z) {} XYZPoint() : x(0), y(0), z(0) {} + XYZPoint( double *p ) + : x(p[0]), y(p[1]), z(p[2]) {} + double normalize(){ + register double r = sqrt(x*x + y*y + z*z ); + register double s = r == 0 ? 0 : 1 / r; + x *= s; + y *= s; + z *= s; + return r; + } }; XYZPoint XYZdifference( XYZPoint & a, XYZPoint & b ){ @@ -63,15 +73,20 @@ return sqrt( d.x * d.x + d.y * d.y + d.z * d.z ); } -XYZPoint CrossProduct (XYZPoint v1, XYZPoint v2){ +XYZPoint CrossProduct (XYZPoint & v1, XYZPoint & v2){ XYZPoint cp; cp.x = v1.y * v2.z - v1.z * v2.y; + cp.y = v1.x * v2.z - v1.z * v2.z; + cp.z = v1.x * v2.y - v1.y * v2.x; +/* was + cp.x = v1.y * v2.z - v1.z * v2.y; cp.y = v1.z * v2.x - v1.x * v2.z; cp.z = v1.x * v2.y - v1.y * v2.x; +*/ return(cp); } -double DotProduct (XYZPoint v1, XYZPoint v2){ +double DotProduct (XYZPoint & v1, XYZPoint & v2){ return((v1.x*v2.x + v1.y*v2.y + v1.z*v2.z)); } @@ -365,6 +380,14 @@ y_point -= y_cen; y_point *= -1; + +#if 1 // map image coords to spherical cartesian + double xyz[3]; + LF.cart3d_photo( x_point, y_point, xyz ); + XYZPoint Point(xyz); + if( Point.normalize() == 0 ) + i = i; +#else // map raw image coordinates to spherical fisheye double xsph, ysph; LF.sphere_photo( lines[l][i]->x, @@ -375,18 +398,23 @@ double r = sqrt( xsph * xsph + ysph * ysph ); double s = r == 0.0 ? 0.0 : sin( r ) / r; + XYZPoint Point; - Point.x = s * xsph; Point.y = s * ysph; Point.z = cos( r ); +#endif mapped_point[i] = Point; } // compute straightness error for this line // Vector cross product of the end points - this is the normal to the estimated plane - XYZPoint norm = CrossProduct(mapped_point[0],mapped_point[npnts - 1]); + XYZPoint & first = mapped_point[0], + & last = mapped_point[npnts - 1]; + XYZPoint norm = CrossProduct( first, last); + if( norm.normalize() == 0 ) + npnts = lines[l].size(); // Compute straigthness error double ssq = 0; @@ -395,10 +423,9 @@ double d = DotProduct(norm,mapped_point[i]); ssq += d * d; } - // normalize, weight, add to optimizer's error vecto - x[l] = sqrt((npnts - 2) * ssq ) / XYZdistance(mapped_point[0],mapped_point[npnts - 1]); - //cout << "Error:\t" << x[l] << endl; - line_errors[l] = x[l] / npnts; // save error per data point + // add to optimizer's error vector + x[l] = sqrt(ssq) ; + line_errors[l] = sqrt(ssq / (npnts - 2)); // save rms error delete [] mapped_point; } @@ -570,16 +597,19 @@ /* select the parameters to be optimized */ - int n = 1; + int n = 0; if (poly_type == 2){ cout << "Using cubic polynomial (Panotools a,b,c) " << endl; n = 3; }else if (poly_type == 3){ cout << "Using quintic polynomial (Panotools a,b,c,f)" << endl; n = 4; - }else{ + }else if( poly_type != 0 ){ cout << "Using even-order polynomial (Panotools a,c)" << endl; n = 2; + } else { + cout << "Using no polynomial" << endl; + n = 0; } int m; // number of parameters to be optimized m = LF.setOptPurpose( lensFunc::calibrate, n, optimise_centre ); @@ -608,13 +638,15 @@ double a,b,c,d,e,f; // PT-style names double p0, p1; // no PT equivalent LF.get_w_c_shift( d, e ); - printf(" Centre shifts: %.1f %.1f \n", d, e ); + printf(" Centre shifts: %.2f %.2f pixels\n", d, e ); LF.get_w_proj_params( p0, p1 ); printf(" Projection params: %g %g \n", p0, p1 ); LF.get_w_rad_params( a, b, c, f ); printf(" Radial coeffs: a %g b %g c %g f %g\n", a, b, c, f ); + + printf("Total squared error initial %g final %g\n", info[0], info[1] ); for (unsigned int i = 0; i < n; i++){ - cout << "Line " << i+1 << " error:\t\t" << line_errors[i] << endl; + cout << "Line " << i+1 << " rms:\t" << line_errors[i] << endl; } printf("\n"); Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/lensFunc.cpp =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/lensFunc.cpp 2009-08-12 14:18:38 UTC (rev 4200) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/lensFunc.cpp 2009-08-13 03:06:10 UTC (rev 4201) @@ -1,4 +1,5 @@ /* lensFunc.cpp for calibrate_lens 28Jul09 TKS + (c) copyright 2009 Thomas K Sharpless */ @@ -70,6 +71,8 @@ { model_valid = spline_valid = false; color = 1; // default green, tca factor == 1 + opt_rad_k = 0; + opt_center = opt_scale = opt_tca = false; camera = no_cam; lens = no_lens; set_f_scale( 1, 1 ); @@ -77,7 +80,7 @@ set_tca_params( 1, 1 ); set_rad_params( 0, 0, 0, 0 ); // validate arguments - if( c_type < digicam || c_type > slitcam ) return false; + if( c_type < digicam || c_type > scanner ) return false; if( hPixels < 1 || vPixels < 1 ) return false; if( hPixmm < 1 || vPixmm < 1 ) return false; if( l_type < rectilinear || l_type > tan_sin_model ) return false; @@ -88,10 +91,10 @@ hPix_mm = hPixmm; vPix_mm = vPixmm; lens = l_type; FL_mm = FLmm; - maxFOVrad = 05. * DEG2RAD( maxFOVdeg ); + maxFOVrad = 0.5 * DEG2RAD( maxFOVdeg ); // post default model params double p0 = 0.5, p1 = 0; - if( lens = rectilinear ) p0 = 1; + if( lens == rectilinear ) p0 = 1; if( lens == tan_sin_model ) p1 = 0.5; model_valid = true; return set_proj_params( p0, p1 ); @@ -198,59 +201,87 @@ /* compute the image <=> equal angle fisheye mappings */ // centered image coords to spherical fisheye -int lensFunc::sphere_photo( double x_dest, double y_dest, double* x_src, double* y_src ){ - *x_src = *y_src = 0; +int lensFunc::sphere_photo( double x_phot, double y_phot, double* x_sphr, double* y_sphr ){ + *x_sphr = *y_sphr = 0; if( !spline_valid ) return 0; double R; - register double x = (x_dest - w_c_shift[0]) / hFLpix, - y = (y_dest - w_c_shift[1]) / vFLpix, + register double x = (x_phot - w_c_shift[0]) / hFLpix, + y = (y_phot - w_c_shift[1]) / vFLpix, r = sqrt( x * x + y * y ); - if( !spline_hermite_val( NSpts, xval, Cxy, r, &R, 0 ) - ) return 0; - *x_src = x * R; - *y_src = y * R; + if( !spline_hermite_val( NSpts, xval, Cxy, r, &R, 0 )) return 0; + if( r > 0 ) R /= r; + *x_sphr = x * R; + *y_sphr = y * R; return 1; } // map spherical fisheye to centered image coordinates -int lensFunc::photo_sphere( double x_dest, double y_dest, double* x_src, double* y_src ){ - *x_src = *y_src = 0; +int lensFunc::photo_sphere( double x_sphr, double y_sphr, double* x_phot, double* y_phot ){ + *x_phot = *y_phot = 0; if( !spline_valid ) return 0; double r; - double R = sqrt( x_dest * x_dest + y_dest * y_dest ); - if( !spline_hermite_val( NSpts, xval, Cxy, R, &r, 0 ) - ) return 0; + double R = sqrt( x_sphr * x_sphr + y_sphr * y_sphr ); + if( !spline_hermite_val( NSpts, xval, Cxy, R, &r, 0 )) return 0; if( R > 0 ) r /= R; - *x_src = x_dest * r * hFLpix + w_c_shift[0]; - *y_src = y_dest * r * vFLpix + w_c_shift[1]; + *x_phot = x_sphr * r * hFLpix + w_c_shift[0]; + *y_phot = y_sphr * r * vFLpix + w_c_shift[1]; return 1; } + +/* compute image <=> Cartesian unit sphere mappings */ +// map image x, y to Cartesian unit sphere +int lensFunc::cart3d_photo( double x_phot, double y_phot, double xyz_sphr[3] ){ + xyz_sphr[0] = xyz_sphr[1] = xyz_sphr[2] = 0; + if( !spline_valid ) return 0; + double R; + register double x = (x_phot - w_c_shift[0]) / hFLpix, + y = (y_phot - w_c_shift[1]) / vFLpix, + r = sqrt( x * x + y * y ); + if( !spline_hermite_val( NSpts, xval, Cxy, r, &R, 0 )) return 0; + xyz_sphr[2] = cos( R ); + register double s = sin( R ); + if( r > 0 ) s /= r; + else + s = 0; + xyz_sphr[0] = x * s; + xyz_sphr[1] = y * s; + return 1; +} +// map Cartesian unit sphere to image x, y +int lensFunc::photo_cart3d( double xyz_sphr[3], double* x_phot, double* y_phot ){ + *x_phot = *y_phot = 0; + if( !spline_valid ) return 0; + double r; + double R = acos( xyz_sphr[2] ); + if( !spline_hermite_val( NSpts, xval, Cxy, R, &r, 0 )) return 0; + *x_phot = xyz_sphr[0] * r * hFLpix + w_c_shift[0]; + *y_phot = xyz_sphr[1] * r * vFLpix + w_c_shift[1]; + return 1; +} + + /* parameter optimization API */ int lensFunc::setOptPurpose( opt_purpose p, - int polyN, + int optRad, bool optCen, bool optScl, bool optTca ){ if( !model_valid ) return 0; int cnt = 0; - if( polyN < 0 || polyN > 4) return 0; - if( polyN == 1 ){ // default for model - polyN = 2; - } - opt_polyn = polyN; - cnt += opt_polyn; + if( optRad < 0 ) optRad = 0; + else if( optRad > 4 ) optRad = 4; + if( optRad ) cnt += radfn.getParamCount( optRad ); + opt_rad_k = optRad; + opt_center = optCen; if( opt_center ) cnt += 2; opt_scale = optScl; if( opt_scale ) cnt += 2; - opt_scale = optScl; - if( opt_scale ) cnt += 2; - opt_tca = optTca; if( opt_tca && color != 1 ) ++cnt; @@ -264,13 +295,9 @@ int lensFunc::getOptParams( double * ppa ){ if( !spline_valid ) return 0; int n = 0; - if( opt_polyn ){ - ppa[n++] = w_rad_params[0]; - ppa[n++] = w_rad_params[2]; - if( opt_polyn > 2 ) - ppa[n++] = w_rad_params[1]; - if( opt_polyn > 3 ) - ppa[n++] = w_rad_params[3]; + + if( opt_rad_k ){ + n += radfn.getInfParams( ppa, opt_rad_k ); } if( opt_center ){ @@ -288,19 +315,20 @@ if( color == 2 ) ppa[n++] = w_tca_params[1]; } + if( lens > stereographic ) { + ppa[n++] = w_proj_params[0]; + if( lens > sine_model ) + ppa[n++] = w_proj_params[1]; + } + return n; } int lensFunc::setOptParams( double * ppa ){ if( !spline_valid ) return 0; int n = 0; - if( opt_polyn ){ - w_rad_params[0] = ppa[n++]; - w_rad_params[2] = ppa[n++]; - if( opt_polyn > 2 ) - w_rad_params[1] = ppa[n++]; - if( opt_polyn > 3 ) - w_rad_params[3] = ppa[n++]; + if( opt_rad_k ){ + n += radfn.setInfParams( ppa, opt_rad_k ); } if( opt_center ){ @@ -318,6 +346,12 @@ if( color == 2 ) w_tca_params[1] = ppa[n++]; } + if( lens > stereographic ) { + w_proj_params[0] = ppa[n++]; + if( lens > sine_model ) + w_proj_params[1] = ppa[n++]; + } + if( setSpline() ) return n; return 0; // setSpline() failed! } @@ -337,7 +371,8 @@ bool lensFunc::setSpline(){ spline_valid = false; - if( !model_valid ) return false; + if( !model_valid ) + return false; // post derived parameters hFLpix = FL_mm * hPix_mm * w_f_scale[0]; vFLpix = FL_mm * vPix_mm * w_f_scale[1]; @@ -359,11 +394,13 @@ double * x = xval, * y = yval, * t = new double[ NSpts ]; -// tabulate r vs angle - A = Amaxrad / (NSpts - 1); +// tabulate real radius/fl vs angle + A = Amaxrad / (NSpts - 1); for( i = 0; i < NSpts; i++ ){ x[i] = i * A; // angle - y[i] = rofR(RofA( x[i] )); + double t = RofA( x[i] ); + // note scale down to 0:1 then back up to radians + y[i] = Amaxrad * radfn.yofx( t / Amaxrad ); } // set up spline table @@ -451,13 +488,6 @@ return 0; } -/* radial polynomial real(ideal) - Note setSpline() sets up the coefficients -*/ -double lensFunc::rofR( double R ){ - return R*(radC[0]+R*(radC[1]+R*(radC[2]+R*(radC[3]+R*radC[4])))); -} - /* Printable descriptions of current model */ const char * lensFunc::camDesc(){ @@ -488,3 +518,128 @@ return ld[c]; } +/* ssifn -- +*/ + +ssifn::ssifn( int k ){ + if( k < 0 ) k = 0; + else if( k > 16 ) k = 16; + kmax = k; + npts = (1 << k) + 1; + para = new double[ 11 * npts ]; + xval = ¶[npts]; + yval = ¶[2 * npts]; + Cxy = ¶[3 * npts]; + Cyx = ¶[7 * npts]; + // initialize to straight line + for( int i = 0; i < npts; i++ ) para[i] = 0; + setSpline(); +} + +ssifn::~ssifn(){ + delete[] para; +} + +int ssifn::getParamCount( int k ){ + if( k <= 0 || k >= kmax ) k = kmax; + return ( 1 << k ) - 1; +} + +int ssifn::getParams( double * p, int k ){ + if( k <= 0 || k >= kmax ) k = kmax; + int j = 1 << (kmax - k); + int n = 0; + for( int i = j; i < npts - 1; i += j ){ + *p++ = para[i]; + ++n; + } + return n; +} + +int ssifn::setParams( double * p, int k ){ + if( k <= 0 || k >= kmax ) k = kmax; + int j = 1 << (kmax - k); + int n = 0; + for( int i = j; i < npts - 1; i += j ){ + register double t = *p++; + if( t < -0.5 ) t = -0.5; + else if( t > 0.5 ) t = 0.5; + para[i] = t; + } + if( !setSpline() ) n = 0; + return n; +} + +int ssifn::getInfParams( double * p, int k ){ + if( k <= 0 || k >= kmax ) k = kmax; + int j = 1 << (kmax - k); + int n = 0; + for( int i = j; i < npts - 1; i += j ){ + register double t = para[i]; + *p++ = tan( t * Pi ); + ++n; + } + return n; +} + +int ssifn::setInfParams( double * p, int k ){ + if( k <= 0 || k >= kmax ) k = kmax; + int j = 1 << (kmax - k); + int n = 0; + for( int i = j; i < npts - 1; i += j ){ + register double t = *p++; + para[i] = atan( t ) * (1/Pi); + ++n; + } + if( !setSpline() ) n = 0; + return n; +} + +double ssifn::yofx( double x ){ + double y = 0; + spline_hermite_val( npts, xval, Cxy, x, &y, 0 ); + return y; +} + +double ssifn::xofy( double y ){ + double x = 0; + spline_hermite_val( npts, yval, Cyx, y, &x, 0 ); + return x; +} + +// recursion to fill xval, yval +void ssifn::sssub( int l, int r ){ + int m = (l+r)/2; + if(m == l) return; // break recursion + register double dx = xval[r] - xval[l], + dy = yval[r] - yval[l], + p = para[m]; + xval[m] = xval[l] + dx * (0.5 - p); + yval[m] = yval[l] + dy * (0.5 + p); + sssub( l, m ); // do left subtree + sssub( m, r ); // do right subtree +} + +// call after posting new params +int ssifn::setSpline(){ + int i = npts - 1; + xval[0] = yval[0] = 0; + xval[i] = yval[i] = 1; + // fill xval, yval arrays + sssub( 0, i ); + // build spline tables + double * t = new double[npts]; + i = spline_tangents_set( npts, xval, yval, t ); + // fail if y is not monotonic + if( i != 1 ) + return 0; + // coefficients for forward spline + spline_hermite_set ( Cxy, npts, xval, yval, t ); + // tangents for inverse spline + i = spline_tangents_set( npts, yval, xval, t ); + // coefficients for inverse spline + spline_hermite_set ( Cyx, npts, yval, xval, t ); + delete [] t; + + return 1; +} Modified: hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/lensFunc.h =================================================================== --- hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/lensFunc.h 2009-08-12 14:18:38 UTC (rev 4200) +++ hugin/branches/gsoc2009_lenscalibration/src/lens_calibrate/lensFunc.h 2009-08-13 03:06:10 UTC (rev 4201) @@ -1,4 +1,7 @@ /* lensFunc.h for calibrate_lens, 28July09 TKS + + (c) copyright 2009 Thomas K Sharpless + This is a C++ header, not to be used in libpano source. In that context, use "lensFunc_glue.h" @@ -7,14 +10,23 @@ By providing what is essentially a single remapping function for all lenses, and only for lenses, lensFunc can support a - more comprhensive set of lens models and a practical lens + more comprehensive set of lens models and a practical lens calibration facility, both of which are sorely needed. Remapping with lensFunc is also faster than with existing stack functions because it tabulates the radial part of the mapping as a cubic spine. There are no evaluations of trig - functions or the radial polynomial during remapping, and + functions or a radial polynomial during remapping, and forward and inverse mappings are equally fast. + + There are also functions to map image coordinates to/from + points on the unit Cartesian sphere. The projection center + is the center of the sphere, and the image center is tangent + to the sphere at (0,0,1). The sphere coordinates are right + handed if image x runs right and y runs up -- caution: in + most image formats, y runs down, which gives left handed + 3D coordinates. These functions use the radial spline, but + do have to evaluate sin & cos, or arccos, as well. The C interface to libpano is very thin: two new remapping stack functions; two to copy lensFunc parameters to/from @@ -32,16 +44,32 @@ but a bit more flexible. The lensFunc basically decides what parameters to make available to the optimizer, based on the declared purpose of the optimization (lens calibration, - pano alignment, ...). It has functions to copy the appropriate - set of values to, and reload them from, a double array during - optimization. The usual PT radial correction and center shift - set a,b,c,d,e is available for the "legacy alignment" purpose. - But other lens-specific parameters can be optimized just as - easily. All lens parameters and the center shifts can be - adjusted via the optimizer API. Calibrated parameters are - protected during routine panorama alignment; however apparent - fov and distortion can be optimized via secondary parameters. + pano alignment, ...). Two functions then copy that set of + values to and from an external double array during optimization. + All lens parameters and the center shifts can be adjusted via the + optimizer API. Calibrated parameters are protected during routine + panorama alignment; however apparent fov and distortion can be + optimized via secondary parameters. + + The traditional radius correction polynomial causes all kinds + of trouble for optimization, so lensFunc does not use one. + Instead it uses an adjustable spline, that is guaranteed to be + monotonic no matter what parameter values the optimizer chooses. + Once it has been optimized, it is possible to translate this + internal radius function into a set of polynomial coefficients + for export to s/w that uses them. A variable number of radius + correction parameters (1, 3, 7, or 15) can be optimized. Unlike + polynomial coefficients they are unconditonally stable under + optimization; so using more of them improves detail but does not + enable wild excursions. + + The radius function is normalized to hold the maximum image radius + constant. By default that is half the diagonal or 180 degrees, + but a different "cropping radius" can be set. This is a little + different from PT's constant radius, which is always half of the + larger image dimension. + The API for setting up lens models will developed along with calibrate_lens, now a gsoc09 project, and eventually may expand to include a lens/camera database. @@ -57,9 +85,9 @@ Lens and camera parameters are specified separately. The basic lens parameters are focal length (mm), nominal projection function, and radial correction factors including TCA. Basic - camera parameters are sensor resolution (pixels per mm, each way) - and center point shifts (mm). This separation reflects the - reality that one lens might be used on several cameras, or that + camera parameters are sensor size and resolution (pixels per mm, + each way) and center point shifts (mm). This separation reflects + the reality that one lens might be used on several cameras, or that an image might have been digitized from film. We also cater for cameras having non-square pixels, and slit-cameras having a lens projection only on the vertical axis. @@ -67,18 +95,70 @@ Following the libpano termninology, we call the projection in which coordinates are given the "destination" and the one whose coordinates are to be computed the "source"; and name - transformation functions <destination>_<source>. - - The radial polynomial used here is essentially the same as in PT. - It converts ideal to real radius, has a cubic term (not used in - some models) and is normalized to hold a certain large radius - constant. The only difference is how that radius is computed: - PT uses half the larger image dimension; we use half the diagonal. + transformation functions <destination>_<source>. But function + arguments are named after the projection they belong to. */ #ifndef _LENSFUNC_H #define _LENSFUNC_H +/* ssifn -- + A simple strictly increasing adjustable function. + + Spans the range [0:1] in both x and y and can be + read as y(x) or as x(y). + + The fn is a cubic spline curve, defined recursively in + terms of the number of levels, k. There are 2^^k + segments and 2^^k - 1 parameters. For k = 1 there is 1 + parameter, that locates a point on the diagonal from + (0,1) to (1,0). That point is the mutual corner of two + new boxes on whose diagonals two level 2 parameters + locate new points. That creates 4 boxes at level 3, and + so on. + + The corner points are tabulated as x and y arrays and + converted to a pair of monotonic Hermite splines that + can be read as y(x) and x(y). + + The basic parameters range from -1/2 at the lower right + corner of a box to 1/2 at the upper left corner. For + convenience in dealing with unconstrained optimizers, + there is an interface that maps this range to the + tangent of an angle (-infinity at lwr rgt, +infinity + at upper left). + + Initially all parameters are 0 (straight line). + + The fns to copy params in and out take an optional argument + k to select a "leading subset", e.g. k = 1 just copies the + center point parameter. This k must be <= the k passed to + c'tor and defaults to that value. Note the params are + copied in left to right order in any case. + +*/ + +class ssifn { +public: + ssifn( int k = 4 ); // default 15 adjustable points + ~ssifn(); + int getParamCount( int k = 0 ); // returns number of params + int getParams( double * p, int k = 0 ); // returns count + int setParams( double * p, int k = 0 ); // returns 1 ok 0 fail + int getInfParams( double * p, int k = 0 ); // returns count + int setInfParams( double * p, int k = 0 ); // returns 1 ok 0 fail + double yofx( double x ); + double xofy( double y ); +protected: + int kmax; + int npts; + double * para; + double * xval, * yval; + double * Cxy, * Cyx; + int setSpline(); + void sssub(int l, int r); +}; + /* A libpano stack function transforms 'dest' coordinates to 'source' coordinates according to an unspecified set of parameters. These definitions are from filter.h @@ -130,10 +210,13 @@ */ int fD_photo_sphere( fDesc * pfd ); // to real int fD_sphere_photo( fDesc * pfd ); // to ideal - /* compute the image <=> equal angle fisheye mappings */ - int photo_sphere( double x_dest, double y_dest, double* x_src, double* y_src ); - int sphere_photo( double x_dest, double y_dest, double* x_src, double* y_src ); - /* select the color channel to be mapped */ + /* compute the image <=> 2d sphere (equal angle fisheye) mappings */ + int photo_sphere( double x_sphr, double y_sphr, double* x_phot, double* y_phot ); + int sphere_photo( double x_phot, double y_phot, double* x_sphr, double* y_sphr ); + /* compute image <=> Cartesian unit sphere mappings */ + int photo_cart3d( double xyz_sphr[3], double* x_phot, double* y_phot ); + int cart3d_photo( double x_phot, double y_phot, double xyz_sphr[3] ); +/* set the color channel to be mapped (selects a tca parameter) */ bool setColorChannel( int rgb ); /* parameter optimization API setOptPurpose() selects a set of parameters and returns their number @@ -148,10 +231,10 @@ get/setOptParams() copy the selected values out/in */ int setOptPurpose( opt_purpose p, - int polyN = 1, - bool optCen = true, - bool optScl = false, - bool optTca = false ); + int optRad = 2, // detail level of radius correction + bool optCen = false, // optimize center shifts + bool optScl = false, // optimize fov + bool optTca = false ); // optimize a tca param int getOptParams( double * ppa ); // copy to array int setOptParams( double * ppa ); // copy from array @@ -170,12 +253,18 @@ lens_kind l_type, double FLmm, double maxFOVdeg ); + bool setMaxAngle( double cropdegrees ); + // inquiry functions double getFL_mm(){ return FL_mm; } double avgFL_pix(){ return 0.5 * (hFLpix + vFLpix); } const char * camDesc(); const char * lensDesc(); + // translate internal radius function to/from external polynomial + bool getRadiusPoly( double * pc, int polyN, bool fwd = false ); + bool setRadiusPoly( double * pc, int polyN, bool fwd = false ); + // set primary and working parameter values bool set_f_scale( double h_scl, double v_scl ); bool set_c_shift( double h_shfmm, double y_shfmm ); @@ -223,7 +312,7 @@ bool model_valid; bool spline_valid; int color; // 0: red, 1: green, 2: blue - int opt_polyn; + int opt_rad_k; bool opt_center; bool opt_scale; bool opt_tca; @@ -234,14 +323,15 @@ // validate model and fill the tables bool setSpline(); // partial radial functions - // computed direct from model parameters + // ideal fns computed direct from model parameters double AofR( double R ); double RofA( double A ); - double rofR( double R ); - + /* internal radius correction function + Note yofx() is real(ideal), xofy() is ideal(real); + they cover 0:1 in both x and y + */ + ssifn radfn; }; - - #endif //ndef _LENSFUNC_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |