snibgo's ImageMagick pages

Measuring detail

If we are searching for small crops from one image within another image, we want to ensure the crop has detail.

There is no point in searching for a patch of blue in an image of blue sky. The more detail a patch has, the more likely it is to be unique within the other image. (This may not be true for artificial images, but I reckon it's true of ordinary photographs.)

There are two approaches to this problem. One is to rank all of the pixels by some measure, such as the standard deviation of surrounding pixels, and then to find the highest-ranking pixel, the second highest, and so on. The algorithm ensures that chosen pixels are not too close together. That method is explored in Details, details. It is quite slow.

Another approach works in the opposite direction. It starts with a number of regularly-spaces pixels, and calculates are measure for each of these. For those patches with a poor measure (low entropy), we won't bother searching in the other image. This is much faster, as we calculate the measure for a much smaller number of pixels. However, many of the pixels will turn out to be unsuitable. That approach is described in this page.

Set up initial conditions:

set MD_SRC=\pictures\20140523\AGA_1837_g.tiff

set WEB_SIZE=-resize 500x500

A source image

The source photograph for this page has had fairly heavy processing from the raw camera image. This is a challenging image, as there are large areas of no detail (in the sky) and repeated areas of similar detail (the roof tiles, painted brickwork and blinds in the windows).

Put it another way: in this image, the chances of a small crop have high entropy is very low.

On this page, all operations are performed on the full-size image, roughly 7500x5000 pixels. Results are resized for display on the web.

The source image.

rem goto skip

%IM%convert ^
  %MD_SRC% ^
  %WEB_SIZE% ^
  md_src_sm.jpg
md_src_sm.jpg
for /F "usebackq" %%L in (`%IM%identify -format "WW=%%w\nHH=%%h" %MD_SRC%`) do set %%L
echo %WW% %HH% 
7378 4924 

Generate a list of coordinates.

call %PICTBAT%nGenCoord %WW% %HH% 6 4 >md_coords.lis

md_coords.lis contains:

1054,985
2108,985
3162,985
4216,985
5270,985
6324,985
1054,1970
2108,1970
3162,1970
4216,1970
5270,1970
6324,1970
1054,2954
2108,2954
3162,2954
4216,2954
5270,2954
6324,2954
1054,3939
2108,3939
3162,3939
4216,3939
5270,3939
6324,3939

Create 24 crops, each 100x100 pixels, centred on these coordinates:

set ncDEBUG=1
set ncDEBUG_STROKE=-stroke #f00 -fill None -strokewidth 15
set ncCROPDIR=.
set ncEXT=.png
call %PICTBAT%nCrop %MD_SRC% md_coords.lis 100 100

%IM%convert ^
  %ncDEBUG_FILE% ^
  %WEB_SIZE% ^
  mc_crops.jpg
mc_crops.jpg

Here are the 24 crops, shown full size. For convenience, we number these web images.

for /L %%i in (0,1,23) do (
  %IM%convert ^
    AGA_1837_g_100_100_crop_%%i.png ^
    -stroke None -fill Red -gravity SouthWest -pointsize 20 -annotate 0 "%%i" ^
    md_crop_%%i.png
)
md_crop_0.pngjpg md_crop_1.pngjpg md_crop_2.png md_crop_3.png md_crop_4.png md_crop_5.png
md_crop_6.png md_crop_7.png md_crop_8.png md_crop_9.png md_crop_10.png md_crop_11.png
md_crop_12.png md_crop_13.png md_crop_14.png md_crop_15.png md_crop_16.png md_crop_17.png
md_crop_18.png md_crop_19.png md_crop_20.png md_crop_21.png md_crop_22.png md_crop_23.png

Crops 4, 5, 12, 13 and 20 are featureless, so would have many false matches in another image.

Crops 15, 17 and 22 look useful.

As a better test of which crops are useful, we will search for them within another image that has undergone similar, but not identical, processing.

Seach for the crops within this image.

set SRCH_IMG=\pictures\20140523\AGA_1839_g.tiff

%IM%convert ^
  %SRCH_IMG% ^
  %WEB_SIZE% ^
  md_srch_sm.jpg
md_srch_sm.jpg

We search for the crops using the method given in Simple alignment.

set MATCH_LIS=md_match.lis
del %MATCH_LIS%
set MATCH_LIS2=md_match2.lis

echo CropNum,Score,X,Y >%MATCH_LIS%
set CROP_NUM=0
for /F %%F in (%ncLIST_FILE%) do (
  echo %%F

  call %PICTBAT%srchImg %SRCH_IMG% %%F
  if ERRORLEVEL 1 exit /B 1

  echo !CROP_NUM!, !siCOMP_FLT!, !siCENT_X!, !siCENT_Y! >>%MATCH_LIS%

  set /A CROP_NUM+=1
)

cSort /i%MATCH_LIS% /o%MATCH_LIS2% /h /kScore
CropNum,Score,X,Y 
0, 0.0668794, 4419, 2398 
1, 0.0127875, 3210, 1926 
2, 0.0380188, 4726, 2204 
3, 0.0593571, 3105, 420 
4, 0.0022269, 6710, 237 
5, 0.00497868, 6094, 999 
6, 0.0814029, 4376, 2736 
7, 0.047739, 2480, 2350 
8, 0.11398, 4367, 2374 
9, 0.056907, 6039, 4477 
10, 0.0517877, 4748, 3212 
11, 0.0842783, 6698, 2155 
12, 0.0084113, 1187, 4393 
13, 0.0217025, 1405, 3110 
14, 0.0646012, 4047, 2401 
15, 0.0726231, 4599, 3303 
16, 0.0772284, 3453, 2313 
17, 0.0843147, 4678, 2858 
18, 0.0485805, 2517, 4379 
19, 0.0422138, 2500, 4571 
20, 0.0148356, 3553, 4390 
21, 0.040483, 4447, 2597 
22, 0.0855242, 5040, 2405 
23, 0.0630489, 3449, 2334 

These are the matches found, in order of the score, so the closest matches are at the top.

CropNum,Score,X,Y 
4, 0.0022269, 6710, 237 
5, 0.00497868, 6094, 999 
12, 0.0084113, 1187, 4393 
1, 0.0127875, 3210, 1926 
20, 0.0148356, 3553, 4390 
13, 0.0217025, 1405, 3110 
2, 0.0380188, 4726, 2204 
21, 0.040483, 4447, 2597 
19, 0.0422138, 2500, 4571 
7, 0.047739, 2480, 2350 
18, 0.0485805, 2517, 4379 
10, 0.0517877, 4748, 3212 
9, 0.056907, 6039, 4477 
3, 0.0593571, 3105, 420 
23, 0.0630489, 3449, 2334 
14, 0.0646012, 4047, 2401 
0, 0.0668794, 4419, 2398 
15, 0.0726231, 4599, 3303 
16, 0.0772284, 3453, 2313 
6, 0.0814029, 4376, 2736 
11, 0.0842783, 6698, 2155 
17, 0.0843147, 4678, 2858 
22, 0.0855242, 5040, 2405 
8, 0.11398, 4367, 2374 

We can markup a copy of the searched image with the locations found.

:skip

set mrCOL_X=3
set mrCOL_Y=4
call %PICTBAT%markRect %SRCH_IMG% md_match.lis 100 100

%IM%convert ^
  %mrOUTFILE% ^
  %WEB_SIZE% ^
  md_srch_marked.jpg
md_srch_marked.jpg

The closest matches are for crops 4 and 5, but these are at the wrong position in the sky.

Correct matches have been found for only crop numbers 7, 15, and 20. Crop 15 is a correct match but the score is not good because the curtain has moved between photos. Crop 11 is close, but one glass pane too high. 19 is also very close. 20 is also very close, less than 100 pixels out. False matches have been found for rest.

Aside: checking for correct matches isn't possible with these reduced images. I checked the full-size versions by making the two images into layers for Gimp.

%PICTBAT%toGimp %ncDEBUG_FILE% %mrOUTFILE%

The techniques

Standard deviation

del md_sd.lis
for /L %%i in (0,1,23) do (
  %IM%convert AGA_1837_g_100_100_crop_%%i.png -format "%%i, %%[fx:standard_deviation]\n" info: >>md_sd.lis
)
cSort /imd_sd.lis /omd_sd.lis /k1 /r
15, 0.217446
22, 0.166763
11, 0.123797
17, 0.100795
7, 0.092101
16, 0.068679
14, 0.0641415
19, 0.0611273
18, 0.0604791
10, 0.0585896
9, 0.0583192
3, 0.0540542
20, 0.0520365
23, 0.0512842
6, 0.0495721
8, 0.047464
0, 0.0416223
2, 0.0368887
13, 0.036255
21, 0.0320853
1, 0.00956863
12, 0.00800066
5, 0.0070369
4, 0.00379715

The threshold could be somewhere between 0.06 and 0.10.

Difference from blur

del md_lbd.lis
for /L %%i in (0,1,23) do (
  %IM%convert ^
    AGA_1837_g_100_100_crop_%%i.png ^
    ^( +clone -blur 0x4 ^) ^
    -compose Difference -composite ^
    -grayscale RMS ^
    -format "%%i, %%[fx:mean]\n" info: >>md_lbd.lis
)
cSort /imd_lbd.lis /omd_lbd.lis /k1 /r
11, 0.0402368
18, 0.0341297
22, 0.0284433
17, 0.0270779
3, 0.0249619
14, 0.0242513
23, 0.0241707
0, 0.0232178
15, 0.0221118
8, 0.021639
6, 0.0214891
16, 0.0207127
19, 0.0186017
9, 0.0165609
21, 0.0164521
7, 0.0157946
2, 0.0156873
10, 0.0141526
13, 0.00665879
20, 0.0057895
1, 0.00486209
12, 0.00432354
4, 0.000983201
5, 0.000929366

The threshold could be somewhere between 0.010 and 0.022.

Difference between two blurs

del md_2bd.lis
for /L %%i in (0,1,23) do (
  %IM%convert ^
    AGA_1837_g_100_100_crop_%%i.png ^
    ^( -clone 0 -blur 0x4 ^) ^
    ^( -clone 0 -blur 0x6 ^) ^
    -delete 0 ^
    -compose Difference -composite ^
    -grayscale RMS ^
    -format "%%i, %%[fx:mean]\n" info: >>md_2bd.lis
)
cSort /imd_2bd.lis /omd_2bd.lis /k1 /r
11, 0.0131496
22, 0.0120719
17, 0.0108971
15, 0.0107203
18, 0.00831235
19, 0.00767631
14, 0.0073792
7, 0.00694394
16, 0.00651588
8, 0.00609133
9, 0.00608128
6, 0.00577632
23, 0.00565061
0, 0.00536901
3, 0.00445679
2, 0.00428925
10, 0.00427402
21, 0.00248127
13, 0.00186595
20, 0.0016006
12, 0.00107566
1, 0.000959411
5, 0.000167381
4, 0.000101817

The threshold could be somewhere between 0.010 and 0.022.

Difference of Gaussians

del md_dog.lis
for /L %%i in (0,1,23) do (
  %IM%convert ^
    AGA_1837_g_100_100_crop_%%i.png ^
    -morphology Convolve DoG:0,4.0,6.0 ^
    -grayscale RMS ^
    -format "%%i, %%[fx:mean]\n" info: >>md_dog.lis
)
cSort /imd_dog.lis /omd_dog.lis /k1 /r
22, 0.0210045
11, 0.019456
17, 0.0178273
15, 0.0174037
18, 0.0153237
14, 0.0133908
19, 0.0129771
7, 0.0124542
16, 0.0116234
9, 0.01044
8, 0.0104363
23, 0.0104016
6, 0.0102716
0, 0.00911032
10, 0.00751994
2, 0.00738392
3, 0.00699886
21, 0.00446465
13, 0.00308597
20, 0.00272584
12, 0.00180523
1, 0.00167776
5, 0.000307883
4, 0.000188003

The threshold could be somewhere between 0.004 and 0.016.

Summary and Conclusions

Scripts

For convenience, scripts are available in a single zip file. See Zipped BAT files.

StopWatch.bat

@set STOP_WATCH_SUB=
@if not "%STOP_WATCH_TIME%"=="" set STOP_WATCH_SUB=/S "%STOP_WATCH_TIME%"

@cDate %STOP_WATCH_SUB% /f"\q \H:\M:\S"

@for /F "usebackq tokens=*" %%L IN (`cDate /f"\d-\b-\Y \H:\M:\S"`) do @set STOP_WATCH_TIME=%%L
@rem echo %STOP_WATCH_TIME%

@if not "%1"=="" @echo %STOP_WATCH_TIME% %1 %2 %3 %4 %5 %6 %7 %8 %9>>stopwatch.lis

nGenCoord.bat

@rem Given:
@rem   %1 image width
@rem   %2 image height
@rem   %3 number of points horizontally >=1
@rem   %4 number of points vertically >=1
@rem   %5 optional deltaX
@rem   %6 optional deltaY
@rem echoes list of coordinates to stdout.

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

@setlocal enabledelayedexpansion

@call echoOffSave


set deltaX=%5
if "%deltaX%"=="" set deltaX=0

set deltaY=%6
if "%deltaY%"=="" set deltaY=0

for /L %%Y in (1,1,%4) do (
  for /L %%X in (1,1,%3) do (

    for /F "usebackq" %%L in (`%IM%identify ^
      -format "px=%%[fx:int(%%X*%1/(%3+1)+%deltaX%+0.5)]\npy=%%[fx:int(%%Y*%2/(%4+1)+%deltaY%+0.5)]" ^
      xc:`) do set %%L

    echo !px!,!py!
  )
)

@call echoRestore

nCrop.bat

rem From image %1,
rem   list of x,y coordinates in text file %2,
rem   creates crops width %3 height %4 in files *_crop_n.*
rem Also creates text file _crops.lis. Name is returned as ncLIST_FILE.
@rem
@rem Also uses:
@rem   ncDEBUG         if 1, creates a marked-up copy of image.
@rem   ncDEBUG_STROKE  eg to get thick strokes
@rem   ncCROPDIR       directory to place the crops, default %TEMP%
@rem   ncBASE          default name is based on %1, %3 and %4, in directory ncCROPDIR
@rem   ncEXT
@rem
@rem Returns:
@rem   ncLIST_FILE name of created file with list of names of crop files

@rem FIXME: we could also use (optional?) standard deviation of each crop.
@rem Or some other measure, such as difference from a blur.

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

@setlocal enabledelayedexpansion

@call echoOffSave

call %PICTBAT%setInOut %1 nl


if "%ncEXT%"=="" set ncEXT=%EXT%

if "%ncDEBUG%"=="1" set DEBUG_FILE=%BASENAME%_nc_dbg%ncEXT%

if "%ncDEBUG_STROKE%"=="" set ncDEBUG_STROKE=-stroke #f00 -fill None

if "%ncCROPDIR%"=="" set ncCROPDIR=%TEMP%

if "%ncBASE%"=="" set ncBASE=%ncCROPDIR%\%~n1_%3_%4_crop

if "%ncAtBASE%"=="" set ncAtBASE=%~n1_%3_%4_crop

set CROP_FILE=%ncAtBASE%_crops.txt
del %CROP_FILE% 2>nul

set RECT_FILE=%ncBASE%_rects.txt
del %RECT_FILE% 2>nul

set LIST_FILE=%ncBASE%s.lis
del %LIST_FILE% 2>nul

set nCrop=0
rem set sCROP=
set sRECT=

set /A W_2=%3/2
set /A H_2=%4/2

for /F "tokens=1,2 delims=, " %%X in (%2) do (
  set /A dx=%%X-%W_2%
  set /A dy=%%Y-%H_2%
  set IMG_FILE=%ncBASE%_!nCrop!%ncEXT%
  rem set sCrop=!sCrop! ^( +clone -crop %3x%4+!dx!+!dy! +repage -write !IMG_FILE! +delete ^)
  echo ^( +clone -crop %3x%4+!dx!+!dy! +repage -write !IMG_FILE! +delete ^) >> %CROP_FILE%
  echo !IMG_FILE!>>%LIST_FILE%
  set /A nCrop+=1

  if "%ncDEBUG%"=="1" (
    set /A endX=!dx!+%3-1
    set /A endY=!dy!+%4-1
    set sRECT=!sRECT! rectangle !dx!,!dy!,!endX!,!endY!
    echo rectangle !dx!,!dy!,!endX!,!endY! >>%RECT_FILE%
    rem FIXME: also annotate the rectangles
  )
)

%IM%convert ^
  %INFILE% ^
  @%CROP_FILE% ^
  NULL:
if ERRORLEVEL 1 exit /B 1

if "%ncDEBUG%"=="1" (
  %IM%convert ^
    %INFILE% ^
    %ncDEBUG_STROKE% ^
    -draw @%RECT_FILE% ^
    %DEBUG_FILE%

  if ERRORLEVEL 1 exit /B 1
)

@call echoRestore

@endlocal & set ncLIST_FILE=%LIST_FILE%& set ncDEBUG_FILE=%DEBUG_FILE%

markRect.bat

rem Given image %1, creates marked-up version with numbered rectangles.
rem Takes coordinates of rectangle centres from file %2.
rem %3 width of rectangle, default 1
rem %4 height of rectangle, default 1
@rem
@rem %2 is CSV file with columns X,Y{,N}
@rem If third column is present, uses this for annotation.
@rem Otherwise numbers seqentially.
@rem
@rem Also uses:
@rem   mrSTROKE  eg to get thick strokes
@rem   mrPIX_HT  height of font in pixels. If 0, no numbering.
@rem   mrCOL_X   column number in %2 for x-coordinate, counting from 1
@rem   mrCOL_Y   column number in %2 for y-coordinate, counting from 1

@rem FIXME: Also option for circles? Ellipes?

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

@setlocal enabledelayedexpansion

@call echoOffSave

call %PICTBAT%setInOut %1 mr


if "%mrSTROKE%"=="" set mrSTROKE=-stroke #f00 -fill None

if "%mrPIX_HT%"=="" set mrPIX_HT=20

if "%mrCOL_X%"=="" set mrCOL_X=1

if "%mrCOL_Y%"=="" set mrCOL_Y=2

set RW=%3
if "%RW%"=="" set RW=1

set RH=%4
if "%RW%"=="" set RH=1

set /A W_2=%RW%/2
set /A H_2=%RH%/2

set nCrop=0
set sRECT=
set sNUMB=

call %PICTBAT%getPointSize %INFILE% %H_2%
set mrTEXT=-pointsize %gpPointsize% -fill #f00 -stroke None

for /F "tokens=%mrCOL_X%,%mrCOL_Y% delims=, " %%X in (%2) do (
  if not "%%X" GTR "a" (
    set /A dx=%%X-%W_2%
    set /A dy=%%Y-%H_2%

    set /A endX=!dx!+%RW%-1
    set /A endY=!dy!+%RH%-1
    set sRECT=!sRECT! rectangle !dx!,!dy!,!endX!,!endY!
    set ANNOT=%%Z
    if "%ANNOT%"=="" set ANNOT=!nCrop!
    if not "%mrPIX_HT%"=="0" set sNUMB=!sNUMB! text %%X,%%Y '!ANNOT!'

    set /A nCrop+=1
  )
)

if "%mrPIX_HT%"=="0" (
  set sTEXT=
) else (
  set sTEXT=%mrTEXT% -draw "%sNUMB%"
)

%IM%convert ^
  %INFILE% ^
  %mrSTROKE% ^
  -draw "%sRECT%" ^
  %sTEXT% ^
  %OUTFILE%

@call echoRestore

@endlocal & set mrOUTFILE=%OUTFILE%

toGimp.bat

setlocal

set TEMP_TIFF=%TEMP%\tg.tiff
set TEMP_XCF=%TEMP%\tg.xcf

%IM%convert ^
  %* ^
  -set label %%f ^
  -type TrueColorAlpha ^
  -compress zip ^
  %TEMP_TIFF%

call %PICTBAT%GimpLoadSave %TEMP_TIFF% xcf

start %GIMP% %TEMP_XCF%

srchImg.bat

rem  Searches image %1 for image %2.
@rem  Writes results to optional batch file %3. Don't use this; it is for legacy purposes only.
@rem  If dimensions are large, resizes to find approx location,
@rem  and searches again within cropped limits.
@rem  Assumes width and height of %2 is smaller than of %1.
@rem
@rem  Also uses:
@rem    siMETRIC defaults to RMSE
@rem    siDEBUG if 1, creates a marked-up copy of image.
@rem    siDEBUG_STROKE eg to get thick strokes
@rem
@rem  Returns:
@rem    siCOMP_XW, siCOMP_YW coord of top-left of found area
@rem    siCOMP_FLT  RMSE difference beween %2 and found area
@rem    siCOMP_CROP=%subW%x%subH%+%COMP_XW%+%COMP_YW%  crop spec of found area

@rem Written: 31 Jan 2014
@rem Revised: 6 May 2014
@rem Revised: 31 May 2014 Don't resize src if already exists.

@rem FIXME: +repage, then add offsets (-format "%X %Y") at end.


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

@setlocal

@call echoOffSave

call %PICTBAT%setInOut %1 si

if "%siDEBUG%"=="1" (
  set DEBUG_OUT=%BASENAME%_si_dbg%EXT%
  if "%siDEBUG_STROKE%"=="" set siDEBUG_STROKE=-fill None -stroke #f00
)

set SRCNAME=%~n1
set SRC=%INFILE%
set SUB=%2
set fBAT=%3
if "%fBAT%"=="" set fBAT=NUL

if "%siMETRIC%"=="" set siMETRIC=RMSE

set TMPEXT=.miff
set TMPDIR=%TEMP%

set TMPSRC=%TMPDIR%\siSrc%TMPEXT%
set TMPSUB=%TMPDIR%\siSub%TMPEXT%


if not "%fBat%"=="NUL" del %fBat% 2>nul

FOR /F "usebackq" %%L ^
IN (`%IM%convert -ping %SUB% -format "subW=%%w\nsubH=%%h\nMinDim=%%[fx:w<h?w:h]" info:`) ^
DO set /A %%L

FOR /F "usebackq" %%L ^
IN (`%IM%identify -format "OFFSET_X=%%X\nOFFSET_Y=%%Y" %SRC%`) ^
DO set /A %%L

echo MinDim=%MinDim% Offset=(%OFFSET_X%,%OFFSET_Y%)

if %MinDim% GEQ 10000 (
  call :ResizeSrch 0.1 1000
  call :CropSrch !COMP_XW! !COMP_YW! 2000
) else if %MinDim% GEQ 5000 (
  call :ResizeSrch 0.2 500
  call :CropSrch !COMP_XW! !COMP_YW! 1000
) else if %MinDim% GEQ 2000 (
  call :ResizeSrch 0.5 200
  call :CropSrch !COMP_XW! !COMP_YW! 400
) else if %MinDim% GEQ 1000 (
  call :ResizeSrch 1 100
  call :CropSrch !COMP_XW! !COMP_YW! 200
) else if %MinDim% GEQ 500 (
  call :ResizeSrch 2 50
  call :CropResizeSrch !COMP_XW! !COMP_YW! 100 5 20
  call :CropResizeSrch !COMP_XW! !COMP_YW! 40 10 10
  call :CropResizeSrch !COMP_XW! !COMP_YW! 20 20 5
  call :CropResizeSrch !COMP_XW! !COMP_YW! 10 50 2
  call :CropSrch !COMP_XW! !COMP_YW! 4
) else if %MinDim% GEQ 200 (
  call :ResizeSrch 5 20
  call :CropResizeSrch !COMP_XW! !COMP_YW! 40 10 10
  call :CropResizeSrch !COMP_XW! !COMP_YW! 20 20 5
  call :CropResizeSrch !COMP_XW! !COMP_YW! 10 50 2
  call :CropSrch !COMP_XW! !COMP_YW! 4
) else if %MinDim% GEQ 100 (
  call :ResizeSrch 10 10
  call :CropSrch !COMP_XW! !COMP_YW! 20
) else if %MinDim% GEQ 50 (
  call :ResizeSrch 20 5
  call :CropSrch !COMP_XW! !COMP_YW! 10
) else if %MinDim% GEQ 20 (
  call :ResizeSrch 50 2
  call :CropSrch !COMP_XW! !COMP_YW! 2
) else if %MinDim% GEQ 10 (
  call :ResizeSrch 50 2
  call :CropSrch !COMP_XW! !COMP_YW! 2
) else (
  FOR /F "usebackq tokens=1-4 delims=()@, " %%R ^
IN (`%IM%compare ^
    -similarity-threshold 0 -dissimilarity-threshold 1 -subimage-search ^
    -metric %siMETRIC% %SRC% %SUB% NULL: 2^>^&1`) ^
DO (
    set COMP_INT=%%R
    set COMP_FLT=%%S
    set COMP_XW=%%T
    set COMP_YW=%%U
  )
)

rem set /A COMP_XW+=%OFFSET_X%
rem set /A COMP_YW+=%OFFSET_Y%

if "%siDEBUG%"=="1" (
  set /A endX=%COMP_XW%+%subW%-1
  set /A endY=%COMP_YW%+%subH%-1

  rem FIXME: does draw respect offsets? Add +repage to make this irrelevant.

  %IM%convert ^
    %SRC% ^
    +repage ^
    %siDEBUG_STROKE% ^
    -draw "rectangle %COMP_XW%,%COMP_YW% !endX!,!endY!" ^
    %DEBUG_OUT%
)

if not "%fBat%"=="NUL" echo set COMP_XW=%COMP_XW%^&set COMP_YW=%COMP_YW%^&set COMP_FLT=%COMP_FLT%^&set COMP_CROP=%subW%x%subH%+%COMP_XW%+%COMP_YW% >%fBat%

FOR /F "usebackq" %%L ^
IN (`%IM%convert -ping %SUB% -format "centX=%%[fx:%COMP_XW%+w/2]\ncentY=%%[fx:%COMP_YW%+h/2]" info:`) ^
DO set /A %%L

call echoRestore

endlocal & set siCOMP_XW=%COMP_XW%& set siCOMP_YW=%COMP_YW%& set siCOMP_FLT=%COMP_FLT%& set siCENT_X=%centX%& set siCENT_Y=%centY%& set siCOMP_CROP=%subW%x%subH%+%COMP_XW%+%COMP_YW%

exit /B 0

:error
echo Error in %0
exit /B 1


rem ------ Subroutines ----------------------------------------------------------

:ResizeSrch
rem %1 is percentage reduction, eg 50 for 50%. May be <1.
rem %2 is multiplier (=100/%1)

echo ResizeSrch %1 %2

rem The convert and compare could be combined into one convert.

set COMP_XW=0
set COMP_YW=0

set TMPSRC_RES=%TMPDIR%\%SRCNAME%_si_%1%TMPEXT%

@rem FIXME: +repage, then add offsets (-format "%X %Y") at end.
if not exist %TMPSRC_RES% %IM%convert %SRC% +repage -resize %1%% %TMPSRC_RES%

%IM%convert %SUB% -resize %1%% %TMPSUB%

set COMP_XW=

FOR /F "tokens=1-4 usebackq delims=()@, " %%R ^
IN (`%IM%compare ^
    -similarity-threshold 0 -dissimilarity-threshold 1 -subimage-search ^
    -metric %siMETRIC% %TMPSRC_RES% %TMPSUB% NULL: 2^>^&1`) ^
DO (
    rem echo %%R %%S %%T %%U
    set COMP_INT=%%R
    set COMP_FLT=%%S
    if not "%%T"=="" set /A COMP_XW=%%T*%2
    if not "%%U"=="" set /A COMP_YW=%%U*%2
  )

if "%COMP_XW%"=="" exit /B 1

echo   COMP_XW, YW = %COMP_XW% %COMP_YW%

exit /B 0


:CropSrch
rem %1,%2 are coords for top-left of estimated result.
rem %3 is plus or minus for tolerance in both directions.

echo CropSrch %1 %2 %3

set /A cropL=%1-%3
set /A cropT=%2-%3
if %cropL% LSS 0 set cropL=0
if %cropT% LSS 0 set cropT=0
set /A cropW=%subW%+%3+%3
set /A cropH=%subH%+%3+%3

set COMP_XW=%cropL%
set COMP_YW=%cropT%

%IM%convert ^
  %SRC% ^
  +repage ^
  -crop %cropW%x%cropH%+%cropL%+%cropT% ^
  +repage ^
  %TMPSRC%

FOR /F "tokens=1-4 usebackq delims=()@, " %%R ^
IN (`%IM%compare ^
    -similarity-threshold 0 -dissimilarity-threshold 1 -subimage-search ^
    -metric %siMETRIC% %TMPSRC% %SUB% NULL: 2^>^&1`) ^
DO (
    rem echo %%R %%S %%T %%U
    set COMP_INT=%%R
    set COMP_FLT=%%S
    if not "%%T"=="" set /A COMP_XW+=%%T
    if not "%%U"=="" set /A COMP_YW+=%%U
  )

echo   COMP_XW, YW = %COMP_XW% %COMP_YW%

exit /B 0


:CropResizeSrch
rem %1,%2 are coords for top-left of estimated result.
rem %3 is plus or minus for tolerance in both directions.
rem %4 is percentage reduction, eg 50 for 50%. May be <1.
rem %5 is multiplier (=100/%1)
rem %1 to %3 are in terms of original full size.

echo CropResizeSrch %1 %2 %3 %4 %5

set /A cropL=%1-%3
set /A cropT=%2-%3
if %cropL% LSS 0 set cropL=0
if %cropT% LSS 0 set cropT=0
set /A cropW=%subW%+%3+%3
set /A cropH=%subH%+%3+%3

set COMP_XW=%cropL%
set COMP_YW=%cropT%

%IM%convert ^
  %SRC% ^
    -crop %cropW%x%cropH%+%cropL%+%cropT% ^
    +repage ^
    -resize %4%% -write %TMPSRC% +delete ^
  %SUB% -resize %4%% %TMPSUB%

FOR /F "tokens=1-4 usebackq delims=()@, " %%R ^
IN (`%IM%compare ^
    -similarity-threshold 0 -dissimilarity-threshold 1 -subimage-search ^
    -metric %siMETRIC% %TMPSRC% %TMPSUB% NULL: 2^>^&1`) ^
DO (
    echo %%R %%S %%T %%U
    set COMP_INT=%%R
    set COMP_FLT=%%S
    if not "%%T"=="" set /A COMP_XW+=%%T*%5
    if not "%%U"=="" set /A COMP_YW+=%%U*%5
  )

echo   COMP_XW, YW = %COMP_XW% %COMP_YW%

exit /B 0

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

%IM%identify -version
Version: ImageMagick 6.8.9-0 Q16 x64 2014-04-06 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC OpenMP
Delegates: bzlib cairo freetype jbig jng jp2 jpeg lcms lqr pangocairo png ps rsvg tiff webp xml zlib

Source file for this web page is mtokens=1-4 usebackq delims=()@, " %%R ^ IN (`%IM%compare ^ -similarity-threshold 0 -dissimilarity-threshold 1 -subimage-search ^ -metric %siMETRIC% %TMPSRC% %TMPSUB% NULL: 2^>^&1`) ^ DO ( echo %%R %%S %%T %%U set COMP_INT=%%R set COMP_FLT=%%S if not "%%T"=="" set /A COMP_XW+=%%T*%5 if not "%%U"=="" set /A COMP_YW+=%%U*%5 ) rem echo COMP_XW, YW = %COMP_XW% %COMP_YW% exit /B 0


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

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


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 24-May-2014.

Page created 14-Oct-2015 05:11:19.

Copyright © 2015 Alan Gibson.