When the camera has twisted around the z-axis between photographs, registering the images is difficult. No areas in one image match areas in the other. We want to find alignment when the image has scaled, rotated, translated and perspectived.
We start by finding points (instead of areas) in each image that might match each other. We use one of the methods from Details, details to identify features in one image, ie areas of high variation, high entropy. These are likely to be distinctive in the other image, reducing false matches.
Set up initial conditions:
set WEB_SIZE=-resize 500x500
We start with two images. We want to find points on the first image that correspond to points on the other image. From that list, we will distort the second image so it registers with the first.
The camera has clearly rotated. The camera position has also moved slightly. A perspective transformation cannot align these images perfectly.
The two photographs have undergone similar, but not identical, processing.
All operations on this page are performed on full-size images, roughly 7500x5000 pixels. These are then reduced in size, and converted to JPG, for the web.
The source image. set ap_ALI_SRC=%PICTLIB%20140602\AGA_1858_sat.tiff %IMG7%magick ^ %ap_ALI_SRC% ^ %WEB_SIZE% ^ ap_ALI_SRC_sm.jpg |
|
Another image. set ap_OTH_SRC=%PICTLIB%20140602\AGA_1860_sat.tiff %IMG7%magick ^ %ap_OTH_SRC% ^ %WEB_SIZE% ^ ap_OTH_SRC_sm.jpg |
For both images, we find six points of interest, using one of the methods from Details, details. The red circles in the debug image are the exclusion zones, showing the minimum distance between features.
Why only six? Because the time required is proportional to n4.
Use a difference between two blurs to find detail. call %PICTBAT%twoBlrDiff %ap_ALI_SRC% We will make crops 100x100, so we don't want to find points within 50 pixels of an edge. call %PICTBAT%blackEdge %tbdOUTFILE% 10 1 set SAVE_A_BE=%beOUTFILE% We find the six lightest points. set nlDEBUG=1 call %PICTBAT%getPointsize %ap_ALI_SRC% 50 set nlPOINTSIZE=%gpPointsize% set nlSTROKEWIDTH=10 call %PICTBAT%nLightest %beOUTFILE% 6 >ap_ali_coords.lis %IMG7%magick ^ %nlDEBUG_FILE% ^ %WEB_SIZE% ^ ap_ali_coords_sm.jpg |
|
For the other image, use a difference between two blurs to find detail. call %PICTBAT%twoBlrDiff %ap_OTH_SRC% We will make crops 100x100, so we don't want to find points with 50 pixels of an edge. call %PICTBAT%blackEdge %tbdOUTFILE% 10 1 We find the six lightest points. set nlDEBUG=1 call %PICTBAT%getPointsize %ap_OTH_SRC% 50 set nlPOINTSIZE=%gpPointsize% set nlSTROKEWIDTH=10 call %PICTBAT%nLightest %beOUTFILE% 6 >ap_oth_coords.lis %IMG7%magick ^ %nlDEBUG_FILE% ^ %WEB_SIZE% ^ ap_oth_coords_sm.jpg |
We can see by eye that the following points correspond:
ALI_SRC | OTH_SRC |
---|---|
0 | 1 |
2 | 0 |
3 | 2 |
4 | 4 |
ALI_SRC point 1 is close to OTH_SRC point 3.
This is a benchark we will use later, to confirm the automated results.
How do we do automatically find points that correspond?
One possibility would be to make crops from one image and search for them in the other area. With arbitrary rotations and scaling, this is difficult.
Another possibility, developed here, is to consider all possible alignments that are defined by the correspondence of two points in one image with two points in the other image.
How many alignments are there? If we have n points, there are (n-1) * n/2 * n * (n-1) possible alignments. For n=6, there are 450 possible alignments. For n=10, there are 4050 possible alignments.
How do we know when an alignment is good? We could distort the image, then check for crops of one image in the other. This would be expensive.
Instead, we look for two aligments that are similar. The principle is that most possible alignments are incorrect, but some are correct. The ones that are correct will be similar to each other. By finding the two alignments that are closest to each other, we should have found two correct alignments.
It is possible that the two closest alignments are both incorrect. This obviously occurs when the points have been badly chosen and there are no correct alignments. Theoretically, it could also happen when there are correct alignments, but two incorrect alignments happen to be close to each other. I haven't seen this happen (yet).
Comparing all alignments with each other would be feasible in a compiled program, but not in a Windows BAT script. Instead, we simplfy the problem. We will consider similarity only for the TX and TY parameters. We do this in two stages. First, we add the absolute values of TX and TY. This gives us a single number that we can sort on; two similar alignments will have similar numbers.
For convenience, we read the point coordinates into an array of structures. We want to distort the second to match the first, so we use OTH_SRC as image A, and ALI_SRC as image B.
set lstA=ap_oth_coords.lis set lstB=ap_ali_coords.lis set alSep=, call %PICTBAT%appendLines %lstA% %lstB% >ap_corrPnts.csv call %PICTBAT%readCoordPairs ap_corrPnts.csv ap_corrPnts 1 2 3 4 set ap_corrPnts
ap_corrPnts.COORDS= 6622,3910,4338,3019 3584,2988,1884,3121 1275,1010,6417,707 2534,932,1397,4307 4585,1413,3383,1368 1820,1194,3893,3439 ap_corrPnts.nPAIRS=6 ap_corrPnts[0].A.x=6622 ap_corrPnts[0].A.y=3910 ap_corrPnts[0].B.x=4338 ap_corrPnts[0].B.y=3019 ap_corrPnts[1].A.x=3584 ap_corrPnts[1].A.y=2988 ap_corrPnts[1].B.x=1884 ap_corrPnts[1].B.y=3121 ap_corrPnts[2].A.x=1275 ap_corrPnts[2].A.y=1010 ap_corrPnts[2].B.x=6417 ap_corrPnts[2].B.y=707 ap_corrPnts[3].A.x=2534 ap_corrPnts[3].A.y=932 ap_corrPnts[3].B.x=1397 ap_corrPnts[3].B.y=4307 ap_corrPnts[4].A.x=4585 ap_corrPnts[4].A.y=1413 ap_corrPnts[4].B.x=3383 ap_corrPnts[4].B.y=1368 ap_corrPnts[5].A.x=1820 ap_corrPnts[5].A.y=1194 ap_corrPnts[5].B.x=3893 ap_corrPnts[5].B.y=3439
An alignment is defined by two points in one image corresponding to two points in the other image. We loop through all possible combinations of two different points in A and two different points in B. So there are four levels of nested loops.
Each pass calls getPerspParams to call IM "-distort" for the transformation parameters. As we are using just two points from the two images, this is overkill. The transformation can only be scale, rotate and translate, with no shear or perspective, and is easy to calculate from the coordinates. (Two points in two images define two lines. The ratio of the lengths gives the scale; the angle between the lines gives the rotation. Apply the scale and rotatation to one point, subtract its (x,y) from the (x,y) of the point in the other image, and that is the translation.)
set /A nMin1=%ap_corrPnts.nPAIRS%-1 set /A nMin2=%ap_corrPnts.nPAIRS%-2 rem i,j are indices into image A rem k,l are indices into image B set XYLIST=ap_xylist.csv del %XYLIST% 2>nul call echoOffSave rem Visit every possible alignment. rem For each one, calculate the sum of the absolute TX and TY parameters. rem for /L %%i in (0,1,%nMin2%) do ( set /A j0=%%i+1 for /L %%j in (!j0!,1,%nMin1%) do ( echo %%i %%j for /L %%k in (0,1,%nMin1%) do ( set /A l0=%%k+1 for /L %%l in (0,1,%nMin1%) do ( if not %%k==%%l ( echo ijkl = %%i %%j %%k %%l set TwoPairs=!ap_corrPnts[%%i].A.x!,!ap_corrPnts[%%i].A.y!,!ap_corrPnts[%%k].B.x!,!ap_corrPnts[%%k].B.y! !ap_corrPnts[%%j].A.x!,!ap_corrPnts[%%j].A.y!,!ap_corrPnts[%%l].B.x!,!ap_corrPnts[%%l].B.y! echo !TwoPairs! call %PICTBAT%getPerspParams TwoPairs pp for /F "usebackq" %%L in (`%IMG7%magick identify ^ -format "sumAbs=%%[fx:abs(!pp.TX!)+abs(!pp.TY!)]" ^ xc:`) do set %%L echo !sumAbs!,!pp.TX!,!pp.TY!, %%i,%%j, %%k,%%l >>%XYLIST% ) ) ) ) ) call echoRestore
The created file, %XYLIST%, has 450 lines, one for each possible alignment. (Perhaps we might restrict the output to alignments where |TX| < 2 * image_width && |TY| < 2 * image_height.)
Then we sort on the sum of the absolute TX and TY parameters, and append each line with the next line.
Aside: cSort.exe is used here to sort in order of the first, then second, columns. The data is interpreted as floating-point numbers. cSort.exe is my own unpublished software. If the only values were 0.000 to 9.999, a text sorter such as Windows sort command would work. Of course, we only want the lowest value, so sorting is overkill.
cSort /i%XYLIST% /o%XYLIST% /k0,1 cHead /i%XYLIST% /oap_xtm1.lis /h1 /x call %PICTBAT%appendLines %XYLIST% ap_xtm1.lis >ap_comp.csv
The file ap_comp.csv contains one line per pair of algnments that might be similar.
We refine the comparison of each alignment with the next. Two similar alignments will have similar sums of absolute values of TX and TY, and similar TX, and similar TY. So by taking differences and adding them together, we then have a measure of similarity of pairs of alignments. This is quite slow because we are calling "identify" to do the calculation.
An input line may say that a point from A corresponds to two points on B, or vice versa. If this happens, we disregard the line.
rem Add the absolute values of the differences of: rem the sum of the absolute TX and TY parameters rem the TX parameters rem the TY parameters rem rem We assume that the smallest value gives the best pair of alignments. rem rem IsOk was: rem IsOk=%%[fx:(%%D==%%K)==(%%E==%%L)&&(%%F==%%M)==(%%G==%%N)?1:0] rem set COMP_SRT=ap_comp_srt.csv del %COMP_SRT% 2>nul for /F "tokens=1-14 delims=, " %%A in (ap_comp.csv) do ( for /F "usebackq" %%L in (`%IMG7%magick identify ^ -format "delta=%%[fx:abs(%%H-(%%A))+abs(%%I-(%%B))+abs(%%J-(%%C))]\nIsOk=%%[fx:(%%D==%%K)==(%%F==%%M)&&(%%D==%%L)==(%%F==%%N)&&(%%E==%%K)==(%%G==%%M)&&(%%E==%%L)==(%%G==%%N)]" ^ xc:`) do set %%L if !IsOk!==1 echo !delta!, %%A,%%B,%%C,%%D,%%E,%%F,%%G, %%H,%%I,%%J,%%K,%%L,%%M,%%N >>%COMP_SRT% )
We sort, and take the lowest measure:
cSort /i%COMP_SRT% /o%COMP_SRT% /k0 cHead /i%COMP_SRT% /h1 /ocomp_srt1.csv
Aside: Just for interest, here are the first 12 lines:
cHead /i%COMP_SRT% /h12 /ocomp_srt12.csv
3.49783, 5113.52,-90.9378465,5022.58633,0,3,2,1, 5115.27,-91.0307269,5024.24128,0,2,2,3 3.9583, 5115.27,-91.0307269,5024.24128,0,2,2,3, 5117.25,-92.1178193,5025.13249,2,3,3,1 62.3611, 5202.18,-177.403304,5024.77931,2,4,3,4, 5204.74,-148.782765,5055.95986,1,2,0,3 203.661, 3375.74,836.743469,2538.99226,2,4,1,0, 3420.93,938.576339,2482.35377,1,5,2,4 868.392, 4267.81,1232.88747,3034.92114,0,2,0,1, 4283.19,814.071308,3469.1167,2,4,1,4 906.195, 8730.75,4648.18184,4082.56547,2,4,5,1, 8743.84,4208.17808,4535.66642,1,2,4,5 979.459, 4975.69,391.785886,4583.90494,0,5,5,3, 4994.34,-489.72744,4504.60887,1,2,2,1 1003.03, 4170.44,137.34355,4033.09714,2,4,3,5, 4170.66,638.861079,3531.80325,0,3,0,1 1025.67, 4074.06,3697.74685,376.31783,2,4,4,5, 4096.58,3207.42809,889.148968,0,2,0,4 1083.84, 7101.48,3600.92531,3500.55773,2,4,5,0, 7144.88,3102.40088,4042.47811,0,2,2,5 1097.49, 11815.7,6780.07364,5035.65746,2,3,0,1, 11818.6,6234.21514,5584.38576,0,4,4,5 1110.73, 4283.19,814.071308,3469.1167,2,4,1,4, 4314.21,1369.43749,2944.76871,0,2,5,1
For simpler matches, from simpler camera movements, most of these would be correct. For this example, the second line is correct but all the rest are wrong. The first line has incorrectly corresponded ALI_SRC point 0 with OTH_SRC point 3. The other two correspondences in this line (2 with 0, and 3 with 2) are correct.
The file comp_srt1.csv is:
3.49783, 5113.52,-90.9378465,5022.58633,0,3,2,1, 5115.27,-91.0307269,5024.24128,0,2,2,3
We now have 3 or 4 correspondences between the images. (The algorithm can give 4, but seems to always give only 3 when the correspondences are correct.) We could add each possible new correspondence to the list, and iterate. But we must beware: not all points will have a corresponding point in the other image.
The following messy code find the 3 or 4 correspondences.
rem Get the numbers of the matching points. rem There will be 3 or 4 matches. rem Either of the last two may be equal to the first two. for /F "tokens=5-8,12-15 delims=, " %%A in (comp_srt1.csv) do ( echo %%A,%%B,%%C,%%D, %%E,%%F,%%G,%%H set ap_corrNdx[0].A=%%A set ap_corrNdx[1].A=%%B set ap_corrNdx[0].B=%%C set ap_corrNdx[1].B=%%D set ap_corrNdx.nPAIRS=2 set /A diff2=^(%%E-%%A^)*^(%%G-%%C^)*^(%%E-%%B^)*^(%%G-%%D^) set /A diff3=^(%%F-%%A^)*^(%%H-%%C^)*^(%%F-%%B^)*^(%%H-%%D^) if not !diff2!==0 ( set ap_corrNdx[2].A=%%E set ap_corrNdx[2].B=%%G set ap_corrNdx.nPAIRS=3 ) if not !diff3!==0 ( set ap_corrNdx[!ap_corrNdx.nPAIRS!].A=%%F set ap_corrNdx[!ap_corrNdx.nPAIRS!].B=%%H set /A ap_corrNdx.nPAIRS+=1 ) echo diff2=!diff2! diff3=!diff3! ) set ap_corrNdx
ap_corrNdx.nPAIRS=3 ap_corrNdx[0].A=0 ap_corrNdx[0].B=2 ap_corrNdx[1].A=3 ap_corrNdx[1].B=1 ap_corrNdx[2].A=2 ap_corrNdx[2].B=3
Above, we found the best transformation from two points that corresponded. Now we know three points that correspond. We can get the coordinates, and feed them to a "-distort".
rem Get the coords of the 3 or 4 points. set /A nLAST=ap_corrNdx.nPAIRS-1 set sCOORD= for /L %%i in (0,1,%nLAST%) do ( set /A ndxA=ap_corrNdx[%%i].A set /A ndxB=ap_corrNdx[%%i].B set /A ax=ap_corrPnts[!ndxA!].A.x set /A ay=ap_corrPnts[!ndxA!].A.y set /A bx=ap_corrPnts[!ndxB!].B.x set /A by=ap_corrPnts[!ndxB!].B.y set sCOORD=!sCOORD! !ax!,!ay!,!bx!,!by! ) echo sCOORD=%sCOORD%
sCOORD= 6622,3910,6417,707 2534,932,1884,3121 1275,1010,1397,4307
%IMG7%magick ^ xc: ^ -verbose ^ -distort Perspective "%sCOORD%" ^ NULL:
Affine projection: -distort AffineProjection \ '0.443409,-0.914466,0.913481,0.444707,-90.9615,5023.79' Equivalent scale, rotation(deg), translation: 1.0163,-64.1321,-90.9615,5023.79 Affine distort, FX equivalent: -fx 'ii=i+page.x+0.5; jj=j+page.y+0.5; xx=+0.430695*ii -0.884698*jj +4483.71; yy=+0.885652*ii +0.429437*jj -2076.84; p{xx-page.x-0.5,yy-page.y-0.5}' \
Note that we need the "+" form of "distort". We also save the transformed version of OTH_SRC, for use later. The file type needs to be capable of recording negative offsets. PNG would be fine, but not TIFF.
set OTH_XFORM=%TEMP%\ap_oth_xf.miff %IMG7%magick ^ %ap_ALI_SRC% ^ ( %ap_OTH_SRC% ^ -virtual-pixel Black ^ +distort Perspective "%sCOORD%" ^ -write %OTH_XFORM% ^ -alpha set -channel A -evaluate Multiply 0.5 ^ ) ^ -layers merge +repage ^ %WEB_SIZE% ^ ap_vis_chk.jpg |
Looking closely at the full-size image, the rear wheel of the red car, and the wing mirror of the yellow car, are both correct. The overall scale, rotate and translate is good, and this is all we can expect from a 3-point match.
We put most of the above into a script, alignPnt.bat, that takes two CSV files of coordinates, and returns 3 or 4 pairs of corresponding coordinates.
call %PICTBAT%alignPnt ap_oth_coords.lis ap_ali_coords.lis echo %apCOORDS%
6622,3910,6417,707 2534,932,1884,3121 1275,1010,1397,4307
Now we know an aproximate alignment, we can find a more exact alignment by:
As the method so far has "latched on" to an incorrect solution, the first is unwise, and we will use the second.
We can take areas around the original six points from ALI_SRC and search for these in the transformed ALI_OTH.
For details of alignArea.bat, see Simple alignment by matching areas.
call %PICTBAT%alignArea %ap_ALI_SRC% %OTH_XFORM% ap_ali_coords.lis if ERRORLEVEL 1 exit /B 1 type %aaCOORDS_CSV% >aa_coords.csv
4355,4721,4338,3019,-17,-1702,1702.0849 , 0 2069,4794,1884,3121,-185,-1673,1683.19755 , 1 1489,6031,1397,4307,-92,-1724,1726.45301 , 3 3325,3183,3383,1368,58,-1815,1815.92649 , 4 3851,5229,3893,3439,42,-1790,1790.49267 , 5
We have found five of the six areas. We can try an alignment with these:
%IMG7%magick ^ %ap_ALI_SRC% ^ ( %OTH_XFORM% ^ -virtual-pixel Black ^ +distort Shepards "%aaCOORDS%" ^ -alpha set -channel A -evaluate Multiply 0.5 ^ ) ^ -layers merge ^ -write x.png ^ +repage ^ %WEB_SIZE% ^ ap_vis_chk2.jpg |
The five points are perfect, but intermediate areas are not good. A larger number of corresponding points should improve the result.
We find as many lightest points as we can. set nlDEBUG=1 call %PICTBAT%getPointsize %ap_ALI_SRC% 50 set nlPOINTSIZE=%gpPointsize% set nlSTROKEWIDTH=10 call %PICTBAT%nLightest %SAVE_A_BE% 9999 >ap_ali_coords2.lis %IMG7%magick ^ %nlDEBUG_FILE% ^ %WEB_SIZE% ^ ap_ali_coords2_sm.jpg |
Make the crops and search for them in the distorted OTH_SRC:
call %PICTBAT%alignArea %ap_ALI_SRC% %OTH_XFORM% ap_ali_coords2.lis if ERRORLEVEL 1 exit /B 1 type %aaCOORDS_CSV% >aa_coords2.csv
4355,4721,4338,3019,-17,-1702,1702.0849 , 0 2069,4794,1884,3121,-185,-1673,1683.19755 , 1 1489,6031,1397,4307,-92,-1724,1726.45301 , 3 3325,3183,3383,1368,58,-1815,1815.92649 , 4 3851,5229,3893,3439,42,-1790,1790.49267 , 5 4862,4552,4909,2758,47,-1794,1794.61556 , 6 1899,5614,1794,3895,-105,-1719,1722.20382 , 7 840,6128,744,4403,-96,-1725,1727.66924 , 8 4628,2773,4575,961,-53,-1812,1812.77494 , 9 2651,4530,2497,2840,-154,-1690,1697.00206 , 10 1383,5275,1196,3601,-187,-1674,1684.41236 , 11 3479,4671,3519,2876,40,-1795,1795.44563 , 13 3339,2566,3096,959,-243,-1607,1625.26859 , 14 5080,4000,5284,2401,204,-1599,1611.96061 , 15 4187,3443,4160,1682,-27,-1761,1761.20697 , 17 2573,4000,2616,2193,43,-1807,1807.51155 , 18 955,5531,767,3856,-188,-1675,1685.51743 , 19 4495,4026,4540,2226,45,-1800,1800.56241 , 21 1538,4360,1355,2691,-183,-1669,1679.00268 , 22 2812,2863,2601,1227,-211,-1636,1649.55054 , 23 2396,3187,2162,1567,-234,-1620,1636.81276 , 26 3573,5724,3631,3934,58,-1790,1790.93942 , 27 2187,4223,1955,2585,-232,-1638,1654.34821 , 29 3755,2805,3814,990,59,-1815,1815.9587 , 34 2808,3495,2866,1671,58,-1824,1824.92192 , 35 1814,3850,1583,2220,-231,-1630,1646.28703 , 36 5880,2351,5614,734,-266,-1617,1638.73274 , 39 3823,2117,3575,518,-248,-1599,1618.11773 , 41 1919,5992,2301,4430,382,-1562,1608.03234 , 43 4482,2195,4248,577,-234,-1618,1634.83332 , 44 3372,3662,3339,1903,-33,-1759,1759.30952 , 45 1171,4488,802,2937,-369,-1551,1594.29044 , 46 5388,2272,5123,661,-265,-1611,1632.64999 , 48 3361,5531,4567,4430,1206,-1101,1632.98408 , 60 2300,3727,2070,2095,-230,-1632,1648.12742 , 61 6236,3316,5495,1679,-741,-1637,1796.90011 , 65
With nLightest.bat defaults, a square image has 50 points. This image has aspect ratio 1:1.5, so around 75 points. (Actually 79.) Searching this size of image takes around 8 seconds per point. So the search takes around ten minutes.
From the list, we see that almost all beyond the 50th were outliers, and choosing to find just the 24 lightest points would have found most non-outliers.
%IMG7%magick ^ %ap_ALI_SRC% ^ ( %OTH_XFORM% ^ -virtual-pixel Black ^ +distort Shepards "%aaCOORDS%" ^ -alpha set -channel A -evaluate Multiply 0.5 ^ ) ^ -layers merge ^ -write x.png ^ +repage ^ %WEB_SIZE% ^ ap_vis_chk3.jpg |
The yellow car is rather fuzzy. The best point for it, number 2, was removed as an outlier. The red car and lorry are okay. Bollards and fencing (hardly visible in the web version) are now aligned, as are most background trees. The most obvious problem is in the framework and roof of the trolley shelter, which is weirdly warped.
This suggests a possible refinement: the radius of the exclusion circle might vary, beginning small, and increasing. This would give a greater weight to areas of high detail. This is desirable: parts of the trees are as warped as the trolley shelter, but this isn't as visible.
For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.
rem Given %1 is the name of an environment variable containing coordinate pairs, rem returns perspective parameters in structure %2.SY etc. rem %3 is method to use: affine or perspective [default perspective] rem rem Updated: rem 23-October-2018 Added %3 for method. rem [[5-November-2018 Changed %1 to be actual string of coords, not an env var.]] @if "%2"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave rem NOTE: rem This can give stupid results, eg for input: rem "0,0,5,5 100,100,105,105 70,70,65,72" rem rem IM gives: rem rem Affine Projection: rem -distort AffineProjection \ rem '1428571428571413.200000,428571428571413.440000,-1428571428571413.200000, rem -428571428571413.440000,0.000000,0.000000' set COORD_PAIRS=!%1! rem set COORD_PAIRS=%~1 echo %0: COORD_PAIRS = %COORD_PAIRS% set MTHD=%3 if "%MTHD%"=="." set MTHD= if "%MTHD%"=="" set MTHD=perspective set /A nLINE=0 for /F "usebackq tokens=*" %%L in (`%IMG7%magick ^ xc: ^ -precision 9 ^ -verbose ^ -distort %MTHD% "%COORD_PAIRS%" ^ +verbose ^ NULL: 2^>^&1`) do ( set LINE=%%L set LINE=!LINE:^>=GREATER_THAN! set LINE=!LINE:^<=LESS_THAN! set LINES[!nLINE!]=!LINE! set /A nLINE+=1 echo %0: LINE=!LINE! ) rem echo nLINE=%nLINE% rem echo 0: %LINES[0]% rem echo 1: %LINES[1]% rem echo 2: %LINES[2]% rem echo 3: %LINES[3]% rem echo 4: {%LINES[4]%} rem echo 5: {%LINES[5]%} rem echo 6: {%LINES[6]%} rem echo 7: {%LINES[7]%} rem echo 8: {%LINES[8]%} rem echo 9: {%LINES[9]%} rem We could also save the "-distort ..." command, if we wanted. set IsPersp=0 for /F "tokens=1-4 delims=',: " %%A in ("%LINES[0]%") do ( if /I "%%A" equ "Perspective" set IsPersp=1 ) rem echo IsPersp=%IsPersp% if %IsPersp%==1 goto IsPersp rem Affine for /F "tokens=1-6 delims=', " %%A in ("%LINES[2]%") do ( rem echo %%A %%B %%C %%D %%E %%F set SX=%%A set RX=%%B set RY=%%C set SY=%%D set TX=%%E set TY=%%F set PX=0 set PY=0 ) set DIST_FX=%LINES[4]% %LINES[5]% %LINES[6]% %LINES[7]% set DIST_FX=%DIST_FX:'="% set DIST_FX=%DIST_FX:\=% goto endPersp :IsPersp rem Perspective for /F "tokens=1-4 delims=', " %%A in ("%LINES[2]%") do ( rem echo %%A %%B %%C %%D set SX=%%A set RY=%%B set TX=%%C set RX=%%D ) for /F "tokens=1-4 delims=', " %%A in ("%LINES[3]%") do ( rem echo %%A %%B %%C %%D set SY=%%A set TY=%%B set PX=%%C set PY=%%D ) set DIST_FX=%LINES[5]% %LINES[6]% %LINES[7]% %LINES[8]% %LINES[9]% set DIST_FX=%DIST_FX:'="% set DIST_FX=%DIST_FX:\=% set DIST_FX=%DIST_FX:GREATER_THAN=^>% set DIST_FX=%DIST_FX:LESS_THAN=^<% :endPersp rem echo DIST_FX=%DIST_FX% rem if not %IsPersp%==1 exit /B 1 @call echoRestore @endlocal & set %2.SX=%SX%& set %2.RY=%RY%& set %2.TX=%TX%& set %2.RX=%RX%& set %2.SY=%SY%& set %2.TY=%TY%& set %2.PX=%PX%& set %2.PY=%PY%& set %2.DIST_FX=%DIST_FX%
rem For image %1, makes black all pixels up to %2 from any edge. rem %3: 0 means param 2 is pixels, 1 means param 2 is percentage. Default 0. rem %4 optional output file @rem @rem Updated: @rem 22-August-2022 Upgraded for IM v7. @rem @if "%2"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion rem @call echoOffSave call %PICTBAT%setInOut %1 be set RTW=%2 set RTH=%2 for /F "usebackq" %%L in (`%IMG7%magick ^ %INFILE% ^ -format "WW=%%w\nHH=%%h\nWm1=%%[fx:w-1]\nHm1=%%[fx:h-1]" ^ info:`) do set %%L if "%3"=="1" ( for /F "usebackq" %%L in (`%IMG7%magick identify ^ -format "RTW=%%[fx:%WW%*%RTW%/100]\nRTH=%%[fx:%HH%*%RTH%/100]" ^ xc:`) do set %%L ) for /F "usebackq" %%L in (`%IMG7%magick ^ %INFILE% ^ -format "WmRT=%%[fx:%WW%-%RTW%]\nHmRT=%%[fx:%HH%-%RTH%]" ^ info:`) do set %%L if not "%4"=="" if not "%4"=="." set OUTFILE=%4 %IMG7%magick ^ %INFILE% ^ -fill #000 ^ -draw "rectangle 0,0 %Wm1%,%RTH% rectangle 0,0 %RTW%,%Hm1% rectangle %WmRT%,0 %Wm1%,%Hm1% rectangle 0,%HmRT% %Wm1%,%Hm1% " ^ %OUTFILE% @call echoRestore @endlocal & set beOUTFILE=%OUTFILE%
rem %1 is CSV file with list of coords from image A. rem %2 is CSV file with list of coords from image B. rem Some points in A correspond to some points in B. rem Returns affine or perspective transformation from B to A. @rem @rem Updated @rem 3-May-2017 Weirdly, needed set lstA and B adding. @rem 3-October-2022 for IM v7. @rem @if "%2"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave call %PICTBAT%setInOut %1 ap set lstA=%1 set lstB=%2 if not exist %lstA% exit /B 1 if not exist %lstB% exit /B 1 set TEMPLIS=%TEMP%\ap_%~n1.csv set alSep=, call %PICTBAT%appendLines %lstA% %lstB% >ap_corrPnts.csv call %PICTBAT%readCoordPairs ap_corrPnts.csv ap_corrPnts 1 2 3 4 set /A nMin1=%ap_corrPnts.nPAIRS%-1 set /A nMin2=%ap_corrPnts.nPAIRS%-2 rem i,j are indexes into image A rem k,l are indexes into image B set XYLIST=%TEMP%\ap_xylist.csv del %XYLIST% 2>nul rem Visit every possible alignment. rem For each one, calculate the sum of the absolute TX and TY parameters. rem for /L %%i in (0,1,%nMin2%) do ( set /A j0=%%i+1 for /L %%j in (!j0!,1,%nMin1%) do ( echo %0: i=%%i j=%%j for /L %%k in (0,1,%nMin1%) do ( set /A l0=%%k+1 for /L %%l in (0,1,%nMin1%) do ( if not %%k==%%l ( rem echo ijkl = %%i %%j %%k %%l set TwoPairs=!ap_corrPnts[%%i].A.x!,!ap_corrPnts[%%i].A.y!,!ap_corrPnts[%%k].B.x!,!ap_corrPnts[%%k].B.y! !ap_corrPnts[%%j].A.x!,!ap_corrPnts[%%j].A.y!,!ap_corrPnts[%%l].B.x!,!ap_corrPnts[%%l].B.y! rem echo !TwoPairs! call %PICTBAT%getPerspParams TwoPairs pp for /F "usebackq" %%L in (`%IMG7%magick identify ^ -format "sumAbs=%%[fx:abs(!pp.TX!)+abs(!pp.TY!)]" ^ xc:`) do set %%L echo !sumAbs!,!pp.TX!,!pp.TY!, %%i,%%j, %%k,%%l >>%XYLIST% ) ) ) ) ) cSort /p0 /i%XYLIST% /o%XYLIST% /k0,1 set APCOMP=%TEMP%\ap_comp.csv cHead /i%XYLIST% /o%TEMP%\ap_xtm1.lis /h1 /x call %PICTBAT%appendLines %XYLIST% %TEMP%\ap_xtm1.lis >%APCOMP% rem Add the absolute values of the differences of: rem the sum of the absolute TX and TY parameters rem the TX parameters rem the TY parameters rem rem We assume that the smallest value gives the best pair of alignments. rem rem IsOk was: rem IsOk=%%[fx:(%%D==%%K)==(%%E==%%L)&&(%%F==%%M)==(%%G==%%N)?1:0] rem set COMP_SRT=%TEMP%\ap_comp_srt.csv del %COMP_SRT% 2>nul for /F "tokens=1-14 delims=, " %%A in (%APCOMP%) do ( if "%%N"=="" ( echo %0: not enough tokens in APCOMP [%APCOMP%] ) else ( for /F "usebackq" %%L in (`%IMG7%magick identify ^ -format "delta=%%[fx:abs(%%H-(%%A))+abs(%%I-(%%B))+abs(%%J-(%%C))]\nIsOk=%%[fx:(%%D==%%K)==(%%F==%%M)&&(%%D==%%L)==(%%F==%%N)&&(%%E==%%K)==(%%G==%%M)&&(%%E==%%L)==(%%G==%%N)]" ^ xc:`) do set %%L if !IsOk!==1 echo !delta!, %%A,%%B,%%C,%%D,%%E,%%F,%%G, %%H,%%I,%%J,%%K,%%L,%%M,%%N >>%COMP_SRT% ) ) if not exist %COMP_SRT% ( echo %0: No entries in COMP_SRT, %COMP_SRT% exit /B 1 ) cSort /p0 /i%COMP_SRT% /o%COMP_SRT% /k0 set COMP_SRT1=%TEMP%\ap_comp_srt1.csv cHead /i%COMP_SRT% /h1 /o%COMP_SRT1% rem Get the numbers of the matching points. rem There will be 3 or 4 matches. rem Either of the last two may be equal to the first two. for /F "tokens=5-8,12-15 delims=, " %%A in (%COMP_SRT1%) do ( echo %%A,%%B,%%C,%%D, %%E,%%F,%%G,%%H set ap_corrNdx[0].A=%%A set ap_corrNdx[1].A=%%B set ap_corrNdx[0].B=%%C set ap_corrNdx[1].B=%%D set ap_corrNdx.nPAIRS=2 set /A diff2=^(%%E-%%A^)*^(%%G-%%C^)*^(%%E-%%B^)*^(%%G-%%D^) set /A diff3=^(%%F-%%A^)*^(%%H-%%C^)*^(%%F-%%B^)*^(%%H-%%D^) if not !diff2!==0 ( set ap_corrNdx[2].A=%%E set ap_corrNdx[2].B=%%G set ap_corrNdx.nPAIRS=3 ) if not !diff3!==0 ( set ap_corrNdx[!ap_corrNdx.nPAIRS!].A=%%F set ap_corrNdx[!ap_corrNdx.nPAIRS!].B=%%H set /A ap_corrNdx.nPAIRS+=1 ) echo diff2=!diff2! diff3=!diff3! ) set ap_corrNdx rem Get the coords of the 3 or 4 points. set /A nLAST=ap_corrNdx.nPAIRS-1 set sCOORD= for /L %%i in (0,1,%nLAST%) do ( set /A ndxA=ap_corrNdx[%%i].A set /A ndxB=ap_corrNdx[%%i].B set /A ax=ap_corrPnts[!ndxA!].A.x set /A ay=ap_corrPnts[!ndxA!].A.y set /A bx=ap_corrPnts[!ndxB!].B.x set /A by=ap_corrPnts[!ndxB!].B.y set sCOORD=!sCOORD! !ax!,!ay!,!bx!,!by! ) echo %0: sCOORD=%sCOORD% @call echoRestore @endlocal & set apCOORDS=%sCOORD%
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-49 Q16-HDRI x64 7a3f3f1:20220924 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 (193331630)
Source file for this web page is alignpnt.h1. To re-create this web page, run "procH1 alignpnt".
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 4-June-2014.
Page created 17-Mar-2023 22:17:37.
Copyright © 2023 Alan Gibson.