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:

• What scale, rotate and translate parameters give the best match?
• How closely do two images match, irrespective of scale, rotation and translation?

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, ... ... will be tested against images #2, #3 and #4.

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

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
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.