gtkdoc for mosaicing
This commit is contained in:
parent
823650b2b4
commit
1aea6a1347
@ -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
3
TODO
@ -1,5 +1,8 @@
|
||||
|
||||
|
||||
- half-way thorough making fits read lazy
|
||||
|
||||
|
||||
|
||||
- im__open_write() should take a mode (text / binary)
|
||||
|
||||
|
@ -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"/>
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 )
|
||||
|
@ -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 ))
|
||||
|
@ -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,
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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 );
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
@ -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 * );
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user