snibgo's ImageMagick pages

Correlating shapes

blah.

See Polar Distortions for a discussion of unrolling images around a defined central point (and rolling them back up).

See Nearest coastal point for the nearCoast.bat script.

Scripts on this page assume that the version of ImageMagick in %IMDEV% has been built with various process modules. See Process modules.

The method

We want to correlate one shape with another. We can do this by finding points on the edge of one shape, then for each point finding the closest point on the other.

If the shapes are not similar, this can create a problem that a correlation in one direction is not a correlation in the other direction. That is, if point pA on shape A is the closest point to pB on shape B, it may not be true that pB on shape B is the closest point to pA on shape A.

Sample images

set SRC_DIR=\pictures\20150805\

set RESIZE=-resize 400x400

set SRC1=%SRC_DIR%AGA_2499_rnd2.tiff
set SRC2=%SRC_DIR%AGA_2505_tri2.tiff

set MSK1=%SRC_DIR%AGA_2499_mc.png
set MSK2=%SRC_DIR%AGA_2505_mc.png

goto skip
%IM%convert ^
  %SRC1% ^
  %RESIZE% ^
  cs_src1.png
cs_src1.png
%IM%convert ^
  %SRC2% ^
  %RESIZE% ^
  cs_src2.png
cs_src2.png
%IM%convert ^
  %MSK1% ^
  %RESIZE% ^
  cs_msk1.png
cs_msk1.png
%IM%convert ^
  %MSK2% ^
  %RESIZE% ^
  cs_msk2.png
cs_msk2.png

Create an outline of the union of the two masks:

%IM%convert ^
  cs_msk1.png ^
  cs_msk2.png ^
  -compose Lighten -composite ^
  -edge 1 ^
  cs_sup_msk.png

Ideally, this edge should be slightly outside the union. Blah.

cs_sup_msk.png
set nlDEBUG=1

call %PICTBAT%nLightest ^
  cs_sup_msk.png 999 >cs_sup_msk.lis
cs_sup_msk_nl_dbg.png

cs_sup_msk.lis contains a list of coordinates found in the outline:

159,10
200,13
119,20
239,26
84,43
274,48
59,76
304,76
329,109
43,114
344,148
36,155
356,188
39,196
363,229
49,236
361,270
37,276
379,307
17,312
1,350
398,352
361,372
131,373
295,373
35,374
76,374
172,376
254,387
212,388

Find the nearest points in each mask. This gives us two pairs of coordinates (x, y, x', y') for each point: a position on the round mask, and a position on the triangular mask. We write this data to a number of text files:

set ncSEA_COL=auto

del cs_correl_1_2.lis
del cs_correl_2_1.lis
del cs_lines.txt

set /A NFp1=%nl_nFound%+1

echo %NFp1% 2 >cs_tri1.lis
echo %NFp1% 2 >cs_tri2.lis

for /F "tokens=1-2 delims=, " %%X in (cs_sup_msk.lis) do (
  call %PICTBAT%nearCoast cs_msk1.png %%X %%Y

  set mx=!ncCST_X!
  set my=!ncCST_Y!

  call %PICTBAT%nearCoast cs_msk2.png %%X %%Y

  echo line !mx!,!my!,!ncCST_X!,!ncCST_Y! >>cs_lines.txt

  echo !mx! !my! >>cs_tri1.lis
  echo !ncCST_X! !ncCST_Y! >>cs_tri2.lis

  echo !mx! !my! !ncCST_X! !ncCST_Y! >>cs_correl_1_2.lis
  echo !ncCST_X! !ncCST_Y! !mx! !my! >>cs_correl_2_1.lis
)

set ncSEA_COL=

Add the central point as a null-distortion.

for /F "usebackq" %%L in (`%IM%identify ^
  -ping ^
  -format "W_2=%%[fx:w/2]\nH_2=%%[fx:h/2]" ^
  cs_msk1.png`) do set %%L

echo %W_2% %H_2% >>cs_tri1.lis
echo %W_2% %H_2% >>cs_tri2.lis

echo %W_2% %H_2% %W_2% %H_2% >>cs_correl_1_2.lis
echo %W_2% %H_2% %W_2% %H_2% >>cs_correl_2_1.lis

Make debugging images.

:skip

call %PICTBAT%tritsttst cs_tri1.lis cs_t1
cs_t1_l.png cs_t1_e.png cs_t1_t.png cs_t1_c.png
call %PICTBAT%tritsttst cs_tri2.lis cs_t2
cs_t2_l.png cs_t2_e.png cs_t2_t.png cs_t2_c.png
%IM%convert ^
  cs_msk1.png ^
  cs_msk2.png ^
  -evaluate Divide 2 ^
  -compose Plus -composite ^
  -stroke Red -draw "@cs_lines.txt" ^
  cs_tc_lines.png
cs_tc_lines.png
%IM%convert ^
  cs_src1.png ^
  -distort Shepards "@cs_correl_1_2.lis" ^
  cs_ds1.png

