libvips/libvips/mosaicing/chkpair.c

234 lines
5.8 KiB
C

/* find image overlaps
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 02/05/1990
* Modified on : 18/04/1991
* 8/7/93 JC
* - allows IM_CODING_LABQ coding
* - now calls im_incheck()
* 13/7/95 JC
* - rewritten
* - now uses im_spcor()
* 13/8/96 JC
* - order of args changed to help C++ API
* 24/1/11
* - gtk-doc
* 18/6/20 kleisauke
* - convert to vips8
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <glib/gi18n-lib.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <vips/vips.h>
#include "pmosaicing.h"
/* vips__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
*
* 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 vips_spcor(); the position of
* the maximum is found with vips_max().
*
* See also: vips_match(), vips__lrmosaic().
*
* Returns: 0 on success, -1 on error
*/
int
vips__correl( VipsImage *ref, VipsImage *sec,
int xref, int yref, int xsec, int ysec,
int hwindowsize, int hsearchsize,
double *correlation, int *x, int *y )
{
VipsImage *surface = vips_image_new();
VipsImage **t = (VipsImage **)
vips_object_local_array( VIPS_OBJECT( surface ), 5 );
VipsRect refr, secr;
VipsRect winr, srhr;
VipsRect wincr, srhcr;
/* Find position of window and search area, and clip against image
* size.
*/
refr.left = 0;
refr.top = 0;
refr.width = ref->Xsize;
refr.height = ref->Ysize;
winr.left = xref - hwindowsize;
winr.top = yref - hwindowsize;
winr.width = hwindowsize * 2 + 1;
winr.height = hwindowsize * 2 + 1;
vips_rect_intersectrect( &refr, &winr, &wincr );
secr.left = 0;
secr.top = 0;
secr.width = sec->Xsize;
secr.height = sec->Ysize;
srhr.left = xsec - hsearchsize;
srhr.top = ysec - hsearchsize;
srhr.width = hsearchsize * 2 + 1;
srhr.height = hsearchsize * 2 + 1;
vips_rect_intersectrect( &secr, &srhr, &srhcr );
/* Extract window and search area.
*/
if( vips_extract_area( ref, &t[0],
wincr.left, wincr.top, wincr.width, wincr.height,
NULL ) ||
vips_extract_area( sec, &t[1],
srhcr.left, srhcr.top, srhcr.width, srhcr.height,
NULL ) ) {
g_object_unref( surface );
return( -1 );
}
ref = t[0];
sec = t[1];
/* Make sure we have just one band. From vips_*mosaic() we will, but
* from vips_match() etc. we may not.
*/
if( ref->Bands != 1 ) {
if( vips_extract_band( ref, &t[2], 0, NULL ) ) {
g_object_unref( surface );
return( -1 );
}
ref = t[2];
}
if( sec->Bands != 1 ) {
if( vips_extract_band( sec, &t[3], 0, NULL ) ) {
g_object_unref( surface );
return( -1 );
}
sec = t[3];
}
/* Search!
*/
if( vips_spcor( sec, ref, &t[4], NULL ) ) {
g_object_unref( surface );
return( -1 );
}
/* Find maximum of correlation surface.
*/
if( vips_max( t[4], correlation, "x", x, "y", y, NULL ) ) {
g_object_unref( surface );
return( -1 );
}
g_object_unref( surface );
/* Translate back to position within sec.
*/
*x += srhcr.left;
*y += srhcr.top;
return( 0 );
}
int
vips__chkpair( VipsImage *ref, VipsImage *sec, TiePoints *points )
{
int i;
int x, y;
double correlation;
const int hcor = points->halfcorsize;
const int harea = points->halfareasize;
/* Check images.
*/
if( vips_image_wio_input( ref ) || vips_image_wio_input( sec ) )
return( -1 );
if( ref->Bands != sec->Bands || ref->BandFmt != sec->BandFmt ||
ref->Coding != sec->Coding ) {
vips_error( "vips_chkpair", "%s", _( "inputs incompatible" ) );
return( -1 );
}
if( ref->Bands != 1 || ref->BandFmt != VIPS_FORMAT_UCHAR ) {
vips_error( "vips_chkpair", "%s", _( "help!" ) );
return( -1 );
}
for( i = 0; i < points->nopoints; i++ ) {
/* Find correlation point.
*/
if( vips__correl( ref, sec,
points->x_reference[i], points->y_reference[i],
points->x_reference[i], points->y_reference[i],
hcor, harea,
&correlation, &x, &y ) )
return( -1 );
/* And note in x_secondary.
*/
points->x_secondary[i] = x;
points->y_secondary[i] = y;
points->correlation[i] = correlation;
/* Note each dx, dy too.
*/
points->dx[i] =
points->x_secondary[i] - points->x_reference[i];
points->dy[i] =
points->y_secondary[i] - points->y_reference[i];
}
return( 0 );
}