Пример #1
0
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;
}