%IM%convert ^
  cs_src2.png ^
  -distort Shepards "@cs_correl_2_1.lis" ^
  cs_ds2.png
cs_ds1.png cs_ds2.png
%IMDEV%convert ^
  cs_src1.png ^
  -verbose ^
  -distort Triangulate "@cs_correl_1_2.lis" ^
  cs_dt1.png >cs_dt1.lis 2^>^&1

%IMDEV%convert ^
  cs_src2.png ^
  -verbose ^
  -distort Triangulate  "@cs_correl_2_1.lis" ^
  cs_dt2.png >cs_dt2.lis 2^>^&1
cs_dt1.png cs_dt2.png

Again, but with "last". Make debugging images.

call %PICTBAT%tritstlasttst cs_tri1.lis cs_t1l
cs_t1l_l.png cs_t1l_e.png cs_t1l_t.png cs_t1l_c.png
call %PICTBAT%tritstlasttst cs_tri2.lis cs_t2l
cs_t2l_l.png cs_t2l_e.png cs_t2l_t.png cs_t2l_c.png
%IM%convert ^
  cs_msk1.png ^
  cs_msk2.png ^
  -evaluate Divide 2 ^
  -compose Plus -composite ^
  -stroke Red -draw "@cs_lines.txt" ^
  cs_tc_lines.png
cs_tc_lines.png
%IM%convert ^
  cs_src1.png ^
  -define triangulate:edgesort=Last ^
  -distort Shepards "@cs_correl_1_2.lis" ^
  cs_ds1l.png

%IM%convert ^
  cs_src2.png ^
  -define triangulate:edgesort=Last ^
  -distort Shepards "@cs_correl_2_1.lis" ^
  cs_ds2l.png
cs_ds1l.png cs_ds2l.png
%IMDEV%convert ^
  cs_src1.png ^
  -verbose ^
  -define triangulate:edgesort=Last ^
  -distort Triangulate "@cs_correl_1_2.lis" ^
  cs_dt1l.png >cs_dt1l.lis 2^>^&1

%IMDEV%convert ^
  cs_src2.png ^
  -verbose ^
  -define triangulate:edgesort=Last ^
  -distort Triangulate  "@cs_correl_2_1.lis" ^
  cs_dt2l.png >cs_dt2l.lis 2^>^&1
cs_dt1l.png cs_dt2l.png

Scripts

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

nearCoast.bat

rem Given image %1 is black mainland around white "sea",
rem finds coordinates (ncX,ncY) of nearest point on the mainland to given coordinate.
rem If the given coord is in the white "sea", the nearest point will be on the coast.
@rem
@rem   %2, %3 coords of central point  [default center of %1]
@rem        Each coord may be suffixed with "%", for percentage of width or height.
@rem        Default: centre of image.
@rem   %4 proportion towards coast point (0 to 100) [100]
@rem   %5 output debugging image [default NULL:, no output]
@rem
@rem Also uses:
@rem   ncSUP_SAMP Factor for supersampling [default 1].
@rem   ncPREFIX prefix for temporary files
@rem   ncBLACKSEA if 1, assumes sea is black (and land is white) so doesn't negate.
@rem   ncSEA_COL sea color: black, white or auto. Default white.
@rem     auto will choose automatically, which takes time.
@rem   nc?? automatic choice for negate
@rem   nc?? if 1, assumes %1 is already supersampled and unrolled.
@rem
@rem Returns data about nearest point:
@rem   ncRAD   distance from given coord. 0 means given coord wasn't sea.
@rem   ncTHETA bearing from given coord to found point, anti-clockwise from north.
@rem   ncCST_X } x,y coord of found point.
@rem   ncCST_Y }


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

@setlocal enabledelayedexpansion

@call echoOffSave

call %PICTBAT%setInOut %1 nc


if "%ncIM%"=="" set ncIM=%IMDEV%

set CENT_X=%2
set CENT_Y=%3

if "%CENT_X%"=="." set CENT_X=
if "%CENT_Y%"=="." set CENT_Y=

set BLANK_CENT=0
if "%CENT_X%"=="" if "%CENT_Y%"=="" set BLANK_CENT=1

if "%CENT_X%"=="" set CENT_X=50%%
if "%CENT_Y%"=="" set CENT_Y=50%%

set X_SUFFIX=%CENT_X:~-1%
if "%X_SUFFIX%"=="%%" (
  set nX=%CENT_X:~0,-1%
  set X_MULT=w/100
) else (
  set nX=%CENT_X%
  set X_MULT=1
)

set Y_SUFFIX=%CENT_Y:~-1%
if "%Y_SUFFIX%"=="%%" (
  set nY=%CENT_Y:~0,-1%
  set Y_MULT=h/100
) else (
  set nY=%CENT_Y%
  set Y_MULT=1
)

set PROP=%4
if "%PROP%"=="." set PROP=
if "%PROP%"=="" set PROP=100

