snibgo's ImageMagick pages

What SRT?

Given two images of the same size, where one image could be scaled, rotated and translated from another image, what are the best SRT parameters?

This script finds the best rotation, irrespective of scale. Given that rotation, it then finds the best scale. Given that rotation and scale, it finally finds the best translation.

The script also returns a score to show how well the images match.

This script uses scripts from What rotation? and What scale?, What rotation and scale? and What translation?.

This script can answer questions like:

This is a sub-problem of the more general problem: "What areas in image A match what areas in image B?"

This technique is suitable for small images (which might be crops from large images). For large images, a system using control points to find an affine transformation would be more suitable.

Sample inputs

We crop a photograph, make a base image, then three variations at different scales, rotations and translations.

set wtDEBUG=1

set ANG=100
set DEP=-depth 16

%IM%convert ^
  \pictures\20140430\GOPR0166.JPG ^
  -crop 900x700+2014+2090 +repage ^
  -gravity Center ^
  ( -clone 0 ^
    -crop 300x200+0+0 +repage ^
    %DEP% -write wsrt_src1.png ^
    +delete ) ^
  ( -clone 0 ^
    -crop 300x200+72+42 +repage ^
    %DEP% -write wsrt_src2.png ^
    +delete ) ^
  ( -clone 0 ^
    -distort SRT 1.2,100 +repage ^
    -crop 300x200+73+43 +repage ^
    %DEP% -write wsrt_src3.png ^
    +delete ) ^
  ( -clone 0 ^
    -distort SRT 0.7,-100 +repage ^
    -crop 300x200+74+44 +repage ^
    %DEP% -write wsrt_src4.png ^
    +delete ) ^
  NULL:

This first image, #1, ...

wsrt_src1.pngjpg

... will be tested against images #2, #3 and #4.

wsrt_src2.pngjpg wsrt_src3.pngjpg wsrt_src4.pngjpg

These are the same examples as used on What translation?. On this page, we derive all the SRT parameters.

The method

Aside: what RMSE score is reasonable?

I am generally concerned with visual differences. If the RMSE is less than 1% (ie the floating-point value is < 0.01), and the error is evenly distributed, I find it difficult to see, so I would consider the images to be equal.

If the RMSE is greater then 10% (ie the floating-point value is > 0.10), the difference is obvious, and the images are unequal.

So, where does the boundary lie? It depends on the purpose and the type of image. Perhaps 5% is a reasonable compromise.

Using the script

We use the script like this:

call %PICTBAT%whatSrt wsrt_src1.png wsrt_src2.png

echo wsrtANGLE=%wsrtANGLE% wsrtSCALE=%wsrtSCALE% wsrtDODGY=%wsrtDODGY% 
wsrtANGLE=42.9 wsrtSCALE=0.5 wsrtDODGY=1 

Scripts

whatSrt.bat

rem Given same-sized images %1 and %2,
rem returns scale, rotate and translate parameters to best match %1 to %2.

@rem Also uses:
@rem   wsrtMETRIC        default RMSE
@rem   wsrtTUNE_CROP     if 1, crop percentage will be adjusted for the given scale
@rem   wsrtDO_SUPER      if 0, no supersampling will be done.
@rem   wsrtDEBUG         if 1, creates images for debugging
@rem
@rem Returns:
@rem   wsrtANGLE     (degrees)
@rem   wsrtSCALE
@rem   wsrtFACT      error margin, multiple of wrsSCALE
@rem   wsrtX, wsrtY  pixel offsets. Positive values mean the first image needs moving
@rem                 down and right in order to register with the second image.
@rem   wsrtSCORE     0.0 to 1.0, more or less

@if "%2"=="" findstr /B "rem @rem" %~f0 & exit /B 1

@setlocal

rem @call echoOffSave

if "%wsrtMETRIC%"=="" set wsrtMETRIC=RMSE

call %PICTBAT%setInOut %1 wsrt
set IN_A=%INFILE%
set TEMP_A_BASE=%TEMP%\%~n1_wsrt
set TEMP_A=%TEMP%\%~n1_wsrt_%wrsMIN_SCALE%_%wrsMAX_SCALE%_%wrsnSTEPS%%EXT%

call %PICTBAT%setInOut %2 wsrt
set IN_B=%INFILE%
set TEMP_B=%TEMP%\%~n2_wsrt%EXT%

set DEBUG_FILE=wsrt_%~n1_%~n2_dbg%EXT%


call %PICTBAT%whatRotScale %IN_A% %IN_B%


call echoRestore

endlocal & set wsrtANGLE=%wrsANGLE%& set wsrtANGLE_ERR=%wrsANGLE_ERR%& set wsrtSCALE=%wrsSCALE%& set wsrtFACT=%wrsFACT%& set wsrtSCORE=%wrsCOMP_FLT%& set wsrtSCORE_SUB=%ScoreSub%& set wsrtDODGY=%wrsDODGY%

All images on this page were created by the commands shown, using:

