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,13 +54,13 @@ 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 bandno,
int xref, int yref, int xsec, int ysec,
int halfcorrelation, int halfarea,
int hwindowsize, int hsearchsize,
int balancetype,
int mwidth );
@ -68,14 +68,14 @@ 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 );
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.
*
* Also used by im_match_linear(), im_match_linear_search(), etc.
* 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().
*
* 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;
@ -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 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.
*
*/