set OUTFILE=%5
if "%OUTFILE%"=="." set OUTFILE=
if "%OUTFILE%"=="" set OUTFILE=NULL:

set SUP_SAMP=%ncSUP_SAMP%
if "%SUP_SAMP%"=="." set SUP_SAMP=
if "%SUP_SAMP%"=="" set SUP_SAMP=1

for /F "usebackq" %%L in (`%ncIM%identify ^
  -ping ^
  -format "WW=%%w\nHH=%%h\nnX=%%[fx:%nX%*%X_MULT%]\nnY=%%[fx:%nY%*%Y_MULT%]"
  %INFILE%`) do set %%L

for /F "usebackq" %%L in (`%ncIM%identify ^
  -ping ^
  -format "W_SS=%%[fx:%WW%*%SUP_SAMP%]\nH_SS=%%[fx:%HH%*%SUP_SAMP%]\nnXS=%%[fx:%nX%*%SUP_SAMP%]\nnYS=%%[fx:%nY%*%SUP_SAMP%]"
  xc:`) do set %%L

rem echo WW=%WW%  HH=%HH%  W_SS=%W_SS%  H_SS=%H_SS%  nX=%nX%  nY=%nY%  nXS=%nXS%  nYS=%nYS%

if %BLANK_CENT%==1 (
  set sUNROLL=-distort depolar "-1,0"
) else (
  set sUNROLL=-distort depolar "-1,0,%nXS%,%nYS%"
)

if %SUP_SAMP%==1 (
  set sSUP_UP=
) else (
  set sSUP_UP=-resize "%W_SS%x%H_SS%^^^!"
)

if "%ncBLACKSEA%"=="1" (
  set sNEG=
) else (
  set sNEG=-negate
)

if "%ncSEA_COL%"=="" set ncSEA_COL=white

if "%ncSEA_COL%"=="white" (
  set sNEG=-negate
) else if "%ncSEA_COL%"=="black" (
  set sNEG=
) else if "%ncSEA_COL%"=="auto" (
  for /F "usebackq" %%L in (`%ncIM%identify ^
    -format "doNEG=%%[fx:p{0,0}.intensity>0.5?1:0]" ^
    %INFILE%`) do set %%L

  if "!doNeg!"=="1" (
    set sNEG=-negate
  ) else (
    set sNEG=
  )
) else (
  echo %0: bad ncSEA_COL "%ncSEA_COL%"
)

for /F "usebackq tokens=1-3 delims=:, " %%W in (`%ncIM%convert ^
  %INFILE% ^
  %sNEG% ^
  %sSUP_UP% ^
  -virtual-pixel Black ^
  %sUNROLL% ^
  -threshold 50%% ^
  -process onewhite ^
  NULL: 2^>^&1`) do (
  set MAGIC=%%W
  set X=%%X
  set Y=%%Y
)

if not "%magic%"=="onewhite" exit /B 1

for /F "usebackq" %%L in (`%ncIM%identify ^
  -ping ^
  -format "dx=%%[fx:%nXS%>%W_SS%/2?%nXS%:%W_SS%-%nXS%]\ndy=%%[fx:%nYS%>%H_SS%/2?%nYS%:%H_SS%-%nYS%]"
  %INFILE%`) do set %%L

for /F "usebackq" %%L in (`%ncIM%identify ^
  -ping ^
  -format "RAD=%%[fx:%Y%/%SUP_SAMP%*hypot(%dx%,%dy%)/%H_SS%]\nTHETA=%%[fx:%X%*2*pi/%W_SS%]"
  xc:`) do set %%L

for /F "usebackq" %%L in (`%ncIM%identify ^
  -format "CST_X=%%[fx:%nX%-%RAD%*sin(%THETA%)]\nCST_Y=%%[fx:%nY%-%RAD%*cos(%THETA%)]"
  xc:`) do set %%L

rem echo RAD=%RAD% THETA=%THETA% CST_X=%CST_X% CST_Y=%CST_Y%

if not "%OUTFILE%"=="NULL:" (

  if "%sNEG%"=="" (
    set DBG_COL=yellow
  ) else (
    set DBG_COL=red
  )

  %ncIM%convert ^
    %INFILE% ^
    -fill None -stroke !DBG_COL! ^
    -draw "line   %nX%,%nY% %CST_X%,%CST_Y%" ^
    -draw "circle %nX%,%nY% %CST_X%,%CST_Y%" ^
    -alpha off ^
    %OUTFILE%
)

call echoRestore

@endlocal & set ncOUTFILE=%OUTFILE%& set ncRAD=%RAD%& set ncTHETA=%THETA%& set ncCST_X=%CST_X%& set ncCST_Y=%CST_Y%

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 correlsh.h1. To re-create this web page, run "procH1 correlsh".


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 16-August-2015.

Page created 13-Oct-2015 20:06:40.

Copyright © 2015 Alan Gibson.