gtkdoc for mosaicing

This commit is contained in:
John Cupitt 2011-01-25 13:12:22 +00:00
parent 823650b2b4
commit 1aea6a1347
21 changed files with 732 additions and 495 deletions

View File

@ -9,6 +9,10 @@
Nicolas Robidoux)
- no tables for uchar either, about a 15% speedup (thanks Nicolas)
- dmask write was broken
- lr/tbmerge() cast images to match, like im_insert()
- lr/tbmosaic() work for any mix of image formats / bands
- removed ancient balance stuff from im_lr/tbmosaic()
- gtk-doc for mosaicing
30/11/10 started 7.24.0
- bump for new stable

3
TODO
View File

@ -1,5 +1,8 @@
- half-way thorough making fits read lazy
- im__open_write() should take a mode (text / binary)

View File

@ -44,12 +44,12 @@
<xi:include href="xml/inplace.xml"/>
<xi:include href="xml/mask.xml"/>
<xi:include href="xml/morphology.xml"/>
<xi:include href="xml/mosaicing.xml"/>
</chapter>
<chapter>
<title>VIPS operation API by section (no gtkdoc comments yet)</title>
<xi:include href="xml/resample.xml"/>
<xi:include href="xml/mosaicing.xml"/>
<xi:include href="xml/other.xml"/>
<xi:include href="xml/video.xml"/>
<xi:include href="xml/cimg_funcs.xml"/>

View File

@ -767,7 +767,7 @@ im_tbmerge1 - first-order top-bottom merge of in1 and in2
im_tbmosaic - top-bottom mosaic of in1 and in2
im_tbmosaic1 - first-order top-bottom mosaic of ref and sec
\end{verbatim}
\caption{Mosaic functions}
caption{Mosaic functions}
\label{fg:mosaicing}
\end{fig2}

View File

@ -197,7 +197,8 @@ maxpos_scan( REGION *reg, void *seq, void *a, void *b )
* image type. Returns a double and the location of max. For complex images,
* finds the pixel with the highest modulus.
*
* See also: im_minpos(), im_min(), im_stats(), im_maxpos_avg().
* See also: im_minpos(), im_min(), im_stats(), im_maxpos_avg(),
* im_maxpos_subpel(), im_maxpos_vec().
*
* Returns: 0 on success, -1 on error
*/

View File

