Commit b7794a3e8 for imagemagick.org
commit b7794a3e8f7a3aba72600c73e2ae060ce7830bc4
Author: Cristy <urban-warrior@imagemagick.org>
Date: Sun Aug 9 08:59:35 2026 -0400
phase similarity now matches Fred's phase script
diff --git a/MagickCore/compare.c b/MagickCore/compare.c
index 87f416fda..ddb9a7720 100644
--- a/MagickCore/compare.c
+++ b/MagickCore/compare.c
@@ -3464,68 +3464,78 @@ static MagickBooleanType SIMMultiplyImage(Image *image,const double factor,
return(status);
}
-static Image *SIMPhaseCorrelationImage(const Image *alpha_image,
- const Image *beta_image,const Image *magnitude_image,ExceptionInfo *exception)
+static Image *SIMPhaseCorrelationImage(const Image *target_image,
+ const Image *reconstruct_image,const Image *magnitude_image,
+ ExceptionInfo *exception)
{
Image
- *alpha_fft = (Image *) NULL,
- *beta_fft = (Image *) NULL,
+ *target_fft = (Image *) NULL,
+ *reconstruct_fft = (Image *) NULL,
*complex_multiplication = (Image *) NULL,
*cross_correlation = (Image *) NULL;
/*
- Take the FFT of the beta (reconstruction) image.
+ Take the FFT of the reconstruction image.
*/
- beta_fft=CloneImage(beta_image,0,0,MagickTrue,exception);
- if (beta_fft == NULL)
+ reconstruct_fft=CloneImage(reconstruct_image,0,0,MagickTrue,exception);
+ if (reconstruct_fft == NULL)
return((Image *) NULL);
- (void) SetImageArtifact(beta_fft,"fourier:normalize","inverse");
- beta_fft=ForwardFourierTransformImage(beta_fft,MagickFalse,exception);
- if (beta_fft == NULL)
+ (void) SetImageArtifact(reconstruct_fft,"fourier:normalize","inverse");
+ reconstruct_fft=ForwardFourierTransformImage(reconstruct_fft,MagickFalse,
+ exception);
+ if (reconstruct_fft == NULL)
return((Image *) NULL);
/*
- Take the FFT of the alpha (test) image.
+ Take the FFT of the target image.
*/
- alpha_fft=CloneImage(alpha_image,0,0,MagickTrue,exception);
- if (alpha_fft == (Image *) NULL)
+ target_fft=CloneImage(target_image,0,0,MagickTrue,exception);
+ if (target_fft == (Image *) NULL)
{
- beta_fft=DestroyImageList(beta_fft);
+ reconstruct_fft=DestroyImageList(reconstruct_fft);
return((Image *) NULL);
}
- (void) SetImageArtifact(alpha_fft,"fourier:normalize","inverse");
- alpha_fft=ForwardFourierTransformImage(alpha_fft,MagickFalse,exception);
- if (alpha_fft == (Image *) NULL)
+ (void) SetImageArtifact(target_fft,"fourier:normalize","inverse");
+ target_fft=ForwardFourierTransformImage(target_fft,MagickFalse,exception);
+ if (target_fft == (Image *) NULL)
{
- beta_fft=DestroyImageList(beta_fft);
+ reconstruct_fft=DestroyImageList(reconstruct_fft);
return((Image *) NULL);
}
/*
- Take the complex conjugate of the beta FFT.
+ Take the complex conjugate of the reconstruction FFT.
*/
- beta_fft=ComplexImages(beta_fft,ConjugateComplexOperator,exception);
- if (beta_fft == (Image *) NULL)
+ reconstruct_fft=ComplexImages(reconstruct_fft,ConjugateComplexOperator,
+ exception);
+ if (reconstruct_fft == (Image *) NULL)
{
- alpha_fft=DestroyImageList(alpha_fft);
+ target_fft=DestroyImageList(target_fft);
return((Image *) NULL);
}
/*
Do complex multiplication.
*/
- AppendImageToList(&beta_fft,alpha_fft);
- DisableCompositeClampUnlessSpecified(beta_fft);
- DisableCompositeClampUnlessSpecified(beta_fft->next);
- complex_multiplication=ComplexImages(beta_fft,MultiplyComplexOperator,
+ AppendImageToList(&reconstruct_fft,target_fft);
+ DisableCompositeClampUnlessSpecified(reconstruct_fft);
+ DisableCompositeClampUnlessSpecified(reconstruct_fft->next);
+ complex_multiplication=ComplexImages(reconstruct_fft,MultiplyComplexOperator,
exception);
- beta_fft=DestroyImageList(beta_fft);
+ reconstruct_fft=DestroyImageList(reconstruct_fft);
if (complex_multiplication == (Image *) NULL)
return((Image *) NULL);
+ if (complex_multiplication->next != (Image *) NULL)
+ {
+ /*
+ Normalize the cross-power spectrum by the product magnitude.
+ */
+ DisableCompositeClampUnlessSpecified(complex_multiplication);
+ DisableCompositeClampUnlessSpecified(complex_multiplication->next);
+ (void) CompositeImage(complex_multiplication,magnitude_image,
+ DivideSrcCompositeOp,MagickTrue,0,0,exception);
+ (void) CompositeImage(complex_multiplication->next,magnitude_image,
+ DivideSrcCompositeOp,MagickTrue,0,0,exception);
+ }
/*
- Divide the results.
- */
- CompositeLayers((Image *) magnitude_image,DivideDstCompositeOp,
- complex_multiplication,0,0,exception);
- /*
- Do the IFT and return the cross-correlation result.
+ Do the IFT and return the phase-correlation result.
*/
(void) SetImageArtifact(complex_multiplication,"fourier:normalize","inverse");
cross_correlation=InverseFourierTransformImage(complex_multiplication,
@@ -4351,24 +4361,24 @@ static Image *PhaseSimilarityImage(const Image *image,const Image *reconstruct,
{
#define ThrowPhaseSimilarityException() \
{ \
- if (correlation_image != (Image *) NULL) \
- correlation_image=DestroyImage(correlation_image); \
- if (fft_images != (Image *) NULL) \
- fft_images=DestroyImageList(fft_images); \
+ if (phase_image != (Image *) NULL) \
+ phase_image=DestroyImage(phase_image); \
if (gamma_image != (Image *) NULL) \
gamma_image=DestroyImage(gamma_image); \
+ if (test_magnitude != (Image *) NULL) \
+ test_magnitude=DestroyImage(test_magnitude); \
if (magnitude_image != (Image *) NULL) \
magnitude_image=DestroyImage(magnitude_image); \
- if (phase_image != (Image *) NULL) \
- phase_image=DestroyImage(phase_image); \
- if (reconstruct_image != (Image *) NULL) \
- reconstruct_image=DestroyImage(reconstruct_image); \
if (reconstruct_magnitude != (Image *) NULL) \
reconstruct_magnitude=DestroyImage(reconstruct_magnitude); \
+ if (correlation_image != (Image *) NULL) \
+ correlation_image=DestroyImage(correlation_image); \
+ if (fft_images != (Image *) NULL) \
+ fft_images=DestroyImageList(fft_images); \
+ if (reconstruct_image != (Image *) NULL) \
+ reconstruct_image=DestroyImage(reconstruct_image); \
if (target_image != (Image *) NULL) \
target_image=DestroyImage(target_image); \
- if (test_magnitude != (Image *) NULL) \
- test_magnitude=DestroyImage(test_magnitude); \
return((Image *) NULL); \
}
@@ -4401,12 +4411,13 @@ static Image *PhaseSimilarityImage(const Image *image,const Image *reconstruct,
(void) ResetImagePage(target_image,"0x0+0+0");
GetPixelInfoRGBA((Quantum) 0,(Quantum) 0,(Quantum) 0,(Quantum) 0,
&target_image->background_color);
- status=SetImageExtent(target_image,2*(size_t) ceil((double) image->columns/
- 2.0),2*(size_t) ceil((double) image->rows/2.0),exception);
+ status=SetImageExtent(target_image,2*CastDoubleToSizeT(ceil((double)
+ image->columns/2.0)),2*CastDoubleToSizeT(ceil((double) image->rows/2.0)),
+ exception);
if (status == MagickFalse)
ThrowPhaseSimilarityException();
/*
- Compute the cross correlation of the test and reconstruct magnitudes.
+ Compute the cross correlation of the target and reconstruct magnitudes.
*/
reconstruct_image=CloneImage(reconstruct,0,0,MagickTrue,exception);
if (reconstruct_image == (Image *) NULL)
@@ -4414,8 +4425,9 @@ static Image *PhaseSimilarityImage(const Image *image,const Image *reconstruct,
(void) ResetImagePage(reconstruct_image,"0x0+0+0");
GetPixelInfoRGBA((Quantum) 0,(Quantum) 0,(Quantum) 0,(Quantum) 0,
&reconstruct_image->background_color);
- status=SetImageExtent(reconstruct_image,2*(size_t) ceil((double)
- image->columns/2.0),2*(size_t) ceil((double) image->rows/2.0),exception);
+ status=SetImageExtent(reconstruct_image,2*CastDoubleToSizeT(ceil((double)
+ image->columns/2.0)),2*CastDoubleToSizeT(ceil((double) image->rows/2.0)),
+ exception);
if (status == MagickFalse)
ThrowPhaseSimilarityException();
/*
@@ -4445,7 +4457,7 @@ static Image *PhaseSimilarityImage(const Image *image,const Image *reconstruct,
(void) CompositeImage(magnitude_image,test_magnitude,MultiplyCompositeOp,
MagickTrue,0,0,exception);
/*
- Compute the cross correlation of the test and reconstruction images.
+ Compute the cross correlation of the target and reconstruction images.
*/
correlation_image=SIMPhaseCorrelationImage(target_image,reconstruct_image,
magnitude_image,exception);
@@ -4455,13 +4467,6 @@ static Image *PhaseSimilarityImage(const Image *image,const Image *reconstruct,
reconstruct_magnitude=DestroyImage(reconstruct_magnitude);
if (correlation_image == (Image *) NULL)
ThrowPhaseSimilarityException();
- /*
- Identify the maxima value in the image and its location.
- */
- status=SIMMultiplyImage(correlation_image,(double) QuantumScale,
- (const ChannelStatistics *) NULL,exception);
- if (status == MagickFalse)
- ThrowPhaseSimilarityException();
gamma_image=CloneImage(correlation_image,0,0,MagickTrue,exception);
correlation_image=DestroyImage(correlation_image);
if (gamma_image == (Image *) NULL)