24#ifndef VIGRA_EXT_CORRELATION_H
25#define VIGRA_EXT_CORRELATION_H
28#include <vigra/stdimage.hxx>
29#include <vigra/inspectimage.hxx>
30#include <vigra/copyimage.hxx>
31#include <vigra/resizeimage.hxx>
32#include <vigra/transformimage.hxx>
41#include "hugin_config.h"
43#include <vigra/fftw3.hxx>
44#include <vigra/functorexpression.hxx>
48#define VIGRA_EXT_USE_FAST_CORR
81 return v1 * vigra::conj(
v2);
92template <
class SrcImage,
class DestImage,
class KernelImage>
96 "correlateImageFastFFT(): coordinates of kernel's upper left must be <= 0.");
98 "correlateImageFastFFT(): coordinates of kernel's lower right must be >= 0.");
103 const int sw =
src.width();
104 const int sh =
src.height();
107 CorrelationResult res;
114 vigra::FindAverageAndVariance<typename KernelImage::PixelType>
kMean;
117 if (
kMean.variance(
false) == 0)
163 vigra::DImage
s(
sw,
sh);
165 double val =
src(0, 0);
167 s2(0, 0) = val * val;
169 for (
int x = 1; x <
sw; ++x)
172 s(x, 0) = val +
s(x - 1, 0);
173 s2(x, 0) = val * val +
s2(x - 1, 0);
176 for (
int y = 1; y <
sh; ++y)
179 s(0, y) = val +
s(0, y - 1);
180 s2(0, y) = val * val +
s2(0, y - 1);
183 for (
int y = 1; y <
sh; ++y)
185 for (
int x = 1; x <
sw; ++x)
188 s(x, y) = val +
s(x - 1, y) +
s(x, y - 1) -
s(x - 1, y - 1);
189 s2(x, y) = val * val +
s2(x - 1, y) +
s2(x, y - 1) -
s2(x - 1, y - 1);
214 if (
xr > 0 &&
yr > 0)
225 if (value > res.maxi)
228 res.maxpos.x =
xr -
kul.x;
229 res.maxpos.y =
yr -
kul.y;
231 dest(
xr -
kul.x,
yr -
kul.y) = vigra::NumericTraits<typename DestImage::value_type>::fromRealPromote(value);
252template <
class SrcImage,
class DestImage,
class KernelImage>
256 vigra::Diff2D
kul, vigra::Diff2D
klr,
260 "convolveImage(): coordinates of "
261 "kernel's upper left must be <= 0.");
263 "convolveImage(): coordinates of "
264 "kernel's lower right must be >= 0.");
268 vigra::NumericTraits<typename SrcImage::value_type>::RealPromote
SumType;
270 vigra::NumericTraits<typename KernelImage::value_type>::RealPromote
KSumType;
272 vigra::NumericTraits<typename DestImage::value_type>
DestTraits;
276 int h =
src.height();
284 "convolveImage(): kernel larger than image.");
293 for(
int y=0; y <
hk; y++) {
294 for(
int x=0; x <
wk; x++) {
348 DEBUG_DEBUG(
"Uniform patch(es) during correlation computation");
372template <
class Iterator,
class Accessor>
379 "subpixelMaxima(): coordinates of "
380 "maxima must be > interpWidth, interpWidth.");
381 vigra::Diff2D
sz = img.second - img.first;
383 "subpixelMaxima(): coordinates of "
384 "maxima must interpWidth pixels from the border.");
385 typedef typename Accessor::value_type T;
391#ifdef DEBUG_CORRELATION
392 exportImage(img,vigra::ImageExportInfo(
"test.tif"));
406 if (std::isnan(a) || std::isnan(b) || std::isnan(c)) {
407#ifdef DEBUG_CORRELATION
408 exportImage(img,vigra::ImageExportInfo(
"test.tif"));
430 if (std::isnan(a) || std::isnan(b) || std::isnan(c))
450 <<
" mean:" << res.
maxi <<
" coeff: a=" << a
451 <<
"; b=" << b <<
"; c=" << c);
456 DEBUG_NOTICE(
"subpixel Maxima has moved to much, ignoring");
503template <
class IMAGET,
class ACCESSORT,
class IMAGES,
class ACCESSORS>
558 vigra::copyImage(vigra::make_triple(
templImg.upperLeft() +
tmplUL,
562#ifdef DEBUG_WRITE_FILES
563 vigra::ImageExportInfo
tmpli(
"hugin_templ.tif");
566 vigra::ImageExportInfo
srci(
"hugin_searchregion.tif");
567 vigra::exportImage(vigra::srcImageRange(
srcImage),
srci);
579#elif defined VIGRA_EXT_USE_FAST_CORR
612 DEBUG_DEBUG(
"subpixel estimation not done, maxima too close to border");
630template <
class IMAGET,
class IMAGES>
683#ifdef DEBUG_WRITE_FILES
688 vigra::ImageExportInfo(
"00_original_template.png"));
693 vigra::ImageExportInfo(
"00_searcharea.png"));
710 vigra::RGBToGrayAccessor<typename IMAGES::value_type>() ),
746#elif defined VIGRA_EXT_USE_FAST_CORR
766#ifdef DEBUG_WRITE_FILES
773 vigra::transformImage(vigra::srcImageRange(
dest), vigra::destImage(
dest),
774 vigra::linearRangeMapping(
776 (
unsigned char)0, (
unsigned char)255)
813 DEBUG_ERROR(
"subpixel estimation not done, maxima to close to border");
823template <
class SrcImage,
class DestImage,
class KernelImage>
828 const int sw =
src.width();
829 const int sh =
src.height();
846 vigra::DImage
s(
sw,
sh);
848 double val =
src(0, 0);
850 s2(0, 0) = val * val;
852 for (
int x = 1; x <
sw; ++x)
855 s(x, 0) = val +
s(x - 1, 0);
856 s2(x, 0) = val * val +
s2(x - 1, 0);
859 for (
int y = 1; y <
sh; ++y)
862 s(0, y) = val +
s(0, y - 1);
863 s2(0, y) = val * val +
s2(0, y - 1);
866 for (
int y = 1; y <
sh; ++y)
868 for (
int x = 1; x <
sw; ++x)
871 s(x, y) = val +
s(x - 1, y) +
s(x, y - 1) -
s(x - 1, y - 1);
872 s2(x, y) = val * val +
s2(x - 1, y) +
s2(x, y - 1) -
s2(x - 1, y - 1);
881#pragma omp parallel for
885 vigra::FImage alpha(
kernel.size());
894 vigra::FindAverageAndVariance<vigra::FImage::PixelType>
kMean;
897 if (
kMean.variance(
false) == 0)
935 if (
xr > 0 &&
yr > 0)
975template <
class IMAGET,
class IMAGES>
1033 vigra::RGBToGrayAccessor<typename IMAGES::value_type>()),
1038 CorrelationResult res;
1054 <<
" at " << res.maxpos);
1059 DEBUG_DEBUG(
"subpixel estimation not done, maxima to close to border");
1062 res.maxpos = res.maxpos +
searchUL;
1083 vigra::Diff2D
kul, vigra::Diff2D
klr,
1088 "convolveImage(): coordinates of "
1089 "kernel's upper left must be <= 0.");
1091 "convolveImage(): coordinates of "
1092 "kernel's lower right must be >= 0.");
1096 vigra::NumericTraits<typename SrcAccessor::value_type>::RealPromote
SumType;
1098 vigra::NumericTraits<typename KernelAccessor::value_type>::RealPromote
KSumType;
1100 vigra::NumericTraits<typename DestAccessor::value_type>
DestTraits;
1112 "convolveImage(): kernel larger than image.");
1121 vigra::FindAverage<typename KernelAccessor::value_type>
average;
1122 vigra::inspectImage(
ki +
kul,
ki +
klr + vigra::Diff2D(1,1),
1160 vigra::FindAverage<typename SrcAccessor::value_type>
average;
Dummy progress display, without output.
misc math function & classes used by other parts of the program
#define DEBUG_NOTICE(msg)
T simpleClipPoint(const T &point, const T &min, const T &max)
clip a point to fit int [min, max] does not do a mathematical clipping, just sets p....
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama.
CorrelationResult correlateImage(SrcIterator sul, SrcIterator slr, SrcAccessor as, DestIterator dul, DestAccessor ad, KernelIterator ki, KernelAccessor ak, vigra::Diff2D kul, vigra::Diff2D klr, double threshold=0.7)
correlate a template with an image.
CorrelationResult PointFineTuneRotSearch(const IMAGET &templImg, vigra::Diff2D templPos, int templSize, const IMAGES &searchImg, vigra::Diff2D searchPos, int sWidth, double startAngle, double stopAngle, int angleSteps)
fine tune a point with normalized cross correlation, searches x,y and phi (rotation around z)
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
CorrelationResult correlateImageFast(SrcImage &src, DestImage &dest, KernelImage &kernel, vigra::Diff2D kul, vigra::Diff2D klr, double threshold=0.7)
correlate a template with an image.
CorrelationResult PointFineTune(const IMAGET &templImg, ACCESSORT access_t, vigra::Diff2D templPos, int templSize, const IMAGES &searchImg, ACCESSORS access_s, vigra::Diff2D searchPos, int sWidth)
fine tune a point with normalized cross correlation
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
void FitPolynom(T x, T xend, T y, double &a, double &b, double &c)
fit a second order polynom to a data set
CorrelationResult subpixelMaxima(vigra::triple< Iterator, Iterator, Accessor > img, vigra::Diff2D max)
find the subpixel maxima by fitting 2nd order polynoms to x and y.
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
vigra::Diff2D toDiff2D() const
Maximum of correlation, position and value.
hugin_utils::FDiff2D corrPos
hugin_utils::FDiff2D curv
hugin_utils::FDiff2D maxpos
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
functions to manage ROI's