[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