static void MakeStripRasters( CSuperscape &A, CSuperscape &B ) { char buf[256]; #if 1 A.MakeRasH(); sprintf( buf, "strips/A_%d.png", gArgs.za ); A.DrawRas( buf ); B.MakeRasV(); sprintf( buf, "strips/B_%d.png", gArgs.zb ); B.DrawRas( buf ); #else // simple debugging - load existing image, but does // NOT acquire {x0,y0,B,...} meta data!! sprintf( buf, "Astrip_%d.png", gArgs.za ); A.Load( buf, flog ); sprintf( buf, "Bstrip_%d.png", gArgs.zb ); B.Load( buf, flog ); #endif }
// Here's the strategy: // We paint a scape for the whole A-block and match it to the // scape for the nearest whole B-block below. If the correlation // (R-block) is at least blockmincorr then we use this B-block and // pair off the tiles. Otherwise, the match is too uncertain and // we ignore this B-block. Remember that the block match transform // will set a search disc for the tile-tile jobs, and this will not // be questioned at the tile level. Therefore, we need to feed very // reliable block-block matches to the tile jobs. // // To do tile pairing, for each A-tile we keep a list of 'pair' // records with these fields { // - id of B-tile that overlaps it (iff overlap >= 0.02). // - the fractional overlap area. // - link (iz) to data about this B-block, especially R-block. // } // // Next we determine if we have enough high quality data matched // to our A-tiles, or we need to examine the next B-block. We have // enough data if at least 0.90 of the A-tiles have good matches, // or if we have already used the lowest allowed B-layer (zmin). // // The test of good matches for an A-tile goes like this: // - Sort its pair records, descending R order, (but place highest // B-layer at the head of the list if its R is within 90% of the // best R yet. We'll get better smoothness if we can keep matches // to nearest layers). // - Sum the fractional areas of records with R >= blocknomcorr. // - Call this A-tile matched if its sum is >= 0.30. // Summing is admittedly coarse, we just sum fractional overlap // areas without regard to orientation, and it's good enough for // a coverage assessment. // // There's an additional clause to stop looking at more B-blocks // a bit earlier, and this really comes into play if few of the // blocks in this region are as good as blocknomcorr. Let's call // the coverage obtained using only great tissue (> blocknomcorr) // 'prime coverage' and the coverage we can get from all blocks // done so far 'secondary coverage'. If we've already looked at // half of the prospective blocks and the secondary coverage is // already adequate (0.90 A-tiles matched) then let's give up. // // Once we've finished accumulating pair records, we proceed // with writing the make.down job files. We do one A-tile at // a time. Its list of pair records is already sorted by R. As // we walk the pair list we keep a running sum of area. If the // current area sum is < 0.80, we sum in all of the tiles with // the current iz index (all come from the same layer) and we // write jobs for those matches. If the sum is still below 0.80 // coverage we repeat for the next set of tiles with a poorer // quality, and so on until coverage is >= 0.80 or the records // are exhausted. // static void LayerLoop() { clock_t t0 = StartTiming(); vector<BlkZ> vZ; vector<vector<Pair> > P( gDat.ntil ); CSuperscape A; ThmRec thm; int next_isN; fprintf( flog, "\n--- Start A layer ----\n" ); A.SetLabel( 'A' ); next_isN = A.FindLayerIndices( TS.vtil.size() ); A.vID_From_sID(); A.CalcBBox(); A.MakeRasA(); A.DrawRas(); A.MakePoints( thm.av, thm.ap ); A.WriteMeta(); t0 = StopTiming( flog, "MakeRasA", t0 ); double prime = 0.0, scdry = 0.0; for(;;) { // align B-block and pair tiles int changed = ThisBZ( vZ, P, A, thm, next_isN ); // any changes to survey? if( gArgs.abdbg ) return; if( next_isN == -1 ) break; if( !changed ) continue; // survey the coverage prime = BlockCoverage( scdry, vZ, P ); fprintf( flog, "Block coverage prime %.2f scdry %.2f Z %d\n", prime, scdry, vZ[vZ.size()-1].Z ); // force measurement of all layers if( gArgs.evalalldz ) continue; // force measurement of at least blockreqdz layers if( vZ.size() < scr.blockreqdz ) continue; // done if satisfied now, or if unlikely to get better if( (prime >= scr.blocknomcoverage) || (scdry >= scr.blocknomcoverage && ZSeen( vZ ) >= 0.50) ) { break; } } fprintf( flog, "Final coverage prime %.2f scdry %.2f ntiles %d\n", prime, scdry, gDat.ntil ); fprintf( flog, "\n--- Write Files ----\n" ); KeepBest( vZ, P ); WriteMakeFile( A, vZ, P ); WriteThumbFiles( vZ ); }
// Return true if changes made. // static bool ThisBZ( vector<BlkZ> &vZ, vector<vector<Pair> > &P, const CSuperscape &A, ThmRec &thm, int &next_isN ) { clock_t t0 = StartTiming(); CSuperscape B; CThmScan S; CorRec best; fprintf( flog, "\n--- Start B layer ----\n" ); B.SetLabel( 'B' ); next_isN = B.FindLayerIndices( next_isN ); if( gArgs.abdbg ) { while( next_isN != -1 && TS.vtil[B.is0].z != gArgs.dbgz ) next_isN = B.FindLayerIndices( next_isN ); } if( next_isN == -1 ) { fprintf( flog, "$$$ Exhausted B layers $$$\n" ); return false; } if( !B.MakeRasB( A.bb ) ) return false; B.DrawRas(); if( !B.MakePoints( thm.bv, thm.bp ) ) { fprintf( flog, "No B points for z=%d.\n", TS.vtil[B.is0].z ); return false; } B.WriteMeta(); t0 = StopTiming( flog, "MakeRasB", t0 ); thm.ftc.clear(); thm.reqArea = int(kPairMinOlap * A.ws * A.hs); thm.olap1D = 4; thm.scl = 1; int Ox = int(A.x0 - B.x0), Oy = int(A.y0 - B.y0), Rx = int((1.0 - scr.blockxyconf) * A.ws), Ry = int((1.0 - scr.blockxyconf) * A.hs); S.Initialize( flog, best ); S.SetRThresh( scr.blockmincorr ); S.SetNbMaxHt( 0.99 ); S.SetSweepConstXY( false ); S.SetSweepPretweak( true ); S.SetSweepNThreads( scr.blockslots ); S.SetUseCorrR( true ); S.SetDisc( Ox, Oy, Rx, Ry ); if( gArgs.abdbg ) { S.Pretweaks( 0, gArgs.abctr, thm ); dbgCor = true; S.RFromAngle( best, gArgs.abctr, thm ); } else { S.Pretweaks( 0, 0, thm ); if( !S.DenovoBestAngle( best, 0, scr.blocksweepspan / 2, scr.blocksweepstep, thm, false ) ) { fprintf( flog, "Low corr [%g] for z=%d.\n", best.R, TS.vtil[B.is0].z ); return false; } Point Aorigin = A.Opts; best.T.Apply_R_Part( Aorigin ); best.X += B.Opts.x - Aorigin.x; best.Y += B.Opts.y - Aorigin.y; best.T.SetXY( best.X, best.Y ); fprintf( flog, "*T: [0,1,2,3,4,5] (block-block)\n" ); fprintf( flog, "[%f,%f,%f,%f,%f,%f]\n", best.T.t[0], best.T.t[1], best.T.t[2], best.T.t[3], best.T.t[4], best.T.t[5] ); } t0 = StopTiming( flog, "Corr", t0 ); if( gArgs.abdbg ) return false; // Build: montage -> montage transform TAffine s, t; // A montage -> A block image s.NUSetScl( inv_scl ); s.AddXY( -A.x0, -A.y0 ); // A block image -> B block image t = best.T * s; // B block image -> B montage t.AddXY( B.x0, B.y0 ); s.NUSetScl( scr.crossscale ); best.T = s * t; // Append to list vZ.push_back( BlkZ( best.T, best.R, TS.vtil[B.is0].z ) ); // Accumulate pairs FindPairs( vZ, P, A, B ); return true; }