@ -76,10 +76,9 @@
* - cast in1 and in2 up to a common format
* - equalise bands
* - make an input array
* - run the supplied area operation passing one of the up-banded,
* up-casted and up-sized inputs as the first param
* - return the matched images in vec[0] and vec[1]
*/
static IMAGE **
IMAGE **
im__insert_base( const char *domain,
IMAGE *in1, IMAGE *in2, IMAGE *out )
{

View File

@ -177,6 +177,8 @@ int im__colour_difference( const char *domain,
int im__colour_unary( const char *domain,
IMAGE *in, IMAGE *out, VipsType type,
im_wrapone_fn buffer_fn, void *a, void *b );
IMAGE **im__insert_base( const char *domain,
IMAGE *in1, IMAGE *in2, IMAGE *out );
/* Structure for holding the lookup tables for XYZ<=>rgb conversion.
* Also holds the luminance to XYZ matrix and the inverse one.

View File

@ -54,28 +54,28 @@ int im_tbmerge1( IMAGE *ref, IMAGE *sec, IMAGE *out,
int im_lrmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
int bandno,
int xref, int yref, int xsec, int ysec,
int halfcorrelation, int halfarea,
int hwindowsize, int hsearchsize,
int balancetype,
int mwidth );
int im_tbmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
int im_tbmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
int bandno,
int xref, int yref, int xsec, int ysec,
int halfcorrelation, int halfarea,
int xref, int yref, int xsec, int ysec,
int hwindowsize, int hsearchsize,
int balancetype,
int mwidth );
int im_lrmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
int im_lrmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
int bandno,
int xr1, int yr1, int xs1, int ys1,
int xr1, int yr1, int xs1, int ys1,
int xr2, int yr2, int xs2, int ys2,
int halfcorrelation, int halfarea,
int hwindowsize, int hsearchsize,
int balancetype,
int mwidth );
int im_tbmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
int bandno,
int xr1, int yr1, int xs1, int ys1,
int xr2, int yr2, int xs2, int ys2,
int halfcorrelation, int halfarea,
int hwindowsize, int hsearchsize,
int balancetype,
int mwidth );

View File

@ -53,6 +53,8 @@
* - weed out overlaps which contain only transparent pixels
* 4/1/07
* - switch to new history thing, switch im_errormsg() too
* 24/1/11
* - gtk-doc
*/
/*
@ -167,9 +169,8 @@ im__global_open_image( SymbolTable *st, char *name )
{
IMAGE *im;
if( (im = im_open_local( st->im, name, "r" )) )
return( im );
if( (im = im_open_local( st->im, im_skip_dir( name ), "r" )) )
if( (im = im_open_local( st->im, name, "r" )) ||
(im = im_open_local( st->im, im_skip_dir( name ), "r" )) )
return( im );
return( NULL );
@ -296,9 +297,8 @@ im__build_symtab( IMAGE *out, int sz )
SymbolTable *st = IM_NEW( out, SymbolTable );
int i;
if( !st )
return( NULL );
if( !(st->table = IM_ARRAY( out, sz, GSList * )) )
if( !st ||
!(st->table = IM_ARRAY( out, sz, GSList * )) )
return( NULL );
st->sz = sz;
st->im = out;
@ -1699,7 +1699,38 @@ transformf( JoinNode *node, double *gamma )
return( out );
}
/* Balance mosaic, outputting in the original format.
/**
* im_global_balance:
* @in: mosaic to rebuild
* @out: output image
* @gamma: gamma of source images
*
* im_global_balance() can be used to remove contrast differences in
* an assembled mosaic.
*
* It reads the History field attached to @in and builds a list of the source
* images that were used to make the mosaic and the position that each ended
* up at in the final image.
*
* It opens each of the source images in turn and extracts all parts which
* overlap with any of the other images. It finds the average values in the
* overlap areas and uses least-mean-square to find a set of correction
* factors which will minimise overlap differences. It uses @gamma to
* gamma-correct the source images before calculating the factors. A value of
* 1.0 will stop this.
*
* Each of the source images is transformed with the appropriate correction
* factor, then the mosaic is reassembled. @out always has the same #BandFmt
* as @in. Use im_global_balancef() to get float output and avoid clipping.
*
* There are some conditions that must be met before this operation can work:
* the source images must all be present under the filenames recorded in the
* history on @in, and the mosaic must have been built using only operations in
* this package.
*
* See also: im_global_balancef(), im_remosaic().
*
* Returns: 0 on success, -1 on error
*/
int
im_global_balance( IMAGE *in, IMAGE *out, double gamma )
@ -1715,9 +1746,19 @@ im_global_balance( IMAGE *in, IMAGE *out, double gamma )
return( 0 );
}
/* Balance mosaic, outputting as float. This is useful if the automatic
* selection of balance range fails - our caller can search the output for the
* min and max, and rescale to prevent burn-out.
/**
* im_global_balancef:
* @in: mosaic to rebuild
* @out: output image
* @gamma: gamma of source images
*
* Just as im_global_balance(), but the output image is always float. This
* stops overflow or underflow in the case of an extremely unbalanced image
* mosaic.
*
* See also: im_global_balance(), im_remosaic().
*
* Returns: 0 on success, -1 on error
*/
int
im_global_balancef( IMAGE *in, IMAGE *out, double gamma )

View File

@ -43,6 +43,20 @@
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/**
* im_align_bands:
* @in: image to align
* @out: output image
*
* This operation uses im_phasecor_fft() to find an integer displacement to
* align all image bands band 0. It is very slow and not very accurate.
*
* Use im_estpar() in preference: it's fast and accurate.
*
* See also: im_global_balancef(), im_remosaic().
*
* Returns: 0 on success, -1 on error
*/
int im_align_bands( IMAGE *in, IMAGE *out ){
#define FUNCTION_NAME "im_align_bands"
if( im_piocheck( in, out ))

View File

@ -1,33 +1,4 @@
/* @(#) Functions which improve the selection of two ttie points pairs in two
* @(#) images, by estimating the correlation coefficient given in page 426
* @(#) 2nd edn of the book Digital Image processing Gonzalez and Wintz
* @(#) The function works as follows:
* @(#) It expects to receive nopoints pairs (coordinates) of points
* @(#) corresponding to ref and sec.
* @(#) The coordinates of the pairs are in arrays x1,y1 and x2,y2
* @(#) After that the program reads a region of 2*halfcorsize +1 pels centered
* @(#) at point (x1, y1) and looks around
* @(#) an area 2*halfareasize+1 centered at point (x2, y2).
* @(#) For each point in this 2*halfareasize+1,
* @(#) the program reads the corresponding
* @(#) image2 values in a region of 2*halfcorsize+1 pels centered at this point
* @(#) and calculates the corresponding correlation coefficients.
* @(#) The result is stored in a the array
* @(#) corcoef[(2*halfareasize+1)(2*halfareasize+1)]. Within this window, the
* @(#) max correlation coefficient is estimated and its corresponding
* @(#) (x, y) coordinates are returned in (x2, y2).
* @(#) The purpose of this function is to improve the selection of
* @(#) control points entered in (x1, y1)
* @(#) Both input images should are either memory mapped or in a buffer.
* @(#) The variable bandno should be between 1 and ref->Bands
* @(#) The program fills the dx[] and dy[] arrays before returning.
* @(#)
* @(#) int im__chkpair( ref, sec, bandno, points )
* @(#) IMAGE *ref, *sec;
* @(#) int bandno;
* @(#) TIE_POINTS *points;
* @(#)
* @(#) Returns 0 on sucess and -1 on error.
/* find image overlaps
*
* Copyright: 1990, N. Dessipris.
*
@ -42,6 +13,8 @@
* - now uses im_spcor()
* 13/8/96 JC
* - order of args changed to help C++ API
* 24/1/11
* - gtk-doc
*/
/*
@ -87,13 +60,36 @@
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Find position of sec within ref. Search around point xsec, ysec for the
* best match for the area around xref, yref. Search an area of size
* hsearchsize for an of size hwindowsize.
/**
* im_correl:
* @ref: reference image
* @sec: secondary image
* @xref: position in reference image
* @yref: position in reference image
* @xsec: position in secondary image
* @ysec: position in secondary image
* @hwindowsize: half window size
* @hsearchsize: half search size
* @correlation: return detected correlation
* @x: return found position
* @y: return found position
*
* Return a new value for xsec, ysec and the correlation at that point.
* This operation finds the position of @sec within @ref.
*
* The area around
* (@xsec, @ysec) is searched for the best match to the area around (@xref,
* @yref). It searches an area of size @hsearchsize for a
* match of size @hwindowsize. The position of the best match is
* returned, together with the correlation at that point.
*
* Only the first band of each image is correlated. @ref and @sec may be
* very large --- the function extracts and generates just the
* parts needed. Correlation is done with im_spcor(); the position of
* the maximum is found with im_maxpos().
*
* Also used by im_match_linear(), im_match_linear_search(), etc.
* See also: im_match_linear(), im_match_linear_search(), im_lrmosaic().
*
* Returns: 0 on success, -1 on error
*/
int
im_correl( IMAGE *ref, IMAGE *sec,

View File

@ -1,14 +1,4 @@
/* Merge two images left-right. dx, dy is the offset needed to get from sec
* (secondary image) to ref (reference image).
*
* Usage:
*
* int
* im_lrmerge( ref, sec, out, dx, dy )
* IMAGE *ref, *sec, *out;
* int dx, dy;
*
* Returns 0 on success and -1 on error
/* Merge two images left-right.
*
* Copyright: 1990, 1991 N. Dessipris
* Author: N. Dessipris
@ -88,6 +78,9 @@
* 20/6/05
* - now requires all bands == 0 for transparency (used to just check
* band 0)
* 24/1/11
* - gtk-doc
* - match formats and bands automatically
*/
/*
@ -700,22 +693,23 @@ lock_free( GMutex *lock )
* im_tbmerge, so not static.
*/
Overlapping *
im__build_mergestate( IMAGE *ref, IMAGE *sec, IMAGE *out,
int dx, int dy, int mwidth )
im__build_mergestate( const char *domain,
IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
{
Overlapping *ovlap = IM_NEW( out, Overlapping );
IMAGE **vec;
Overlapping *ovlap;
int x;
if( !ovlap )
if( !(vec = im__insert_base( domain, ref, sec, out )) ||
!(ovlap = IM_NEW( out, Overlapping )) )
return( NULL );
if( mwidth < -1 ) {
im_error( "im_lr/tbmerge",
"%s", _( "mwidth must be -1 or >= 0" ) );
im_error( domain, "%s", _( "mwidth must be -1 or >= 0" ) );
return( NULL );
}
ovlap->ref = ref;
ovlap->sec = sec;
ovlap->ref = vec[0];
ovlap->sec = vec[1];
ovlap->out = out;
ovlap->dx = dx;
ovlap->dy = dy;
@ -725,21 +719,21 @@ im__build_mergestate( IMAGE *ref, IMAGE *sec, IMAGE *out,
*/
ovlap->rarea.left = 0;
ovlap->rarea.top = 0;
ovlap->rarea.width = ref->Xsize;
ovlap->rarea.height = ref->Ysize;
ovlap->rarea.width = ovlap->ref->Xsize;
ovlap->rarea.height = ovlap->ref->Ysize;
/* Area occupied by sec image.
*/
ovlap->sarea.left = -dx;
ovlap->sarea.top = -dy;
ovlap->sarea.width = sec->Xsize;
ovlap->sarea.height = sec->Ysize;
ovlap->sarea.width = ovlap->sec->Xsize;
ovlap->sarea.height = ovlap->sec->Ysize;
/* Compute overlap.
*/
im_rect_intersectrect( &ovlap->rarea, &ovlap->sarea, &ovlap->overlap );
if( im_rect_isempty( &ovlap->overlap ) ) {
im_error( "im_lr/tbmerge", "%s", _( "no overlap" ) );
im_error( domain, "%s", _( "no overlap" ) );
return( NULL );
}
@ -794,12 +788,13 @@ build_lrstate( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
{
Overlapping *ovlap;
if( !(ovlap = im__build_mergestate( ref, sec, out, dx, dy, mwidth )) )
if( !(ovlap = im__build_mergestate( "im_lrmerge",
ref, sec, out, dx, dy, mwidth )) )
return( NULL );
/* Select blender.
*/
switch( ref->Coding ) {
switch( ovlap->ref->Coding ) {
case IM_CODING_LABQ:
ovlap->blend = lr_blend_labpack;
break;
@ -1040,7 +1035,7 @@ im__start_merge( IMAGE *out, void *a, void *b )
int
im__lrmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
{
{
Overlapping *ovlap;
#ifdef DEBUG
@ -1051,20 +1046,6 @@ im__lrmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
printf( "sec is %d x %d pixels\n", sec->Xsize, sec->Ysize );
#endif
/* Check IMAGEs parameters
*/
if( ref->Bands != sec->Bands ||
ref->BandFmt != sec->BandFmt ||
ref->Coding != sec->Coding ) {
im_error( "im_lrmerge",
"%s", _( "input images incompatible" ) );
return( -1 );
}
if( ref->Coding != IM_CODING_NONE && ref->Coding != IM_CODING_LABQ ) {
im_error( "im_lrmerge",
"%s", _( "inputs not uncoded or IM_CODING_LABQ" ) );
return( -1 );
}
if( dx > 0 || dx < 1 - ref->Xsize ) {
#ifdef DEBUG
printf( "im__lrmerge: no overlap, using insert\n" );
@ -1079,8 +1060,6 @@ im__lrmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
return( 0 );
}
if( im_piocheck( ref, out ) || im_piocheck( sec, out ) )
return( -1 );
/* Build state for this join.
*/
@ -1089,7 +1068,7 @@ im__lrmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
/* Prepare the output IMAGE.
*/
if( im_cp_descv( out, ref, sec, NULL ) )
if( im_cp_descv( out, ovlap->ref, ovlap->sec, NULL ) )
return( -1 );
out->Xsize = ovlap->oarea.width;
out->Ysize = ovlap->oarea.height;
@ -1098,7 +1077,7 @@ im__lrmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
/* Set demand hints.
*/
if( im_demand_hint( out, IM_THINSTRIP, ref, sec, NULL ) )
if( im_demand_hint( out, IM_THINSTRIP, ovlap->ref, ovlap->sec, NULL ) )
return( -1 );
/* Generate!
@ -1110,6 +1089,43 @@ im__lrmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
return ( 0 );
}
/**
* im_lrmerge:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @dx: displacement of ref from sec
* @dy: displacement of ref from sec
* @mwidth: maximum seam width
*
* This operation joins two images left-right (with @ref on the left) with a
* smooth seam.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* @dx and @dy give the displacement of @sec relative to @ref, in other words,
* the vector to get from the origin of @sec to the origin of @ref, in other
* words, @dx will generally be a negative number.
*
* @mwidth limits the maximum width of the
* blend area. A value of "-1" means "unlimited". The two images are blended
* with a raised cosine.
*
* Pixels with all bands equal to zero are "transparent", that
* is, zero pixels in the overlap area do not contribute to the merge.
* This makes it possible to join non-rectangular images.
*
* See also: im_lrmosaic(), im_tbmerge(), im_match_linear(), im_insert().
*
* Returns: 0 on success, -1 on error
*/
int
im_lrmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
{

View File

@ -1,16 +1,4 @@
/* @(#) Program to calculate the best possible tie points
* @(#) in the overlapping part between the primary and the secondary picture
* @(#)
* @(#) Right call:
* @(#) int im_lrmosaic( reference, secondary, out, bandno,
* @(#) xref, yref, xsec, ysec, halfcorrelation, halfarea )
* @(#) IMAGE *reference, *secondary, *out;
* @(#) int bandno;
* @(#) int xref, yref, xsec, ysec;
* @(#) int halfcorrelation, halfarea;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
/* join left-right with an approximate overlap
*
* Copyright: 1990, N. Dessipris.
*
@ -32,6 +20,11 @@
* - added tunable max blend width
* 24/2/05
* - im_scale() makes it work for any image type
* 25/1/11
* - gtk-doc
* - remove balance stuff
* - any mix of types and bands
* - cleanups
*/
/*
@ -109,23 +102,14 @@ im__find_lroverlap( IMAGE *ref_in, IMAGE *sec_in, IMAGE *out,
int *dx0, int *dy0,
double *scale1, double *angle1, double *dx1, double *dy1 )
{
Rect left, right, overlap;
IMAGE *ref, *sec;
IMAGE *t[6];
TIE_POINTS points, *p_points;
TIE_POINTS newpoints, *p_newpoints;
int dx, dy;
int i;
Rect left, right, overlap;
/* Check ref and sec are compatible.
*/
if( ref_in->Bands != sec_in->Bands ||
ref_in->BandFmt != sec_in->BandFmt ||
ref_in->Coding != sec_in->Coding ) {
im_error( "im_lrmosaic", "%s", _( "input images incompatible" ) );
return( -1 );
}
/* Test cor and area.
*/
if( halfcorrelation < 0 || halfarea < 0 ||
@ -148,68 +132,39 @@ im__find_lroverlap( IMAGE *ref_in, IMAGE *sec_in, IMAGE *out,
/* Find overlap.
*/
im_rect_intersectrect( &left, &right, &overlap );
if( overlap.width < 2*halfarea + 1 ||
overlap.height < 2*halfarea + 1 ) {
im_error( "im_lrmosaic", "%s", _( "overlap too small for search" ) );
if( overlap.width < 2 * halfarea + 1 ||
overlap.height < 2 * halfarea + 1 ) {
im_error( "im_lrmosaic",
"%s", _( "overlap too small for search" ) );
return( -1 );
}
/* Extract overlaps.
/* Extract overlaps as 8-bit, 1 band.
*/
ref = im_open_local( out, "temp_one", "t" );
sec = im_open_local( out, "temp_two", "t" );
if( !ref || !sec )
return( -1 );
if( ref_in->Coding == IM_CODING_LABQ ) {
IMAGE *t1 = im_open_local( out, "temp:3", "p" );
IMAGE *t2 = im_open_local( out, "temp:4", "p" );
IMAGE *t3 = im_open_local( out, "temp:5", "p" );
IMAGE *t4 = im_open_local( out, "temp:6", "p" );
IMAGE *t5 = im_open_local( out, "temp:7", "p" );
IMAGE *t6 = im_open_local( out, "temp:8", "p" );
if( !t1 || !t2 || !t3 || !t4 || !t5 || !t6 )
return( -1 );
if( im_extract_area( ref_in, t1,
if( !(ref = im_open_local( out, "temp_one", "t" )) ||
!(sec = im_open_local( out, "temp_two", "t" )) ||
im_open_local_array( out, t, 6, "im_lrmosaic", "p" ) ||
im_extract_area( ref_in, t[0],
overlap.left, overlap.top,
overlap.width, overlap.height ) )
return( -1 );
if( im_extract_area( sec_in, t2,
overlap.width, overlap.height ) ||
im_extract_area( sec_in, t[1],
overlap.left - right.left, overlap.top - right.top,
overlap.width, overlap.height ) )
return( -1 );
if( im_LabQ2Lab( t1, t3 ) || im_LabQ2Lab( t2, t4 ) ||
im_Lab2disp( t3, t5, im_col_displays( 1 ) ) ||
im_Lab2disp( t4, t6, im_col_displays( 1 ) ) )
return( -1 );
/* Extract the green.
*/
if( im_extract_band( t5, ref, 1 ) ||
im_extract_band( t6, sec, 1 ) )
return( -1 );
if( ref_in->Coding == IM_CODING_LABQ ) {
if( im_LabQ2Lab( t[0], t[2] ) ||
im_LabQ2Lab( t[1], t[3] ) ||
im_Lab2disp( t[2], t[4], im_col_displays( 1 ) ) ||
im_Lab2disp( t[3], t[5], im_col_displays( 1 ) ) ||
im_extract_band( t[4], ref, 1 ) ||
im_extract_band( t[5], sec, 1 ) )
return( -1 );
}
else if( ref_in->Coding == IM_CODING_NONE ) {
IMAGE *t1 = im_open_local( out, "temp:9", "p" );
IMAGE *t2 = im_open_local( out, "temp:10", "p" );
IMAGE *t3 = im_open_local( out, "temp:11", "p" );
IMAGE *t4 = im_open_local( out, "temp:12", "p" );
if( !t1 || !t2 || !t3 || !t4 )
return( -1 );
if( im_extract_area( ref_in, t1,
overlap.left, overlap.top,
overlap.width, overlap.height ) )
return( -1 );
if( im_extract_area( sec_in, t2,
overlap.left - right.left, overlap.top - right.top,
overlap.width, overlap.height ) )
return( -1 );
if( im_extract_band( t1, t3, bandno_in ) ||
im_extract_band( t2, t4, bandno_in ) )
return( -1 );
if( im_scale( t3, ref ) ||
im_scale( t4, sec ) )
if( im_extract_band( t[0], t[2], bandno_in ) ||
im_extract_band( t[1], t[3], bandno_in ) ||
im_scale( t[2], ref ) ||
im_scale( t[3], sec ) )
return( -1 );
}
else {
@ -286,161 +241,68 @@ im__find_lroverlap( IMAGE *ref_in, IMAGE *sec_in, IMAGE *out,
return( 0 );
}
/* Scale im by fac with a lut.
/**
* im_lrmosaic:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @bandno: band to search for features
* @xref: position in reference image
* @yref: position in reference image
* @xsec: position in secondary image
* @ysec: position in secondary image
* @hwindowsize: half window size
* @hsearchsize: half search size
* @balancetype: no longer used
* @mwidth: maximum blend width
*
* This operation joins two images left-right (with @ref on the left)
* given an approximate overlap.
*
* @sec is positioned so that the pixel (@xsec, @ysec) lies on top of the
* pixel in @ref at (@xref, @yref). The overlap area is divided into three
* sections, 20 high-contrast points in band @bandno of image @ref are found
* in each, and each high-contrast point is searched for in @sec using
* @hwindowsize and @hsearchsize (see im_correl()).
*
* A linear model is fitted to the 60 tie-points, points a long way from the
* fit are discarded, and the model refitted until either too few points
* remain or the model reaches good agreement.
*
* The detected displacement is used with im_lrmerge() to join the two images
* together.
*
* @mwidth limits the maximum width of the
* blend area. A value of "-1" means "unlimited". The two images are blended
* with a raised cosine.
*
* Pixels with all bands equal to zero are "transparent", that
* is, zero pixels in the overlap area do not contribute to the merge.
* This makes it possible to join non-rectangular images.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* See also: im_lrmerge(), im_tbmosaic(), im_insert(), im_global_balance().
*
* Returns: 0 on success, -1 on error
*/
static IMAGE *
transform( IMAGE *out, IMAGE *im, double fac )
{
IMAGE *t1 = im_open_local( out, "transform:1", "p" );
IMAGE *t2 = im_open_local( out, "transform:2", "p" );
IMAGE *t3 = im_open_local( out, "transform:3", "p" );
IMAGE *t4 = im_open_local( out, "transform:4", "p" );
if( !t1 || !t2 || !t3 || !t4 )
return( NULL );
if( fac == 1.0 )
/* Easy!
*/
return( im );
if( im_identity( t1, 1 ) ||
im_lintra( fac, t1, 0.0, t2 ) ||
im_clip2fmt( t2, t3, IM_BANDFMT_UCHAR ) ||
im_maplut( im, t4, t3 ) )
return( NULL );
return( t4 );
}
/* Balance two images. dx, dy parameters as for im_??merge, etc.
*/
int
im__balance( IMAGE *ref, IMAGE *sec, IMAGE *out,
IMAGE **ref_out, IMAGE **sec_out, int dx, int dy, int balancetype )
{
double lavg, ravg;
double lfac, rfac;
Rect left, right, overlap;
IMAGE *t1, *t2;
/* Test balancetype.
*/
if( balancetype < 0 || balancetype > 3 ) {
im_error( "im_mosaic", "%s", _( "bad balancetype parameter" ) );
return( -1 );
}
/* No balance - easy!
*/
if( balancetype == 0 ) {
*ref_out = ref;
*sec_out = sec;
return( 0 );
}
/* Must be uchar uncoded.
*/
if( ref->Coding != IM_CODING_NONE ||
ref->BandFmt != IM_BANDFMT_UCHAR ) {
im_error( "im_mosaic", "%s", _( "uncoded uchar only for balancing" ) );
return( -1 );
}
/* Set positions of left and right.
*/
left.left = 0;
left.top = 0;
left.width = ref->Xsize;
left.height = ref->Ysize;
right.left = -dx;
right.top = -dy;
right.width = sec->Xsize;
right.height = sec->Ysize;
/* Find overlap.
*/
im_rect_intersectrect( &left, &right, &overlap );
/* Extract overlaps.
*/
t1 = im_open_local( out, "temp_one", "p" );
t2 = im_open_local( out, "temp_two", "p" );
if( !t1 || !t2 )
return( -1 );
if( im_extract_area( ref, t1,
overlap.left, overlap.top,
overlap.width, overlap.height ) )
return( -1 );
if( im_extract_area( sec, t2,
overlap.left - right.left, overlap.top - right.top,
overlap.width, overlap.height ) )
return( -1 );
/* And find the average.
*/
if( im_avg( t1, &lavg ) || im_avg( t2, &ravg ) )
return( -1 );
/* Compute scale factors.
*/
switch( balancetype ) {
case 1:
/* Ajust left.
*/
rfac = 1.0;
lfac = ravg / lavg;
break;
case 2:
/* Adjust right.
*/
lfac = 1.0;
rfac = lavg / ravg;
break;
case 3:
{
/* Adjust both to weighted average.
*/
double ltot = (double) ref->Xsize * ref->Ysize;
double rtot = (double) sec->Xsize * sec->Ysize;
double rat = ltot / (ltot + rtot);
double navg = rat * (lavg - ravg) + ravg;
lfac = navg / lavg;
rfac = navg / ravg;
}
break;
default:
error_exit( "internal error #897624395" );
return( -1 );
}
/* Transform the left and right images.
*/
if( !(*ref_out = transform( out, ref, lfac )) )
return( -1 );
if( !(*sec_out = transform( out, sec, rfac )) )
return( -1 );
return( 0 );
}
int
im_lrmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
int bandno,
int xref, int yref, int xsec, int ysec,
int halfcorrelation, int halfarea,
int hwindowsize, int hsearchsize,
int balancetype,
int mwidth )
{
int dx0, dy0;
double scale1, angle1, dx1, dy1;
IMAGE *ref2, *sec2;
IMAGE *dummy;
/* Correct overlap. dummy is just a placeholder used to ensure that
@ -451,7 +313,7 @@ im_lrmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
if( im__find_lroverlap( ref, sec, dummy,
bandno,
xref, yref, xsec, ysec,
halfcorrelation, halfarea,
hwindowsize, hsearchsize,
&dx0, &dy0,
&scale1, &angle1, &dx1, &dy1 ) ) {
im_close( dummy );
@ -459,16 +321,9 @@ im_lrmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
}
im_close( dummy );
/* Balance.
*/
if( im__balance( ref, sec, out,
&ref2, &sec2,
dx0, dy0, balancetype ) )
return( -1 );
/* Merge left right.
*/
if( im_lrmerge( ref2, sec2, out, dx0, dy0, mwidth ) )
if( im_lrmerge( ref, sec, out, dx0, dy0, mwidth ) )
return( -1 );
return( 0 );

View File

@ -1,38 +1,11 @@
/* This function implements:
* "Extension of Phase Correlation to Subpixel Registration"
* by H. Foroosh, from IEEE trans. Im. Proc. 11(3), 2002.
*
* If the best three matches in the correlation are aranged:
*
* 02 or 01
* 1 2
*
* then we return a subpixel match using the ratio of correlations in the
* vertical and horizontal dimension.
*
* ( xs[0], ys[0] ) is the best integer alignment
* ( xs[ use_x ], ys[ use_x ] ) is equal in y and (+/-)1 off in x
* ( xs[ use_y ], ys[ use_y ] ) is equal in x and (+/-)1 off in y
*
*
* Alternatively if the best four matches in the correlation are aranged in
* a square:
*
* 01 or 03 or 02 or 03
* 32 12 31 21
*
* then we return a subpixel match weighting with the sum the two on each
* side over the sum of all four, but only if all four of them are very
* close to the best, and the fifth is nowhere near.
*
* This alternative method is not described by Foroosh, but is often the
* case where the match is close to n-and-a-half pixels in both dimensions.
/* find position of maximum, subpixel estimation
*
* Copyright: 2008, Nottingham Trent University
*
* Author: Tom Vajzovic
*
* Written on: 2008-02-07
*
* 25/1/11
* - gtk-doc
*/
/*
@ -77,6 +50,47 @@
#define MOST_OF( A, B ) ( (A) > 0.9 * (B) )
#define LITTLE_OF( A, B ) ( (B) < 0.1 * (B) )
/**
* im_maxpos_subpel:
* @in: input image
* @x: output position of maximum
* @y: output position of maximum
*
* This function implements:
*
* "Extension of Phase Correlation to Subpixel Registration"
* by H. Foroosh, from IEEE trans. Im. Proc. 11(3), 2002.
*
* If the best three matches in the correlation are aranged:
*
* 02 or 01
* 1 2
*
* then we return a subpixel match using the ratio of correlations in the
* vertical and horizontal dimension.
*
* ( xs[0], ys[0] ) is the best integer alignment
* ( xs[ use_x ], ys[ use_x ] ) is equal in y and (+/-)1 off in x
* ( xs[ use_y ], ys[ use_y ] ) is equal in x and (+/-)1 off in y
*
* Alternatively if the best four matches in the correlation are aranged in
* a square:
*
* 01 or 03 or 02 or 03
* 32 12 31 21
*
* then we return a subpixel match weighting with the sum the two on each
* side over the sum of all four, but only if all four of them are very
* close to the best, and the fifth is nowhere near.
*
* This alternative method is not described by Foroosh, but is often the
* case where the match is close to n-and-a-half pixels in both dimensions.
*
* See also: im_maxpos(), im_min(), im_stats().
*
* Returns: 0 on success, -1 on error
*/
int im_maxpos_subpel( IMAGE *in, double *x, double *y ){
#define FUNCTION_NAME "im_maxpos_subpel"

View File

@ -114,6 +114,28 @@ remosaic( JoinNode *node, RemosaicData *rd )
return( out );
}
/**
* im_remosaic:
* @in: mosaic to rebuild
* @out: output image
* @old_str: gamma of source images
* @new_str: gamma of source images
*
* im_remosaic() works rather as im_global_balance(). It takes apart the
* mosaiced image in and rebuilds it, substituting images.
*
* Unlike im_global_balance(), images are substituted based on their file
* names. The rightmost occurence of the string @old_str is swapped
* for @new_str, that file is opened, and that image substituted for
* the old image.
*
* It's convenient for multispectral images. You can mosaic one band, then
* use that mosaic as a template for mosaicing the others automatically.
*
* See also: im_lrmosaic(), im_global_balance().
*
* Returns: 0 on success, -1 on error
*/
int
im_remosaic( IMAGE *in, IMAGE *out, const char *old_str, const char *new_str )
{

View File

@ -68,6 +68,9 @@
* 20/6/05
* - now requires all bands == 0 for transparency (used to just check
* band 0)
* 24/1/11
* - gtk-doc
* - match formats and bands automatically
*/
/*
@ -616,12 +619,13 @@ build_tbstate( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
{
Overlapping *ovlap;
if( !(ovlap = im__build_mergestate( ref, sec, out, dx, dy, mwidth )) )
if( !(ovlap = im__build_mergestate( "im_tbmerge",
ref, sec, out, dx, dy, mwidth )) )
return( NULL );
/* Select blender.
*/
switch( ref->Coding ) {
switch( ovlap->ref->Coding ) {
case IM_CODING_LABQ:
ovlap->blend = tb_blend_labpack;
break;
@ -665,20 +669,6 @@ im__tbmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
{
Overlapping *ovlap;
/* Check IMAGEs parameters
*/
if( ref->Bands != sec->Bands ||
ref->BandFmt != sec->BandFmt ||
ref->Coding != sec->Coding ) {
im_error( "im_tbmerge",
"%s", _( "input images incompatible" ) );
return( -1 );
}
if( ref->Coding != IM_CODING_NONE && ref->Coding != IM_CODING_LABQ ) {
im_error( "im_tbmerge",
"%s", _( "inputs not uncoded or IM_CODING_LABQ" ) );
return( -1 );
}
if( dy > 0 || dy < 1 - ref->Ysize ) {
/* No overlap, use insert instead.
*/
@ -689,8 +679,6 @@ im__tbmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
return( 0 );
}
if( im_piocheck( ref, out ) || im_piocheck( sec, out ) )
return( -1 );
/* Build state for this join.
*/
@ -720,6 +708,43 @@ im__tbmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
return ( 0 );
}
/**
* im_tbmerge:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @dx: displacement of ref from sec
* @dy: displacement of ref from sec
* @mwidth: maximum seam width
*
* This operation joins two images top-bottom (with @ref on the top) with a
* smooth seam.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* @dx and @dy give the displacement of @sec relative to @ref, in other words,
* the vector to get from the origin of @sec to the origin of @ref, in other
* words, @dx will generally be a negative number.
*
* @mwidth limits the maximum height of the
* blend area. A value of "-1" means "unlimited". The two images are blended
* with a raised cosine.
*
* Pixels with all bands equal to zero are "transparent", that
* is, zero pixels in the overlap area do not contribute to the merge.
* This makes it possible to join non-rectangular images.
*
* See also: im_lrmosaic(), im_lrmerge(), im_match_linear(), im_insert().
*
* Returns: 0 on success, -1 on error
*/
int
im_tbmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth )
{

View File

@ -1,17 +1,4 @@
/* @(#) Program to calculate the best possible tie points
* @(#) in the overlapping part between the primary and the secondary picture
* @(#)
* @(#) Right call:
* @(#) int im_tbmosaic( reference, secondary, out, bandno,
* @(#) xref, yref, xsec, ysec, halfcorrelation, halfarea, balancetype )
* @(#) IMAGE *reference, *secondary, *out;
* @(#) int bandno;
* @(#) int xref, yref, xsec, ysec;
* @(#) int halfcorrelation, halfarea;
* @(#) int balancetype;
* @(#)
* @(#) Returns 0 on success and -1 on error
* @(#)
/* join top-bottom with an approximate overlap
*
* Copyright: 1990, N. Dessipris.
*
@ -33,6 +20,11 @@
* - added tunable max blend width
* 24/2/05
* - im_scale() makes it work for any image type
* 25/1/11
* - gtk-doc
* - remove balance stuff
* - any mix of types and bands
* - cleanups
*/
/*
@ -86,23 +78,14 @@ im__find_tboverlap( IMAGE *ref_in, IMAGE *sec_in, IMAGE *out,
int *dx0, int *dy0,
double *scale1, double *angle1, double *dx1, double *dy1 )
{
Rect top, bottom, overlap;
IMAGE *ref, *sec;
IMAGE *t[6];
TIE_POINTS points, *p_points; /* defined in mosaic.h */
TIE_POINTS newpoints, *p_newpoints;
int i;
int dx, dy;
Rect top, bottom, overlap;
/* Check ref and sec are compatible.
*/
if( ref_in->Bands != sec_in->Bands ||
ref_in->BandFmt != sec_in->BandFmt ||
ref_in->Coding != sec_in->Coding ) {
im_error( "im_tbmosaic", "%s", _( "input images incompatible" ) );
return( -1 );
}
/* Test cor and area.
*/
if( halfcorrelation < 0 || halfarea < 0 ||
@ -125,68 +108,39 @@ im__find_tboverlap( IMAGE *ref_in, IMAGE *sec_in, IMAGE *out,
/* Find overlap.
*/
im_rect_intersectrect( &top, &bottom, &overlap );
if( overlap.width < 2*halfarea + 1 ||
overlap.height < 2*halfarea + 1 ) {
im_error( "im_tbmosaic", "%s", _( "overlap too small for search" ) );
if( overlap.width < 2 * halfarea + 1 ||
overlap.height < 2 * halfarea + 1 ) {
im_error( "im_tbmosaic", "%s",
_( "overlap too small for search" ) );
return( -1 );
}
/* Extract overlaps.
/* Extract overlaps as 8-bit, 1 band.
*/
ref = im_open_local( out, "temp_one", "t" );
sec = im_open_local( out, "temp_two", "t" );
if( !ref || !sec )
return( -1 );
if( ref_in->Coding == IM_CODING_LABQ ) {
IMAGE *t1 = im_open_local( out, "temp:3", "p" );
IMAGE *t2 = im_open_local( out, "temp:4", "p" );
IMAGE *t3 = im_open_local( out, "temp:5", "p" );
IMAGE *t4 = im_open_local( out, "temp:6", "p" );
IMAGE *t5 = im_open_local( out, "temp:7", "p" );
IMAGE *t6 = im_open_local( out, "temp:8", "p" );
if( !t1 || !t2 || !t3 || !t4 || !t5 || !t6 )
return( -1 );
if( im_extract_area( ref_in, t1,
if( !(ref = im_open_local( out, "temp_one", "t" )) ||
!(sec = im_open_local( out, "temp_two", "t" )) ||
im_open_local_array( out, t, 6, "im_tbmosaic", "p" ) ||
im_extract_area( ref_in, t[0],
overlap.left, overlap.top,
overlap.width, overlap.height ) )
return( -1 );
if( im_extract_area( sec_in, t2,
overlap.width, overlap.height ) ||
im_extract_area( sec_in, t[1],
overlap.left - bottom.left, overlap.top - bottom.top,
overlap.width, overlap.height ) )
return( -1 );
if( im_LabQ2Lab( t1, t3 ) || im_LabQ2Lab( t2, t4 ) ||
im_Lab2disp( t3, t5, im_col_displays( 1 ) ) ||
im_Lab2disp( t4, t6, im_col_displays( 1 ) ) )
return( -1 );
/* Extract the green.
*/
if( im_extract_band( t5, ref, 1 ) ||
im_extract_band( t6, sec, 1 ) )
return( -1 );
if( ref_in->Coding == IM_CODING_LABQ ) {
if( im_LabQ2Lab( t[0], t[2] ) ||
im_LabQ2Lab( t[1], t[3] ) ||
im_Lab2disp( t[2], t[4], im_col_displays( 1 ) ) ||
im_Lab2disp( t[3], t[5], im_col_displays( 1 ) ) ||
im_extract_band( t[4], ref, 1 ) ||
im_extract_band( t[5], sec, 1 ) )
return( -1 );
}
else if( ref_in->Coding == IM_CODING_NONE ) {
IMAGE *t1 = im_open_local( out, "temp:9", "p" );
IMAGE *t2 = im_open_local( out, "temp:10", "p" );
IMAGE *t3 = im_open_local( out, "temp:11", "p" );
IMAGE *t4 = im_open_local( out, "temp:12", "p" );
if( !t1 || !t2 || !t3 || !t4 )
return( -1 );
if( im_extract_area( ref_in, t1,
overlap.left, overlap.top,
overlap.width, overlap.height ) )
return( -1 );
if( im_extract_area( sec_in, t2,
overlap.left - bottom.left, overlap.top - bottom.top,
overlap.width, overlap.height ) )
return( -1 );
if( im_extract_band( t1, t3, bandno_in ) ||
im_extract_band( t2, t4, bandno_in ) )
return( -1 );
if( im_scale( t3, ref ) ||
im_scale( t4, sec ) )
if( im_extract_band( t[0], t[2], bandno_in ) ||
im_extract_band( t[1], t[3], bandno_in ) ||
im_scale( t[2], ref ) ||
im_scale( t[3], sec ) )
return( -1 );
}
else {
@ -263,17 +217,68 @@ im__find_tboverlap( IMAGE *ref_in, IMAGE *sec_in, IMAGE *out,
return( 0 );
}
/**
* im_tbmosaic:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @bandno: band to search for features
* @xref: position in reference image
* @yref: position in reference image
* @xsec: position in secondary image
* @ysec: position in secondary image
* @hwindowsize: half window size
* @hsearchsize: half search size
* @balancetype: no longer used
* @mwidth: maximum blend width
*
* This operation joins two images top-bottom (with @ref on the top)
* given an approximate overlap.
*
* @sec is positioned so that the pixel (@xsec, @ysec) lies on top of the
* pixel in @ref at (@xref, @yref). The overlap area is divided into three
* sections, 20 high-contrast points in band @bandno of image @ref are found
* in each, and each high-contrast point is searched for in @sec using
* @hwindowsize and @hsearchsize (see im_correl()).
*
* A linear model is fitted to the 60 tie-points, points a long way from the
* fit are discarded, and the model refitted until either too few points
* remain or the model reaches good agreement.
*
* The detected displacement is used with im_tbmerge() to join the two images
* together.
*
* @mwidth limits the maximum height of the
* blend area. A value of "-1" means "unlimited". The two images are blended
* with a raised cosine.
*
* Pixels with all bands equal to zero are "transparent", that
* is, zero pixels in the overlap area do not contribute to the merge.
* This makes it possible to join non-rectangular images.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* See also: im_tbmerge(), im_lrmosaic(), im_insert(), im_global_balance().
*
* Returns: 0 on success, -1 on error
*/
int
im_tbmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
int bandno,
int bandno,
int xref, int yref, int xsec, int ysec,
int halfcorrelation, int halfarea,
int hwindowsize, int hsearchsize,
int balancetype,
int mwidth )
{
int dx0, dy0;
double scale1, angle1, dx1, dy1;
IMAGE *ref2, *sec2;
IMAGE *dummy;
/* Correct overlap. dummy is just a placeholder used to ensure that
@ -284,7 +289,7 @@ im_tbmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
if( im__find_tboverlap( ref, sec, dummy,
bandno,
xref, yref, xsec, ysec,
halfcorrelation, halfarea,
hwindowsize, hsearchsize,
&dx0, &dy0,
&scale1, &angle1, &dx1, &dy1 ) ) {
im_close( dummy );
@ -292,16 +297,9 @@ im_tbmosaic( IMAGE *ref, IMAGE *sec, IMAGE *out,
}
im_close( dummy );
/* Balance.
*/
if( im__balance( ref, sec, out,
&ref2, &sec2,
dx0, dy0, balancetype ) )
return( -1 );
/* Merge top-bottom.
*/
if( im_tbmerge( ref2, sec2, out, dx0, dy0, mwidth ) )
if( im_tbmerge( ref, sec, out, dx0, dy0, mwidth ) )
return( -1 );
return( 0 );

View File

@ -93,6 +93,26 @@ im__coeff( int xr1, int yr1, int xs1, int ys1,
return( 0 );
}
/**
* im_match_linear:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @xr1: first reference tie-point
* @yr1: first reference tie-point
* @xs1: first secondary tie-point
* @ys1: first secondary tie-point
* @xr2: second reference tie-point
* @yr2: second reference tie-point
* @xs2: second secondary tie-point
* @ys2: second secondary tie-point
*
* Scale, rotate and translate @sec so that the tie-points line up.
*
* See also: im_match_linear_search().
*
* Returns: 0 on success, -1 on error
*/
int
im_match_linear( IMAGE *ref, IMAGE *sec, IMAGE *out,
int xr1, int yr1, int xs1, int ys1,
@ -123,6 +143,35 @@ im_match_linear( IMAGE *ref, IMAGE *sec, IMAGE *out,
return( 0 );
}
/**
* im_match_linear_search:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @xr1: first reference tie-point
* @yr1: first reference tie-point
* @xs1: first secondary tie-point
* @ys1: first secondary tie-point
* @xr2: second reference tie-point
* @yr2: second reference tie-point
* @xs2: second secondary tie-point
* @ys2: second secondary tie-point
* @hwindowsize: half window size
* @hsearchsize: half search size
*
* Scale, rotate and translate @sec so that the tie-points line up.
*
* Before performing the transformation, the tie-points are improved by
* searching an area of @sec of size @hsearchsize for a
* match of size @hwindowsize to @ref.
*
* This function will only work well for small rotates and scales.
*
* See also: im_match_linear().
*
* Returns: 0 on success, -1 on error
*/
int
im_match_linear_search( IMAGE *ref, IMAGE *sec, IMAGE *out,
int xr1, int yr1, int xs1, int ys1,
@ -133,19 +182,12 @@ im_match_linear_search( IMAGE *ref, IMAGE *sec, IMAGE *out,
int xs4, ys4;
double cor1, cor2;
/* Search for new tie-points.
*/
if( im_correl( ref, sec, xr1, yr1, xs1, ys1,
hwindowsize, hsearchsize, &cor1, &xs3, &ys3 ) )
return( -1 );
if( im_correl( ref, sec, xr2, yr2, xs2, ys2,
hwindowsize, hsearchsize, &cor2, &xs4, &ys4 ) )
return( -1 );
/* ... and match_linear.
*/
if( im_match_linear( ref, sec, out,
xr1, yr1, xs3, ys3, xr2, yr2, xs4, ys4 ) )
hwindowsize, hsearchsize, &cor1, &xs3, &ys3 ) ||
im_correl( ref, sec, xr2, yr2, xs2, ys2,
hwindowsize, hsearchsize, &cor2, &xs4, &ys4 ) ||
im_match_linear( ref, sec, out,
xr1, yr1, xs3, ys3, xr2, yr2, xs4, ys4 ) )
return( -1 );
return( 0 );

View File

@ -93,8 +93,8 @@ int im__make_blend_luts();
int im__attach_input( REGION *or, REGION *ir, Rect *area );
int im__copy_input( REGION *or, REGION *ir, Rect *area, Rect *reg );
Overlapping *im__build_mergestate( IMAGE *ref, IMAGE *sec, IMAGE *out,
int dx, int dy, int mwidth );
Overlapping *im__build_mergestate( const char *domain,
IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth );
void *im__start_merge( IMAGE *out, void *, void * );
int im__merge_gen( REGION *or, void *seq, void *a, void * );
int im__stop_merge( void *seq, void *, void * );

View File

@ -1,4 +1,5 @@
/* 1st order mosaic functions
*
* 31/7/97 JC
* - done!
* 12/9/97 JC
@ -12,6 +13,8 @@
* - better mosaic1 calcs ... was a bit broken
* 14/12/04
* - works for LABQ as well
* 25/1/11
* - gtk-doc
*/
/*
@ -206,7 +209,45 @@ rotjoin( IMAGE *ref, IMAGE *sec, IMAGE *out, joinfn jfn,
return( 0 );
}
/* 1st order left-right merge.
/**
* im_lrmerge1:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @xr1: first reference tie-point
* @yr1: first reference tie-point
* @xs1: first secondary tie-point
* @ys1: first secondary tie-point
* @xr2: second reference tie-point
* @yr2: second reference tie-point
* @xs2: second secondary tie-point
* @ys2: second secondary tie-point
* @mwidth: maximum blend width
*
* This operation joins two images left-right (with @ref on the left)
* given a pair of tie-points. @sec is scaled and rotated as
* necessary before the join.
*
* @mwidth limits the maximum width of the
* blend area. A value of "-1" means "unlimited". The two images are blended
* with a raised cosine.
*
* Pixels with all bands equal to zero are "transparent", that
* is, zero pixels in the overlap area do not contribute to the merge.
* This makes it possible to join non-rectangular images.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* See also: im_tbmerge1(), im_lrmerge(), im_insert(), im_global_balance().
*
* Returns: 0 on success, -1 on error
*/
int
im_lrmerge1( IMAGE *ref, IMAGE *sec, IMAGE *out,
@ -218,7 +259,45 @@ im_lrmerge1( IMAGE *ref, IMAGE *sec, IMAGE *out,
xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2, mwidth ) );
}
/* 1st order top-bottom merge.
/**
* im_tbmerge1:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @xr1: first reference tie-point
* @yr1: first reference tie-point
* @xs1: first secondary tie-point
* @ys1: first secondary tie-point
* @xr2: second reference tie-point
* @yr2: second reference tie-point
* @xs2: second secondary tie-point
* @ys2: second secondary tie-point
* @mwidth: maximum blend width
*
* This operation joins two images top-bottom (with @ref on the top)
* given a pair of tie-points. @sec is scaled and rotated as
* necessary before the join.
*
* @mwidth limits the maximum height of the
* blend area. A value of "-1" means "unlimited". The two images are blended
* with a raised cosine.
*
* Pixels with all bands equal to zero are "transparent", that
* is, zero pixels in the overlap area do not contribute to the merge.
* This makes it possible to join non-rectangular images.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* See also: im_lrmerge1(), im_tbmerge(), im_insert(), im_global_balance().
*
* Returns: 0 on success, -1 on error
*/
int
im_tbmerge1( IMAGE *ref, IMAGE *sec, IMAGE *out,
@ -333,39 +412,131 @@ rotjoin_search( IMAGE *ref, IMAGE *sec, IMAGE *out, joinfn jfn,
return( 0 );
}
/* 1st order lr mosaic.
/**
* im_lrmosaic1:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @bandno: band to search for features
* @xr1: first reference tie-point
* @yr1: first reference tie-point
* @xs1: first secondary tie-point
* @ys1: first secondary tie-point
* @xr2: second reference tie-point
* @yr2: second reference tie-point
* @xs2: second secondary tie-point
* @ys2: second secondary tie-point
* @hwindowsize: half window size
* @hsearchsize: half search size
* @balancetype: no longer used
* @mwidth: maximum blend width
*
* This operation joins two images left-right (with @ref on the left)
* given an approximate pair of tie-points. @sec is scaled and rotated as
* necessary before the join.
*
* Before performing the transformation, the tie-points are improved by
* searching band @bandno in an area of @sec of size @hsearchsize for a
* match of size @hwindowsize to @ref.
*
* @mwidth limits the maximum width of the
* blend area. A value of "-1" means "unlimited". The two images are blended
* with a raised cosine.
*
* Pixels with all bands equal to zero are "transparent", that
* is, zero pixels in the overlap area do not contribute to the merge.
* This makes it possible to join non-rectangular images.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* See also: im_tbmosaic1(), im_lrmerge(), im_insert(), im_global_balance().
*
* Returns: 0 on success, -1 on error
*/
int
im_lrmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
int bandno,
int xr1, int yr1, int xs1, int ys1,
int xr2, int yr2, int xs2, int ys2,
int halfcorrelation, int halfarea,
int hwindowsize, int hsearchsize,
int balancetype,
int mwidth )
{
return( rotjoin_search( ref, sec, out, im__lrmerge1,
bandno,
xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
halfcorrelation, halfarea, balancetype,
hwindowsize, hsearchsize, balancetype,
mwidth ) );
}
/* 1st order tb mosaic.
/**
* im_tbmosaic1:
* @ref: reference image
* @sec: secondary image
* @out: output image
* @bandno: band to search for features
* @xr1: first reference tie-point
* @yr1: first reference tie-point
* @xs1: first secondary tie-point
* @ys1: first secondary tie-point
* @xr2: second reference tie-point
* @yr2: second reference tie-point
* @xs2: second secondary tie-point
* @ys2: second secondary tie-point
* @hwindowsize: half window size
* @hsearchsize: half search size
* @balancetype: no longer used
* @mwidth: maximum blend width
*
* This operation joins two images top-bottom (with @ref on the top)
* given an approximate pair of tie-points. @sec is scaled and rotated as
* necessary before the join.
*
* Before performing the transformation, the tie-points are improved by
* searching band @bandno in an area of @sec of size @hsearchsize for a
* match of size @hwindowsize to @ref.
*
* @mwidth limits the maximum height of the
* blend area. A value of "-1" means "unlimited". The two images are blended
* with a raised cosine.
*
* Pixels with all bands equal to zero are "transparent", that
* is, zero pixels in the overlap area do not contribute to the merge.
* This makes it possible to join non-rectangular images.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* See also: im_lrmosaic1(), im_tbmerge(), im_insert(), im_global_balance().
*
* Returns: 0 on success, -1 on error
*/
int
im_tbmosaic1( IMAGE *ref, IMAGE *sec, IMAGE *out,
int bandno,
int xr1, int yr1, int xs1, int ys1,
int xr2, int yr2, int xs2, int ys2,
int halfcorrelation, int halfarea,
int hwindowsize, int hsearchsize,
int balancetype,
int mwidth )
{
return( rotjoin_search( ref, sec, out, im__tbmerge1,
bandno,
xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2,
halfcorrelation, halfarea, balancetype, mwidth ) );
hwindowsize, hsearchsize, balancetype, mwidth ) );
}
#ifdef OLD

View File

@ -52,7 +52,41 @@
* @stability: Stable
* @include: vips/vips.h
*
* A set of operations for assembling large image mosaics.
* These functions are useful for joining many small images together to make
* one large image. They can cope with unstable contrast and arbitary sub-image
* layout, but will not do any geometric correction. Geometric errors should
* be removed before using these functions.
*
* The mosaicing functions can be grouped into layers:
*
* The lowest level functions are im_correl(), im_lrmerge() and im_tbmerge().
* im_correl()
* searches a large image for a small sub-image, returning
* the position of the best sub-image match. im_lrmerge() and im_tbmerge()
* join two images together
* left-right or up-down with a smooth seam.
*
* Next, im_lrmosaic() and im_tbmosaic() use the
* search function plus the two low-level merge operations to join two images
* given just an approximate overlap as a start point.
*
* The functions im_lrmosaic1() and im_tbmosaic1() are
* first-order
* analogues of the basic mosaic functions: they take two approximate
* tie-points and use
* them to rotate and scale the right-hand or bottom image before starting to
* join.
*
* Finally, im_global_balance() can be used to remove contrast differences in
* a mosaic
* which has been assembled with these functions. It takes the mosaic apart,
* measures image contrast differences along the seams, finds a set of
* correction factors which will minimise these differences, and reassembles
* the mosaic.
* im_remosaic() uses the
* same
* techniques, but will reassemble the image from a different set of source
* images.
*
*/