%IM%identify -version
Versioset /A x1=x0
set /A y1=y0
set wsrtANGLE=0
set wsrtSCALE=1
set wsrtX=0
set wsrtY=0

set CHANGED=0
set nIter=0

:loop

rem ---------------
rem What rotation?

rem call %PICTBAT%whatRotScale %IN_A% %IN_B%

if %nIter%==0 (
  call %PICTBAT%whatRot %IN_A% %IN_B%
) else (
  call %PICTBAT%whatRot %IN_A_TMP% %IN_B_TMP%
)

if not "%wrANGLE%"=="0" set CHANGED=1

rem Add angle to what we had before.
for /F "usebackq" %%L in (`%IM%identify ^
  -format "wsrtANGLE=%%[fx:%wsrtANGLE%+%wrANGLE%]" ^
  xc:`) do set %%L

rem We crop off the virtual pixels.
for /F "usebackq" %%L in (`%IM%convert ^
  -ping %IN_A% ^
  -format "WW=%%w\nHH=%%h\nCropFact=%%[fx:1-abs(sin(%wrANGLE%*pi/180))]" ^
  info:`) do set %%L

for /F "usebackq" %%L in (`%IM%identify ^
  -format "CW=%%[fx:int(%WW%*%CropFact%)]\nCH=%%[fx:int(%HH%*%CropFact%)]" ^
  xc:`) do set %%L

%IM%convert ^
  %IN_A% ^
  -distort SRT %x0%,%y0%,%wsrtSCALE%,%wsrtANGLE%,%x1%,%y1% ^
  -crop %CW%x%CH%+0+0 +repage ^
  %IN_A_TMP%

%IM%convert ^
  %IN_B% ^
  -crop %CW%x%CH%+0+0 +repage ^
  %IN_B_TMP%

rem ---------------
rem What scale?

call %PICTBAT%whatScaleT %IN_A_TMP% %IN_B_TMP%
rem Multiply scale by previous value
for /F "usebackq" %%L in (`%IM%identify ^
  -format "wsrtSCALE=%%[fx:%wsrtSCALE%*%wstSCALE%]" ^
  xc:`) do set %%L

if not "%wstSCALE%"=="1" set CHANGED=1

%IM%convert ^
  %IN_A% ^
  -distort SRT %x0%,%y0%,%wsrtSCALE%,%wsrtANGLE%,%x1%,%y1% ^
  -crop %CW%x%CH%+0+0 +repage ^
  %IN_A_TMP%

rem ---------------
rem What translation?

call %PICTBAT%whatTrans %IN_A_TMP% %IN_B_TMP%
set /A wsrtX+=%wtX%
set /A wsrtY+=%wtY%

set /A x1=WW_2+(wsrtX)
set /A y1=HH_2+(wsrtY)

if not "%wtX%"=="0" set CHANGED=1
if not "%wtY%"=="0" set CHANGED=1


%IM%convert ^
  %IN_A% ^
  -distort SRT %x0%,%y0%,%wsrtSCALE%,%wsrtANGLE%,%x1%,%y1% ^
  -crop %CW%x%CH%+0+0 +repage ^
  %IN_A_TMP%

%IM%compare -metric RMSE %1 %2 NULL:

%IM%compare -metric RMSE %IN_A_TMP% %IN_B_TMP% NULL:
cmd /c exit /B 0

echo wsrtANGLE=%wsrtANGLE%  wsrtSCALE=%wsrtSCALE%  wsrtX=%wsrtX% wsrtY=%wsrtY%

set /A nIter+=1
if %CHANGED%==1 if %nIter% LSS 2 goto loop

echo nIter=%nIter%


call echoRestore

endlocal & set wsrtANGLE=%wsrtANGLE%& set wsrtSCALE=%wsrtSCALE%& set wsrtFACT=%wrsFACT%& set wsrtSCORE=%wrsCOMP_FLT%& set wsrtSCORE_SUB=%ScoreSub%& set wsrtX=%wsrtX%& set wsrtY=%wsrtY%& set wsrtDODGY=%wsrtDODGY%

All images on this page were created by the commands shown, using:

%IM%identify -version
Version: ImageMagick 6.9.1--6 Q16 x64 2015-06-20 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib cairo freetype jng jp2 jpeg lcms lqr openexr pangocairo png ps rsvg tiff webp xml zlib

To improve internet download speeds, some images may have been automatically converted (by ImageMagick, of course) from PNG to JPG.

Source file for this web page is whatsrt.h1. To re-create this web page, run "procH1 whatsrt".


This page, including the images, is my copyright. Anyone is permitted to use or adapt any of the code, scripts or images for any purpose, including commercial use.

Anyone is permitted to re-publish this page, but only for non-commercial use.

Anyone is permitted to link to this page, including for commercial use.


Page version v1.0 13-May-2014.

Page created 14-Oct-2015 04:40:12.

Copyright © 2015 Alan Gibson.