[ptx] Looking for expertise on optimizer internals
Littlefields - Rik, Janis, Kyle & Peter
rj.littlefield at computer.org
Tue Apr 27 05:41:46 BST 2004
Pablo,
The code is small enough that I will just include it here, after my
signature.
There are mods to adjust.c and optimise.c. In adjust.c, I replace
fcnPano and
introduce a function newDistSphere, logically replacing the old distSphere.
In optimise.C, I allocate o->numData*2 function slots instead of o->numData.
Replies to your other comments interspersed below...
Pablo d'Angelo wrote:
>On Mon, 26 Apr 2004, Littlefields - Rik, Janis, Kyle & Peter wrote:
>
>
>
>>Briefly, I have working prototype code that changes the way that the
>>lmdif optimizer is called. The original code seeks to optimize distance
>>squared, where distance is what lmdif sees. My mods also seek to
>>optimize distance squared, but the formulation is to optimize dx^2 +
>>dy^2, where dx and dy are what lmdif sees.
>>
>>The change in formulation gives lmdif better information about how to
>>change the parameters, leading to faster and more accurate convergence.
>>
>>But of course there are wrinkles dealing with wraparound and near-polar
>>points, and I would like to tap into whatever other people know about
>>the optimizer, to be sure that I don't mess things up..
>>
>>
>
>I think panotools uses angular differences (for normal control points), and
>its probably a not good idea to split the spherical coordinates and use them
>like they where normal cartesian coordinates, at least near the poles.
>
>
Yes, it appears to be using latitude/longitude style coordinates. These
can be
handled by scaling longitude by sin(latitude) [in 0..pi], then treating
as normal cartesian.
See the code for details.
>>If you have experience with the guts of adjust.c and are willing to
>>share it, please chime in.
>>
>>
>
>Sounds very interesting. I'm still thinking about adding a (optional)
>penalty for the HFOV optimisation, so that it becomes possible to optimise
>it for partial panos as well.
>
>
I regularly use HFOV optimization for partial panos, but yes, there are lots
of pits to fall into. We should split this topic off to a separate thread.
>Can you post you code, or the patches, so that we can see exactly what you
>modified.
>
>ciao
> Pablo
>
>
Current code follows, in Textpad Compare Files format.
Best regards,
--Rik
Compare: (<)C:\Rik\PanoramaTools2.6.ML12\PanoTools\Sources\adjust.c
(59753 bytes)
with:
(>)C:\Rik\PanoramaTools2.6.ML12_beforeHacking\PanoTools\Sources\adjust.c
(55785 bytes)
1246d1246
< #if 0 // old version, replaced by Rik Littlefield
1323,1484d1322
< #endif
<
< /* ---- Revision history ----
<
< 04/26/2004, Rik Littlefield, reworked fcnPano and newDistSphere to
expose dx and dy
< separately to the optimizer (e.g.lmdif).
< */
<
< // Angular Distance of Control point "num"
<
< void newDistSphere (int num, double cdiff[2]) {
< double x, y ; // Coordinates of control point in panorama
< double w2, h2;
< int j;
< Image sph;
< int n[2];
< struct MakeParams mp;
< struct fDesc stack[15];
< double lat[2], lon[2]; // latitude & longitude, in degrees
< double dlon;
<
< // Get image position in imaginary spherical image
<
< SetImageDefaults( &sph );
<
< sph.width = 360;
< sph.height = 180;
< sph.format = _equirectangular;
< sph.hfov = 360.0;
<
< n[0] = g->cpt[num].num[0];
< n[1] = g->cpt[num].num[1];
<
< // Calculate coordinates x/y in panorama
<
< for(j=0; j<2; j++){
< SetInvMakeParams( stack, &mp, &g->im[ n[j] ], &sph, 0 );
<
< h2 = (double)g->im[ n[j] ].height / 2.0 - 0.5;
< w2 = (double)g->im[ n[j] ].width / 2.0 - 0.5;
<
<
< execute_stack( (double)g->cpt[num].x[j] - w2, //
cartesian x-coordinate src
< (double)g->cpt[num].y[j] - h2, //
cartesian y-coordinate src
< &x, &y, stack);
<
< x = DEG_TO_RAD( x );
< y = DEG_TO_RAD( y ) + PI/2.0;
<
< // x is now in the range -PI to +PI, and y is 0 to PI
< lat[j] = y;
< lon[j] = x;
<
< }
<
< dlon = lon[0]-lon[1];
< if (dlon <= -PI) dlon += PI;
< if (dlon >= PI) dlon -= PI;
< cdiff[0] = (dlon*sin(0.5*(lat[0]+lat[1]))) * g->pano.width / ( 2.0
* PI );
< cdiff[1] = (lat[0]-lat[1]) * g->pano.width / ( 2.0 * PI );
<
< return;
<
< }
<
<
< // Levenberg-Marquardt function measuring the quality of the fit in fvec[]
<
< int fcnPano(m,n,x,fvec,iflag)
< int m,n;
< int *iflag;
< double x[],fvec[];
< {
< #pragma unused(n)
< int i;
< static int numIt;
< double result;
< int iresult;
< double cdiff[2];
<
< if( *iflag == -100 ){ // reset
< numIt = 0;
< infoDlg ( _initProgress, "Optimizing Variables" );
< return 0;
< }
< if( *iflag == -99 ){ //
< infoDlg ( _disposeProgress, "" );
< return 0;
< }
<
<
< if( *iflag == 0 )
< {
< char message[256];
< result = 0.0;
< for( i=0; i < m; i++)
< {
< result += fvec[i]*fvec[i] ;
< }
< result = sqrt( result/ (double)m );
<
< sprintf( message, "Average Difference between Controlpoints
\nafter %d iteration(s): %25.15g pixels", numIt,result);//average);
< numIt += 10;
< if( !infoDlg ( _setProgress,message ) )
< *iflag = -1;
< return 0;
< }
<
< // Set Parameters
<
< SetAlignParams( x ) ;
<
< // Calculate distances
<
< iresult = 0;
< for( i=0; i < g->numPts; i++){
< int j;
< switch(g->cpt[i].type){
< // For ordinary control points, return the x- and y-errors
< // separately.
< case 0: newDistSphere(i,cdiff);
< fvec[iresult] = cdiff[0];
< fvec[iresult+1] = cdiff[1];
< break;
< // For horizontal, vertical, and line control points,
< // include two copies of the single distance result.
< // Note that we return distance, not distance squared.
< // The optimizer will handle the squaring.
< case 1:
< case 2: fvec[iresult] = sqrt(distSquared(i));
< fvec[iresult+1] = fvec[iresult];
< break;
< default:for(j=0; j<g->numPts; j++){
< if(j!=i && g->cpt[i].type == g->cpt[j].type){
< fvec[iresult] = sqrt(distLine(i,j));
< fvec[iresult+1] = fvec[iresult];
< break;
< }
< }
< break;
< }
< iresult += 2;
< }
<
< // If not enough control points are provided, then fill out
< // the function vector with copies of the average error
< // for the actual control points. This is really just staving
< // off disaster, since we have an underdetermined system,
< // but if we've gotten this far down, it's really about all
< // we can do.
<
< result = 0.0;
< for (i=0; i < iresult; i++) {
< result += fvec[i]*fvec[i];
< }
< result = sqrt(result/(double)iresult);
< for (i=iresult; i < m; i++) {
< fvec[i] = result;
< }
<
< return 0;
< }
Compare: (<)C:\Rik\PanoramaTools2.6.ML12\PanoTools\Sources\optimize.c
(9861 bytes)
with:
(>)C:\Rik\PanoramaTools2.6.ML12_beforeHacking\PanoTools\Sources\optimize.c
(9414 bytes)
33,42c33,36
< // PrintError("RunLMOptimizer");
< LM.n = o->numVars;
<
< // We assume here that each control point contributes two
functions to be optimized.
< // For ordinary control points, these functions are the X- and
Y-coordinate errors.
< // Horizontal, vertical, and line control points each contribute
only a single
< // function logically, but fcnPano (in adjust.c) replicates these
to consistently
< // provide two functions per control point.
<
< if( o->numData*2 < LM.n )
---
>
> LM.n = o->numVars;
>
> if( o->numData < LM.n )
46d40
< PrintError("You have too few control points or too many
parameters. Expect strange values!");
50c43
< LM.m = o->numData*2;
---
> LM.m = o->numData;
134,137c127,129
< // PrintError("RunBROptimizer");
< LM.n = o->numVars;
<
< if( o->numData*2 < LM.n )
---
> LM.n = o->numVars;
>
> if( o->numData < LM.n )
143c135
< LM.m = o->numData*2;
---
> LM.m = o->numData;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.email-lists.org/pipermail/ptx/attachments/20040426/63f47508/attachment.htm
More information about the ptX
mailing list