Linear Methods for Image Interpolation
|
Linear interpolation. More...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fftw3.h>
#include "basic.h"
#include "linterp.h"
#include "lkernels.h"
Go to the source code of this file.
Data Structures | |
struct | scalescanfilter |
Defines | |
#define | CLAMP(X, A, B) (((X) < (A)) ? (A) : (((X) > (B)) ? (B) : (X))) |
Clamp X to [A, B]. | |
Functions | |
int | LinInterp2d (float *Dest, const float *Src, int SrcWidth, int SrcHeight, float *X, float *Y, int NumSamples, float(*Kernel)(float), float KernelRadius, int KernelNormalize, boundaryhandling Boundary) |
2D linear interpolation (arbitrary resampling) | |
int | MakeScaleRotationGrid (float **X, float **Y, int *GridWidth, int *GridHeight, int SrcWidth, int SrcHeight, float Scale, float Theta) |
Make a sampling grid for scaling and rotating an image. | |
int | LinScale2d (float *Dest, int DestWidth, float XStart, float XStep, int DestHeight, float YStart, float YStep, const float *Src, int SrcWidth, int SrcHeight, int NumChannels, float(*Kernel)(float), float KernelRadius, int KernelNormalize, boundaryhandling Boundary) |
Scale image with a compact support interpolation kernel. | |
int | FourierScale2d (float *Dest, int DestWidth, float XStart, int DestHeight, float YStart, const float *Src, int SrcWidth, int SrcHeight, int NumChannels, double PsfSigma, boundaryhandling Boundary) |
Scale image with Fourier zero padding. | |
Variables | |
int(* | ExtensionMethod [3])(int, int) |
Boundary extension methods. |
Linear interpolation.
This file implements LinInterp2d
for interpolating at arbitrary sample locations with a compactly supported interpolation kernel, LinScale2d
for interpolating on a uniform grid of sample locations with a compactly supported interpolation kernel, and FourierScale2d
for interpolating on a uniform grid using Fourier interpolation.
Copyright (c) 2010-2011, Pascal Getreuer All rights reserved.
This program is free software: you can use, modify and/or redistribute it under the terms of the simplified BSD License. You should have received a copy of this license along this program. If not, see <http://www.opensource.org/licenses/bsd-license.html>.
Definition in file linterp.c.
#define CLAMP | ( | X, | |
A, | |||
B | |||
) | (((X) < (A)) ? (A) : (((X) > (B)) ? (B) : (X))) |
int FourierScale2d | ( | float * | Dest, |
int | DestWidth, | ||
float | XStart, | ||
int | DestHeight, | ||
float | YStart, | ||
const float * | Src, | ||
int | SrcWidth, | ||
int | SrcHeight, | ||
int | NumChannels, | ||
double | PsfSigma, | ||
boundaryhandling | Boundary | ||
) |
Scale image with Fourier zero padding.
Dest | pointer to memory for holding the interpolated image |
DestWidth | output image width |
XStart | leftmost sample location (in input coordinates) |
DestHeight | output image height |
YStart | uppermost sample location (in input coordinates) |
Src | the input image |
SrcWidth,SrcHeight,NumChannels | input image dimensions |
PsfSigma | Gaussian PSF standard deviation |
Boundary | boundary handling |
The image is first mirror folded with half-sample even symmetry to avoid boundary artifacts, then transformed with a real-to-complex DFT.
The interpolation is computed so that Dest[m + DestWidth*n] is the interpolation of Input at sampling location (XStart + m*SrcWidth/DestWidth, YStart + n*SrcHeight/DestHeight) for m = 0, ..., DestWidth - 1, n = 0, ..., DestHeight - 1, where the pixels of Src are located at the integers.
Definition at line 705 of file linterp.c.
int LinInterp2d | ( | float * | Dest, |
const float * | Src, | ||
int | SrcWidth, | ||
int | SrcHeight, | ||
float * | X, | ||
float * | Y, | ||
int | NumSamples, | ||
float(*)(float) | Kernel, | ||
float | KernelRadius, | ||
int | KernelNormalize, | ||
boundaryhandling | Boundary | ||
) |
2D linear interpolation (arbitrary resampling)
Dest | pointer to destination array |
Src | pointer to source array |
SrcWidth,SrcHeight | dimensions of the source data |
X,Y | the sampling locations |
NumSamples | the number of samples |
Kernel | the interpolation kernel to use |
KernelRadius | the radius of support of the kernel |
KernelNormalize | if nonzero, weights are normalized to sum to 1 |
Boundary | boundary handling |
This routine implements the computation Dest[k] = sum_m sum_n Src[m,n] Kernel(X[k] - m) Kernel(Y[k] - n), k = 0, ..., NumSamples-1. The source image Src is interpolated at points (X[0],Y[0]), (X[1],Y[1]), ... (X[NumSamples-1],Y[NumSamples-1]). Src should be in row-major order as Src[m + SrcWidth*n] = (m,n)th pixel value, m = 0, ..., SrcWidth-1, n = 0, ..., SrcHeight-1. Dest should have space for at least NumSamples elements. The pixels of Src are logically positioned at the integers with the upper-left corner (Src[0]) corresponding to (0,0). In other words, if X[k] = m and Y[k] = n, then Dest[k] = Src[m + SrcWidth*n]. If (X[k],Y[k]) is outside of [0,SrcWidth-1] x [0,SrcHeight-1], then Src is extrapolated with half-sample even symmetry.
Kernel should be a function with the calling syntax float Kernel(float x). Kernel should be zero (or approximately zero) for |x| >= KernelRadius.
If KernelNormalize is nonzero, the computation includes a normalizing denominator, Dest[k] = 1/Z[k] sum_m sum_n Src[m,n] Kernel(X[k] - m) Kernel(Y[k] - n), where Z[k] is Z[k] = sum_m sum_n Kernel(X[k] - m) Kernel(Y[k] - n). The normalization ensures that the interpolation exactly reproduces constant functions. Normalization is needed for example with the Lanczos kernels, which do not reproduce constants.
This normalization is equivalent to, but more efficient than, applying LinInterp2d
with the normalized kernel NormalizedKernel(x) = Kernel(x) / sum_n Kernel(x - n). On the other hand, if Kernel is already normalized, it is slightly more efficient to use KernelNormalize = 0.
Definition at line 146 of file linterp.c.
int LinScale2d | ( | float * | Dest, |
int | DestWidth, | ||
float | XStart, | ||
float | XStep, | ||
int | DestHeight, | ||
float | YStart, | ||
float | YStep, | ||
const float * | Src, | ||
int | SrcWidth, | ||
int | SrcHeight, | ||
int | NumChannels, | ||
float(*)(float) | Kernel, | ||
float | KernelRadius, | ||
int | KernelNormalize, | ||
boundaryhandling | Boundary | ||
) |
Scale image with a compact support interpolation kernel.
Dest | pointer to memory for holding the interpolated image |
DestWidth | width of the output image |
XStart | leftmost sampling location (in input coordinates) |
XStep | the length between successive samples (in input coordinates) |
DestHeight | height of the output image |
YStart | uppermost sampling location (in input coordinates) |
YStep | the length between successive samples (in input coordinates) |
Src | the input image |
SrcWidth,SrcHeight,NumChannels | input image dimensions |
Kernel | interpolation kernel function to use |
KernelRadius | kernel support radius |
KernelNormalize | if nonzero, filter rows are normalized to sum to 1 |
Boundary | boundary handling |
This is a generic linear interpolation routine to scale an image using any compactly supported interpolation kernel. The kernel is applied separably along both dimensions. Half-sample even symmetric extension is used to handle the boundaries.
The interpolation is computed so that Dest[m + DestWidth*n] is the interpolation of Src at sampling location (XStart + m*XStep, YStart + n*YStep) for m = 0, ..., DestWidth - 1, n = 0, ..., DestHeight - 1, where the pixels of Src are located at the integers.
The implementation follows the approach taken in ffmpeg's swscale library. First a "scanline filter" is constructed, a sparse matrix such that multiplying with a row of the input image produces an interpolated row in the output image. Similarly a second matrix is constructed for interpolating columns. The interpolation itself is then essentially two sparse matrix times dense matrix multiplies.
Definition at line 463 of file linterp.c.
int MakeScaleRotationGrid | ( | float ** | X, |
float ** | Y, | ||
int * | GridWidth, | ||
int * | GridHeight, | ||
int | SrcWidth, | ||
int | SrcHeight, | ||
float | Scale, | ||
float | Theta | ||
) |
Make a sampling grid for scaling and rotating an image.
X,Y | array of sample locations |
GridWidth,GridHeight | the dimensions of the sampling grid |
SrcWidth,SrcHeight | the size of the source image |
Scale | the scale factor (> 1 for finer resolution) |
Theta | rotation angle (counter clockwise) |
This routine creates sampling locations (X[0],Y[0]), (X[1],Y[1]), ... (X[N-1],Y[N-1]), where the number of samples is N = GridWidth*GridHeight, such that interpolating the source image at these locations produces an scaled and rotated version of the image of size GridWidth by GridHeight.
The memory for X and Y is allocated by this routine. It is the responsibility of the caller to call Free(X), Free(Y) to release this memory when done.
Definition at line 252 of file linterp.c.
int(* ExtensionMethod[3])(int, int) |