Searching for the location of one image inside another is very easy. Doing it quickly is harder.
This is a sub-problem of the more general problem: "What areas in image A match what areas in image B?"
Here is an easy search. We create a large image and a small image, then search for the best position of the small image within the large one.
%IMG7%magick ^ -size 400x300 xc: ^ -sparse-color barycentric "0,0 #88f 399,0 #44f 0,299 #2f2 399,299 #484" ^ si_large.png |
|
Small image: %IMG7%magick ^ -size 50x50 xc:#0aa ^ -sparse-color barycentric "0,0 #0af 49,0 #28f 0,49 #2f2 49,49 #484" ^ si_sub.png |
%IMG7%magick compare ^ si_large.png si_sub.png ^ -metric RMSE ^ -subimage-search ^ NULL: cmd /c exit /B 0
10728.2 (0.163701) @ 135,144
IM has placed the small image against every possible position within the large image. At each position, it compares the small image with the same area of the large image, using the RMSE metric. It keeps track of the best score. It returns the best score, both as an integer between zero and quantum, and as a floating point from 0.0 to 1.0. It also returns the coordinates of the position of this best score.
Aside: Subimage-search for metric NCC doesn't seem to work:
rem %IMG7%magick compare ^ rem si_large.png si_sub.png ^ rem -metric NCC ^ rem -subimage-search ^ rem NULL: cmd /c exit /B 0
We can get these four values into environment variables, so we can paste the sub-image over the large image at the found position.
for /F "usebackq tokens=1-4 delims=()@, " %%A in (`%IMG7%magick compare ^ si_large.png si_sub.png ^ -metric RMSE ^ -subimage-search ^ NULL: 2^>^&1`) ^ do ( set SI_COMP_INT=%%A set SI_COMP_FLT=%%B set SI_COMP_X=%%C set SI_COMP_Y=%%D ) %IMG7%magick ^ si_large.png ^ si_sub.png ^ -geometry +%SI_COMP_X%+%SI_COMP_Y% ^ -composite ^ si_comp.png |
As mentioned above, IM compares the small image with part of the large image, for every possible position. There are (W-w+1)*(H-h+1) possible positions, where WxH are the dimensions of the large image and wxh are the dimensions of the sub image.
At each position, it does w*h pixel-by-pixel comparisons.
So the total number of pixel-by-pixel comparisons is (W-w+1)*(H-h+1)*w*h.
If both images were twice as wide and twice as high, the number of comparisons would increase by a factor of approximately 24=16. In general the time taken is proportional to linear_dimension4. This is bad news for large images such as digital photographs.
A solution is to reduce the size of both images equally. If each image is halved, the time is reduced to about 1/16th, which is a big improvement. The reduction could be anything we want, giving massive performance increases, but there are two pitfalls:
After many experiments with photographs and video frames, I have concluded that reducing both images such that the minimum dimension is between 10 and 20 pixels works well. However, if the minumum dimension is already between 10 and 19 pixels, we can halve the dimensions.
The script srchImg.bat does two or more searches. The first resizes the images before searching; the last uses the results of the previous to make a crop that will be searched. Any intermediary searches are on a resized crop. When used with set siDEBUG=1, we also get debugging text and an image.
set siDEBUG=1 call %PICTBAT%srchImg si_large.png si_sub.png F:\pictures\srchImg: MinDim=50 Offset=(0,0) :ResizeSrch: 20 5 :ResizeSrch: Creating TMPSRC_RES [C:\Users\Alan\AppData\Local\Temp\siSrc_si_large_20.miff] :ResizeSrch: 10701.9 0.1633 27 29 :ResizeSrch: COMP_XW,YW = 135,145 IsDissim=0 :CropResizeSrch: 135,145 10 50 2 :CropResizeSrch: 10725.5 0.163661 6 5 :CropResizeSrch: COMP_XW,YW = 137,145 IsDissim=0 :CropSrch: 137,145 2 :CropSrch: 10728.2 0.163701 0 1 :CropSrch: COMP_XW,YW = 135,144 IsDissim=0 echo siCOMP_XW=%siCOMP_XW% siCOMP_YW=%siCOMP_YW% siCOMP_FLT=%siCOMP_FLT% siCOMP_CROP=%siCOMP_CROP% siCOMP_XW=135 siCOMP_YW=144 siCOMP_FLT=0.163701 siCOMP_CROP=50x50+135+144 |
When the sub-image is small, less than 10 pixels on the shortest dimension, the script doesn't save any time. The greatest savings occur when the sub-image is only slightly smaller than the large image. Sadly, I usually want to search for small sub-images. For real photographs, a sub-image size of 100x100 generally works well, but bigger is faster. Approximates timings for large image 4000x3000, with given sizes of sub-image:
The value returned in siCOMP_FLT is the number in parentheses from IM's compare. Zero is an exact match.
The script will use a setting for -dissimilarity-threshold of siDISSIM_THR. By default, this is 1.0.
Any setting of siDISSIM_THR between 0 and 1 will stop the script early if any of the searches have a worse score. This can increase performance when we are looking for exact matches rather than more generally for the best match.
Beware of setting siDISSIM_THR too low. Even if the final search would yield a perfect score of zero, and previous search might not.
The returned variable siIS_DISSIM will be 0 if a match was found within the limit, and 1 if it wasn't.
I took two hand-held photographs with a GoPro camera, pointing the camera in roughly the same direction for both. They are both 4000x3000 pixels. Here is the first, resized for the web, and a crop from the second.
The large image (shown resized for the web): set WEB_SIZE=-resize 500x500 set SRC=%PICTLIB%20140430\GOPR0166.JPG set SI_SRC=si_src.jpg if not exist %SI_SRC% copy %SRC% %SI_SRC% %IMG7%magick ^ %SI_SRC% ^ %WEB_SIZE% ^ si_photo_sm.jpg |
|
Subimage, taken from the second photo: %IMG7%magick ^ %PICTLIB%20140430\GOPR0167.JPG ^ -crop 200x200+2481+2493 +repage ^ si_photo_sub.png |
We search for the sub-image, marking the location with a red square:
set siDEBUG=1 set siDEBUG_STROKE=-fill None -stroke #f00 -strokewidth 10 call StopWatch call %PICTBAT%srchImg %SI_SRC% si_photo_sub.png call StopWatch set siDEBUG= set siDEBUG_STROKE= 0 00:00:19 echo siCOMP_XW=%siCOMP_XW% siCOMP_YW=%siCOMP_YW% ^ siCOMP_FLT=%siCOMP_FLT% siCOMP_CROP=%siCOMP_CROP% siCOMP_XW=2407 siCOMP_YW=2377 siCOMP_FLT=0.121981 siCOMP_CROP=200x200+2407+2377 %IMG7%magick ^ si_src_si_dbg.tiff ^ %WEB_SIZE% ^ si_src_si_dbg_sm.jpg |
|
Crop out what has been found, just to see what it looks like. %IMG7%magick ^ %SI_SRC% ^ -crop %siCOMP_CROP% ^ si_fnd_crp.png |
|
The difference with the sub-image: %IMG7%magick ^ si_photo_sub.png ^ si_fnd_crp.png ^ -compose Difference -composite ^ -auto-level ^ si_fnd_diff.png |
For comparison, here is the same search as a simple IM command:
call StopWatch %IMG7%magick compare ^ %SI_SRC% si_photo_sub.png ^ -metric RMSE ^ -subimage-search ^ NULL: call StopWatch
7249.67 (0.110623) @ 1431,1046 0 03:42:53
This takes massively longer: hours instead of seconds. It has found a different solution, numerically slightly better than the script's solution. (The RMSE difference from the sub-image si_photo_sub.png is slightly lower.)
Crop the result found by the simple command, just to see what it looks like. for /F "usebackq tokens=3,4 delims=()@, " %%X in (si_srch3.lis) do ( set FND_X=%%X set FND_Y=%%Y ) %IMG7%magick ^ %SI_SRC% ^ -crop 200x200+%FND_X%+%FND_Y% +repage ^ si_fnd_crp2.png |
Although the result from the single command is numerically better, it is clearly wrong. (Previous versions of IM found results that were closer to that of the script.)
This script copes with small rotations that are typically found with holding a camera in one's hand, up to around 10°. If the angle is large, eg 45°, it will find false positives. Smaller sub-images are more tolerant of rotations. Searching rotated images are the subject of another page, What rotation?.
A process module is available for a similar function. See Process modules: multi-scale image search.
Option | Description | |
---|---|---|
Short
form |
Long form | |
n | noCrop | Don't replace input images with crop. |
z number | sizeDiv number | Size divider for multi_scale.
Default: 2.0. |
md integer | minDim integer | Minimum dimension for multi_scale.
Default: 20. |
ss integer | superSample integer | Factor for super-sampling.
Default: 1 (no super-sampling). |
f string | file string | Write verbose text to stderr or stdout.
Default: stderr. |
v | verbose | Write some text output to stderr. |
version | Write version information to stderr. |
The script reads and writes image files at each level, which is a large overhead. The process module doesn't read and write so the overhead is far smaller and we adopt a simpler scheme that resizes by 50% at each level. Experimentation suggests that 50% ("sizeDiv 2") is the optimum amount for speed.
The module resizes from each level to the next, so at one level we have a 50% resize of a 50% resize of a 50% resize of the input. It may be more accurate (but slower) to multiply the factors and always resize directly from the input, so we get a 12.5% resize of the input.
call StopWatch %IM7DEV%magick ^ %SI_SRC% si_photo_sub.png ^ -process srchimg ^ si_pm_out.png >si_pm.lis 2^>^&1 call StopWatch 0.1219815 @ 2407,2377 0 00:00:10 |
Decreasing the minDim parameter will perform a smaller subimage search at the lowest level, which increases performance but also increases the probability of an incorrect result.
call StopWatch %IM7DEV%magick ^ %SI_SRC% si_photo_sub.png ^ -process 'srchimg md 10' ^ si_pm2_out.png >si_pm2.lis 2^>^&1 call StopWatch 0.1219815 @ 2407,2377 0 00:00:06 |
|
call StopWatch %IM7DEV%magick ^ %SI_SRC% si_photo_sub.png ^ -process 'srchimg md 5' ^ si_pm3_out.png >si_pm3.lis 2^>^&1 call StopWatch 0.13506816 @ 2476,2615 0 00:00:04 |
The module can super-sample, which gives results precise to sub-pixel. For example, superSample 100 will give a resolution of 0.01 pixels. Internally, this works by resizing the sub-image by that factor, and also a slightly larger crop of the main image by the same factor. So beware of memory requirements when large factors are used with large sub-images.
Super-sampling is useful for long chain-searches, eg tracking movement of features through hundreds of video frames.
We don't need to keep large tiff files, so delete them.
del si_*_*.tiff
For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.
rem Searches image %1 for smaller image %2. @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 Writes results to optional batch file %3. Don't use this; it is for legacy purposes only. @rem @rem Also uses: @rem siMETRIC defaults to RMSE @rem siDEBUG if 1, creates a marked-up copy of image. @rem siDEBUG_STROKE eg "-fill None -stroke #f00 -strokewidth 10" to get thick strokes @rem siDELTEMPSRC if not 0, will remove temporary source (%1) files. @rem siDELTEMPSUB if not 0, will remove temporary subimage (%2) files. @rem siDIV_DIM Divide min dim by this, for purpose of choosing resizes. [1] @rem siDISSIM_THR Dissimilarity threshold. [1] @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 siIS_DISSIM 1 if images too dissimilar; otherwise 0 @rem Written: 31 Jan 2014 @rem Revised: 6 May 2014 @rem Revised: 31 May 2014 Don't resize src if already exists. @rem Revised: 8 August 2016 Tidied, slightly. @rem Revised: 9 September 2016 Added siDISSIM_THR @rem Revised: 10-August-2022 for IM v7. @rem @rem FIXME: +repage, then add offsets (-format "%X %Y") at end. @if "%2"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave call %PICTBAT%setInOut %1 si set siERROR=0 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 SRC_PREF=%TMPDIR%\siSrc_%SRCNAME% set TMPSRC=%SRC_PREF%%TMPEXT% set TMPSUB=%TMPDIR%\siSub%TMPEXT% if not "%siDELTEMPSRC%"=="0" ( call :delTemp %TMPSRC% ) if not "%siDELTEMPSUB%"=="0" ( call :delTemp %TMPSUB% ) if not "%fBat%"=="NUL" del %fBat% 2>nul if "%siDIV_DIM%"=="" set siDIV_DIM=1 if "%siDISSIM_THR%"=="" set siDISSIM_THR=1 set subW= for /F "usebackq" %%L in (`%IMG7%magick ^ %SUB% ^ -format "subW=%%w\nsubH=%%h\nMinDim=%%[fx:int((w<h?w:h)/%siDIV_DIM%+0.5)]" ^ info:`) do set /A %%L if "%subW%"=="" set siERROR=1 set OFFSET_X= for /F "usebackq" %%L in (`%IMG7%magick identify ^ -format "OFFSET_X=%%X\nOFFSET_Y=%%Y" ^ %SRC%`) do set /A %%L if "%OFFSET_X%"=="" set siERROR=1 if %siERROR%==1 exit /B 1 echo %0: MinDim=%MinDim% Offset=(%OFFSET_X%,%OFFSET_Y%) set SIM_DISSIM=-similarity-threshold 0 -dissimilarity-threshold %siDISSIM_THR% set IsDissim=0 if %MinDim% GEQ 10000 ( call :ResizeSrch 0.01 1000 call :CropResizeSrch !COMP_XW! !COMP_YW! 2000 0.2 500 call :CropResizeSrch !COMP_XW! !COMP_YW! 1000 0.5 200 call :CropResizeSrch !COMP_XW! !COMP_YW! 400 1 100 call :CropResizeSrch !COMP_XW! !COMP_YW! 200 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 5000 ( call :ResizeSrch 0.2 500 call :CropResizeSrch !COMP_XW! !COMP_YW! 1000 0.5 200 call :CropResizeSrch !COMP_XW! !COMP_YW! 400 1 100 call :CropResizeSrch !COMP_XW! !COMP_YW! 200 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 2000 ( call :ResizeSrch 0.5 200 call :CropResizeSrch !COMP_XW! !COMP_YW! 400 1 100 call :CropResizeSrch !COMP_XW! !COMP_YW! 200 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 1000 ( call :ResizeSrch 1 100 call :CropResizeSrch !COMP_XW! !COMP_YW! 200 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 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 :CropResizeSrch !COMP_XW! !COMP_YW! 20 20 5 call :CropResizeSrch !COMP_XW! !COMP_YW! 10 50 2 call :CropSrch !COMP_XW! !COMP_YW! 2 ) else if %MinDim% GEQ 50 ( call :ResizeSrch 20 5 call :CropResizeSrch !COMP_XW! !COMP_YW! 10 50 2 call :CropSrch !COMP_XW! !COMP_YW! 2 ) 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 (`%IMG7%magick compare ^ %SIM_DISSIM% -subimage-search ^ -metric %siMETRIC% %SRC% %SUB% NULL: 2^>^&1`) ^ DO ( if /I %%U GTR A set IsDissim=1 set COMP_INT=%%R set COMP_FLT=%%S set COMP_XW=%%T set COMP_YW=%%U ) ) if %siERROR%==1 ( echo Error in %0 exit /B 1 ) 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. %IMG7%magick ^ %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 (`%IMG7%magick ^ %SUB% ^ -format "centX=%%[fx:int(%COMP_XW%+w/2)]\ncentY=%%[fx:int(%COMP_YW%+h/2)]" ^ info:`) do set /A %%L if not "%siDELTEMPSRC%"=="0" ( call :delTemp %TMPSRC% ) if not "%siDELTEMPSUB%"=="0" ( call :delTemp %TMPSUB% ) if %siERROR%==1 ( echo Error in %0 exit /B 1 ) if %IsDissim%==1 ( set COMP_FLT=1 ) call echoRestore @endlocal & set siCOMP_XW=%COMP_XW%& set siCOMP_YW=%COMP_YW%& set siCOMP_FLT=%COMP_FLT%& set siIS_DISSIM=%IsDissim%& set siCENT_X=%centX%& set siCENT_Y=%centY%& set siCOMP_CROP=%subW%x%subH%+%COMP_XW%+%COMP_YW% @exit /B 0 rem ------ Subroutines ---------------------------------------------------------- :delTemp if /I "%~x1"==".mpc" del %~dpn1.cache 2>nul del %1 2>nul exit /B 0 :ResizeSrch rem %1 is percentage reduction, eg 50 for 50%. May be <1. rem %2 is multiplier (=100/%1) echo %0: %1 %2 rem The convert and compare could be combined into one convert. set COMP_XW=0 set COMP_YW=0 set TMPSRC_RES=%SRC_PREF%_%1%TMPEXT% @rem FIXME: +repage, then add offsets (-format "%X %Y") at end. if not "%siDELTEMPSRC%"=="0" ( del %TMPSRC_RES% 2>nul ) if not exist %TMPSRC_RES% ( echo %0: Creating TMPSRC_RES [%TMPSRC_RES%] %IMG7%magick %SRC% +repage -resize %1%% %TMPSRC_RES% if ERRORLEVEL 1 set siERROR=1 ) %IMG7%magick %SUB% -resize %1%% %TMPSUB% if ERRORLEVEL 1 set siERROR=1 set COMP_XW= FOR /F "tokens=1-4 usebackq delims=()@, " %%R ^ IN (`%IMG7%magick compare ^ %SIM_DISSIM% -subimage-search ^ -metric %siMETRIC% %TMPSRC_RES% %TMPSUB% NULL: 2^>^&1`) ^ DO ( echo %0: %%R %%S %%T %%U if /I %%U GTR A set IsDissim=1 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%"=="" ( set siERROR=1 exit /B 1 ) if not "%siDELTEMPSRC%"=="0" ( del %TMPSRC_RES% 2>nul ) echo %0: COMP_XW,YW = %COMP_XW%,%COMP_YW% IsDissim=%IsDissim% 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 %0: %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% if %IsDissim%==1 exit /B 0 %IMG7%magick ^ %SRC% ^ +repage ^ -crop %cropW%x%cropH%+%cropL%+%cropT% ^ +repage ^ %TMPSRC% if ERRORLEVEL 1 ( set siERROR=1 exit /B 1 ) set COMP_INT= for /F "tokens=1-4 usebackq delims=()@, " %%R ^ in (`%IMG7%magick compare ^ %SIM_DISSIM% -subimage-search ^ -metric %siMETRIC% %TMPSRC% %SUB% NULL: 2^>^&1`) ^ do ( echo %0: %%R %%S %%T %%U if /I %%U GTR A set IsDissim=1 set COMP_INT=%%R set COMP_FLT=%%S if not "%%T"=="" set /A COMP_XW+=%%T if not "%%U"=="" set /A COMP_YW+=%%U ) if "%COMP_INT%"=="" set siERROR=1 echo %0: COMP_XW,YW = %COMP_XW%,%COMP_YW% IsDissim=%IsDissim% 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/%4) rem %1 to %3 are in terms of original full size. echo %0: %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% if %IsDissim%==1 exit /B 0 %IMG7%magick ^ %SRC% ^ -crop %cropW%x%cropH%+%cropL%+%cropT% ^ +repage ^ -resize %4%% -write %TMPSRC% +delete ^ %SUB% -resize %4%% %TMPSUB% if ERRORLEVEL 1 ( set siERROR=1 exit /B 1 ) set COMP_INT= for /F "tokens=1-4 usebackq delims=()@, " %%R ^ in (`%IMG7%magick compare ^ %SIM_DISSIM% -subimage-search ^ -metric %siMETRIC% %TMPSRC% %TMPSUB% NULL: 2^>^&1`) ^ do ( echo %0: %%R %%S %%T %%U if /I %%U GTR A set IsDissim=1 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 ) if "%COMP_INT%"=="" set siERROR=1 echo %0: COMP_XW,YW = %COMP_XW%,%COMP_YW% IsDissim=%IsDissim% exit /B 0
All images on this page were created by the commands shown, using:
%IMG7%magick -version
Version: ImageMagick 7.1.0-42 Q16-HDRI x64 396d87c:20220709 https://imagemagick.org Copyright: (C) 1999 ImageMagick Studio LLC License: https://imagemagick.org/script/license.php Features: Cipher DPC HDRI OpenCL Delegates (built-in): bzlib cairo freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib Compiler: Visual Studio 2022 (193231332)
Source file for this web page is srchimg.h1. To re-create this web page, run "procH1 srchimg".
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 6-May-2014.
Page created 28-Aug-2022 00:02:15.
Copyright © 2022 Alan Gibson.