When we have a list of interesting points in one image, we can locate matching areas in another image, making the assumption that any rotation and scaling is small. The assumption is true if the camera is hand-held but not moved much, such as frames from a video or stills intended for a panorama.
Scripts on this page assume that the version of ImageMagick in %IM7DEV% has been built with various process modules. See Process modules.
When we want to align one image to another, we start by matching points in one image with points in the other. We can use one of the 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.
We then crop a small area around each point, and search for that crop in the other image, using the technique from Searching an image.
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 of corresponding points, we will distort the second image so it registers with the first.
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 files are too large for me to upload. These are then reduced in size, and converted to JPG, for the web.
The source image. set sa_ALI_SRC=%PICTLIB%20140523\AGA_1837_g.tiff %IMG7%magick ^ %sa_ALI_SRC% ^ %WEB_SIZE% ^ sa_ALI_SRC_sm.jpg |
|
Another image. set sa_OTH_SRC=%PICTLIB%20140523\AGA_1839_g.tiff %IMG7%magick ^ %sa_OTH_SRC% ^ %WEB_SIZE% ^ sa_OTH_SRC_sm.jpg |
We find 24 points of interest in the source image 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.
Use a difference between two blurs, twoBlrDiff.bat, to find detail.
call %PICTBAT%twoBlrDiff %sa_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% 50 set SAVE_DIFF=%beOUTFILE%
We find the 24 lightest points.
24 is overkill for this method.
We should find plenty of matches with fewer points, but I choose 24 so I can compare the results with measdet.htm.
set nlDEBUG=1 call %PICTBAT%getPointsize %sa_ALI_SRC% 50 set nlPOINTSIZE=%gpPointsize% set nlSTROKEWIDTH=10 call %PICTBAT%nLightest %beOUTFILE% 24 >sa_ali_coords.lis
We look at the debug image:
%IMG7%magick ^ %nlDEBUG_FILE% ^ %WEB_SIZE% ^ sa_ali_coords_sm.jpg |
We make crops of the first image, %sa_ALI_SRC%, centred on the coordinates:
set ncDEBUG= call %PICTBAT%nCrop %sa_ALI_SRC% sa_ali_coords.lis 100 100
A list of the generated crop files is now in %ncLIST_FILE%.
We search for these crops within %sa_OTH_SRC%:
set MATCH_LIS=sa_match.lis del %MATCH_LIS% set MATCH_LIS2=sa_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 %sa_OTH_SRC% %%F if ERRORLEVEL 1 exit /B 1 echo !CROP_NUM!, !siCOMP_FLT!, !siCENT_X!, !siCENT_Y! >>%MATCH_LIS% set /A CROP_NUM+=1 )
CropNum,Score,X,Y 0, 0.110896, 5671, 3771 1, 0.117396, 6177, 3844 2, 0.129868, 6393, 2959 3, 0.0767293, 2006, 2270 4, 0.0990973, 4624, 4652 5, 0.116674, 6490, 3378 6, 0.0907304, 7197, 2646 7, 0.0943666, 2290, 250 8, 0.0648876, 2026, 2811 9, 0.121583, 5385, 3661 10, 0.111844, 3144, 3933 11, 0.0631738, 915, 2931 12, 0.0739243, 7262, 2354 13, 0.081462, 2019, 1780 14, 0.0870536, 5911, 1781 15, 0.0490783, 455, 3714 16, 0.0929437, 5746, 3247 17, 0.0641008, 2021, 1727 18, 0.0987857, 2672, 2048 19, 0.0845894, 6924, 4526 20, 0.0945779, 2555, 2825 21, 0.098023, 2269, 1971 22, 0.0671523, 2627, 1536 23, 0.0923491, 6784, 2102
These are the matches found, in order of the score, so the closest matches are at the top:
cSort /i%MATCH_LIS% /o%MATCH_LIS2% /h /kScore
CropNum,Score,X,Y 15, 0.0490783, 455, 3714 11, 0.0631738, 915, 2931 17, 0.0641008, 2021, 1727 8, 0.0648876, 2026, 2811 22, 0.0671523, 2627, 1536 12, 0.0739243, 7262, 2354 3, 0.0767293, 2006, 2270 13, 0.081462, 2019, 1780 19, 0.0845894, 6924, 4526 14, 0.0870536, 5911, 1781 6, 0.0907304, 7197, 2646 23, 0.0923491, 6784, 2102 16, 0.0929437, 5746, 3247 7, 0.0943666, 2290, 250 20, 0.0945779, 2555, 2825 21, 0.098023, 2269, 1971 18, 0.0987857, 2672, 2048 4, 0.0990973, 4624, 4652 0, 0.110896, 5671, 3771 10, 0.111844, 3144, 3933 5, 0.116674, 6490, 3378 1, 0.117396, 6177, 3844 9, 0.121583, 5385, 3661 2, 0.129868, 6393, 2959
We can markup a copy of the searched image with the locations found:
set mrCOL_X=3 set mrCOL_Y=4 set mrSTROKE=-strokewidth 10 call %PICTBAT%markRect %sa_OTH_SRC% %MATCH_LIS% 100 100 %IMG7%magick ^ %mrOUTFILE% ^ %WEB_SIZE% ^ sa_srch_marked.jpg |
By looking carefully at the full-size images, we find the following matches are correct: 0, 1, 3, 6, 8, 11, 13, 14, 15, 16, 20, 22 and 23. These are incorrect: 2, 4, 5, 7, 9, 10, 12, 17, 18, 19 and 21. Out of 24 matches, 13 are correct. Number 17 has a good score but the match is false. Number 0 has a bad score but the match is correct. The score is not a good indicator of whether the match is correct.
To automatically find the correct matches, we calculate dx, dy and r for each coordinate pair, and remove outliers with a "modified Thompson tau technique". (For details, see the Statistics page.)
cProject /isa_match.lis /osa_match3.lis /h /kScore,X,Y cHead /isa_match3.lis /h1 /x call %PICTBAT%appendLines sa_match3.lis sa_ali_coords.lis >sa_coord_pairs.lis call %PICTBAT%extendCoordPairs sa_coord_pairs.lis sa_matchMTTE.lis set rcoAPPEND_NUM=1 set rcoDEBUG_FILE=sa_rco_debug.lis del %rcoDEBUG_FILE% 2>nul call removeCsvOutliers sa_matchMTTE.lis sa_matchMTTE_good.lis 6 1 7 1 8 1
The result, written to sa_matchMTTE_good.lis, is:
0.110896,5671,3771,5271,3431,-400,-340,524.97619 , 0 0.117396,6177,3844,5769,3509,-408,-335,527.91003 , 1 0.0767293,2006,2270,1630,1884,-376,-386,538.861763 , 3 0.0907304,7197,2646,6804,2339,-393,-307,498.6963 , 6 0.0648876,2026,2811,1645,2428,-381,-383,540.231432 , 8 0.0631738,915,2931,521,2534,-394,-397,559.325487 , 11 0.081462,2019,1780,1648,1391,-371,-389,537.551858 , 13 0.0870536,5911,1781,5550,1456,-361,-325,485.74273 , 14 0.0490783,455,3714,51,3316,-404,-398,567.115509 , 15 0.0929437,5746,3247,5355,2911,-391,-336,515.535644 , 16 0.0945779,2555,2825,2177,2448,-378,-377,533.866088 , 20 0.0671523,2627,1536,2265,1155,-362,-381,525.552091 , 22 0.0923491,6784,2102,6406,1790,-378,-312,490.130595 , 23
The columns in sa_matchMTTE_good.lis are: score, xB,yB, xA,yA, dx, dy, t, point_num.
This has accepted exactly those pairs we have found visually to be good, and rejected those we found to be bad. The resulting list is perfect.
The debug output sent to sa_rco_debug.lis is:
removeCsvOutliers: Column=6 IsAbs=1 removeOutliers: removed 18 removeOutliers: removed 21 removeOutliers: removed 19 removeOutliers: removed 10 removeOutliers: removed 7 removeOutliers: removed 2 removeOutliers: removed 5 removeOutliers: removed 12 removeOutliers: removed 17 removeCsvOutliers: Column=7 IsAbs=1 removeOutliers: removed 9 removeOutliers: removed 4 removeCsvOutliers: Column=8 IsAbs=1 removeCsvOutliers: nVAL=24
Aside:
To align images accurately, we must eliminate all bad matches. An algorithm may also eliminate good matches. (See example later on this page.) It is better to err on the side of over-elimination rather than under-elimination. Previous (unpublished) versions of my scripts removed samples outside the range mean ± k * standard_deviation where 1.0 < k < 2.0. This needed a good choice of k, and was over-conservative.
Finding outliers of dx, dy and r works well because the sample has a fairly constant linear displacement across the entire image. If the camera had between twisted significantly around the z-axis, from a landscape format towards a portrait format, it wouldn't have worked.
A possible solution is to read the verbose distort parameters and use them to calculate the error for each control point, then eliminate control points based on outlier errors.
We have successfully matched small areas in one image with small areas from another. The output from the process is a list of coordinate pairs: each (x,y) coordinate from one image matches an (x,y) coordinate from the other image.
For convenience, we put much of the above into a script, alignArea.bat. This takes two images and a CSV list of coordinates of points in one image, and finds corresponding points in a second image. The list can be used for a perspective (or affine) distortiontion from one image to the other.
call %PICTBAT%alignArea ^ %PICTLIB%20140523\AGA_1837_g.tiff ^ %PICTLIB%20140523\AGA_1839_g.tiff ^ sa_ali_coords.lis type %aaCOORDS_CSV%
5671,3771,5271,3431,-400,-340,524.97619 , 0 6177,3844,5769,3509,-408,-335,527.91003 , 1 2006,2270,1630,1884,-376,-386,538.861763 , 3 7197,2646,6804,2339,-393,-307,498.6963 , 6 2026,2811,1645,2428,-381,-383,540.231432 , 8 915,2931,521,2534,-394,-397,559.325487 , 11 2019,1780,1648,1391,-371,-389,537.551858 , 13 5911,1781,5550,1456,-361,-325,485.74273 , 14 455,3714,51,3316,-404,-398,567.115509 , 15 5746,3247,5355,2911,-391,-336,515.535644 , 16 2555,2825,2177,2448,-378,-377,533.866088 , 20 2627,1536,2265,1155,-362,-381,525.552091 , 22 6784,2102,6406,1790,-378,-312,490.130595 , 23
This is a complex subject, and deserves a separate page.
ImageMagick has three simple but effective methods of using a list of coordinate pairs to transform one image geometrically to match another. The methods are:
When a rectilinear camera is used to take multiple photographs from the same position, the perspective distortion is the correct one to use.
Shepards looks attractive, but image points that are not in the small list of coordinate pairs will be interpolated using all the control points. Another method divides the image into triangles and displaces according the distance from only three points. This is more complex, and easiest written in C (unpublished).
For convenience, we read the coordinate pairs into an environment variable.
set COORD_PAIR_LIST= for /F "tokens=2-5 delims=, " %%A in (sa_matchMTTE_good.lis) do ( set COORD_PAIR_LIST=!COORD_PAIR_LIST! %%A,%%B,%%C,%%D ) set COORD_PAIR_LIST
COORD_PAIR_LIST= 5671,3771,5271,3431 6177,3844,5769,3509 2006,2270,1630,1884 7197,2646,6804,2339 2026,2811,1645,2428 915,2931,521,2534 2019,1780,1648,1391 5911,1781,5550,1456 455,3714,51,3316 5746,3247,5355,2911 2555,2825,2177,2448 2627,1536,2265,1155 6784,2102,6406,1790
We use the coordinate-pair list for an affine transformation. -verbose sends the six affine parameters to stderr.
%IMG7%magick ^ %sa_OTH_SRC% ^ -verbose ^ -virtual-pixel None ^ +distort Affine "%COORD_PAIR_LIST%" ^ -write sa_xform_a.png ^ %WEB_SIZE% ^ sa_xform_a_sm.jpg
We show the parameters, just for interest:
Affine projection: -distort AffineProjection \ '0.999683,0.0137551,-0.018084,0.999078,-334.116,-409.422' Equivalent scale, rotation(deg), translation: 0.999777,0.788309,-334.116,-409.422 Affine distort, FX equivalent: -size 7467x5023 -page -424-410 xc: +insert \ -fx 'ii=i+page.x+0.5; jj=j+page.y+0.5; xx=+1.00007*ii +0.018102*jj +341.55; yy=-0.0137687*ii +1.00067*jj +405.097; v.p{xx-v.page.x-0.5,yy-v.page.y-0.5}' \
Aside: If we wanted just the parameters without any image processing, we could:
%IMG7%magick ^ xc: ^ -verbose ^ -virtual-pixel None ^ +distort Affine "%COORD_PAIR_LIST%" ^ NULL: 2>somewhere.lis
We make three images for the web:
%IMG7%magick ^ %sa_ALI_SRC% ^ ( sa_xform_a.png -channel A -evaluate Multiply 0.5 ) ^ -layers merge +repage ^ -write sa_xform_comp_a.png ^ ( +clone -crop 500x500+510+4526 -write sa_xform_comp_a_cr.jpg +delete ) ^ %WEB_SIZE% ^ sa_xform_comp_a_sm.jpg
We show the distorted image (reduced in size for the web), then that image 50% transparent and merged over the first image, and finally a 100% crop of the merge.
The 100% crop shows that the alignment from Affine is approximately correct, but not exact.
%IMG7%magick ^ %sa_OTH_SRC% ^ -verbose ^ -virtual-pixel None ^ +distort Perspective "%COORD_PAIR_LIST%" ^ -write sa_xform_p.png ^ %WEB_SIZE% ^ sa_xform_p_sm.jpg
Perspective Projection: -distort PerspectiveProjection \ '1.02579, -0.00475227, -398.082, 0.0199438, 1.02372, -457.416, 2.37374e-06, 2.98293e-06' Perspective Distort, FX Equivelent: -size 7464x5042 -page -416-458 xc: +insert \ -fx 'ii=i+page.x+0.5; jj=j+page.y+0.5; rr=-2.25721e-06*ii -2.92431e-06*jj + 1; xx=(+0.976073*ii +0.00339439*jj +390.109)/rr; yy=(-0.0200242*ii +0.977644*jj +439.219)/rr; rr>0 ? v.p{xx-v.page.x-0.5,yy-v.page.y-0.5} : blue' \
%IMG7%magick ^ %sa_ALI_SRC% ^ ( sa_xform_p.png -channel A -evaluate Multiply 0.5 ) ^ -layers merge +repage ^ -write sa_xform_comp_p.png ^ ( +clone -crop 500x500+510+4526 -write sa_xform_comp_p_cr.jpg +delete ) ^ %WEB_SIZE% ^ sa_xform_comp_p_sm.jpg
The 100% crop shows that the alignment from Perspective is exactly correct.
%IMG7%magick ^ %sa_OTH_SRC% ^ -verbose ^ -virtual-pixel None ^ +distort Shepards "%COORD_PAIR_LIST%" ^ -write sa_xform_s.png ^ %WEB_SIZE% ^ sa_xform_s_sm.jpg
%IMG7%magick ^ %sa_ALI_SRC% ^ ( sa_xform_s.png -channel A -evaluate Multiply 0.5 ) ^ -layers merge +repage ^ -write sa_xform_comp_s.png ^ ( +clone -crop 500x500+110+4126 -write sa_xform_comp_s_cr.jpg +delete ) ^ %WEB_SIZE% ^ sa_xform_comp_s_sm.jpg
The 100% crop shows that the alignment from Shepards is worse then the affine transformation at this location, though it is exactly correct at each control point.
This isn't (yet) part of the standard IM distribution.
goto skipTri %IMDEV%convert ^ %sa_OTH_SRC% ^ -verbose ^ -virtual-pixel None ^ -define triangulate:outside=clamp ^ +distort Triangulate "%COORD_PAIR_LIST%" ^ -write sa_xform_t.png ^ %WEB_SIZE% ^ sa_xform_t_sm.jpg
@sa_xform_t.lis
%IMG7%magick ^ %sa_ALI_SRC% ^ ( sa_xform_t.png -channel A -evaluate Multiply 0.5 ) ^ -layers merge +repage ^ -write sa_xform_comp_t.png ^ ( +clone -crop 500x500+110+4126 -write sa_xform_comp_t_cr.jpg +delete ) ^ %WEB_SIZE% ^ sa_xform_comp_t_sm.jpg :skipTri
The 100% crop shows that the alignment from Triangulate is worse then the affine transformation at this location, though it is exactly correct at each control point.
Some of the features found on the first image were close to the bottom or right edge, so aren't on the second image, so the matches were certain to be false. We can treat the first result as an approximation, and ensure we don't find any features in non-overlapping areas. Then we repeat the entire process.
Above, we blackened the edge of an image to avoid picking points there. We can take the found result to make a mask for more blackening. (We want to blacken 50 pixels more. The simple, obvious and elegant method for doing this is by eroding the white with "-morphology erode rectangle:100x100". Sadly, it is also agonizingly slow. (I suppose it performs 100x100 operations per input pixel.) Instead, we use "-morphology Distance Chebyshev:1,1 -threshold 50".)
%IMG7%magick ^ %sa_OTH_SRC% ^ -fill White -colorize 100 ^ -virtual-pixel Black -distort Affine "%COORD_PAIR_LIST%" ^ -morphology Distance Chebyshev:1,1 -threshold 50 ^ -write sa_xform_maskXX.miff ^ %WEB_SIZE% ^ sa_xform_maskXX_sm.png BUG: sa_xform_maskXX.miff is black |
|
%IMG7%magick ^ %sa_OTH_SRC% ^ -fill White -colorize 100 ^ sa_x.miff call %PICTBAT%blackEdge sa_x.miff 50 . sa_x2.miff %IMG7%magick ^ sa_x2.miff ^ -virtual-pixel Black -distort Affine "%COORD_PAIR_LIST%" ^ -write sa_xform_mask.miff ^ %WEB_SIZE% ^ sa_xform_mask_sm.png BUG: sa_xform_mask.miff is black |
|
%IMG7%magick ^ %SAVE_DIFF% ^ sa_xform_mask.miff ^ -compose Darken -composite ^ -write sa_xform_diff.miff ^ %WEB_SIZE% ^ sa_xform_diff_sm.jpg |
|
Note: the following nLightest is massively slow. Why? Solution: miff. BUG: sa_xform_diff.miff is black call %PICTBAT%nLightest sa_xform_diff.miff 24 %IMG7%magick ^ %nlDEBUG_FILE% ^ %WEB_SIZE% ^ sa_xf_coords_sm.jpg |
|
Make crops from the coordinates. set ncDEBUG= call %PICTBAT%nCrop %sa_ALI_SRC% sa_ali_coordsB.lis 100 100 |
We search for the crops using the method as above.
set MATCH_LIS=sa_matchB.lis del %MATCH_LIS% 2>nul set MATCH_LIS2=sa_match2B.lis echo CropNum,Score,X,Y >%MATCH_LIS% set CROP_NUM=0 for /F %%F in (%ncLIST_FILE%) do ( echo %%F call %PICTBAT%srchImg %sa_OTH_SRC% %%F if ERRORLEVEL 1 exit /B 1 echo !CROP_NUM!, !siCOMP_FLT!, !siCENT_X!, !siCENT_Y! >>%MATCH_LIS% set /A CROP_NUM+=1 )
CropNum,Score,X,Y 0, 0.110896, 5671, 3771 1, 0.117396, 6177, 3844 2, 0.129868, 6393, 2959 3, 0.0767293, 2006, 2270 4, 0.0907304, 7197, 2646 5, 0.0943666, 2290, 250 6, 0.0648876, 2026, 2811 7, 0.121583, 5385, 3661 8, 0.0631738, 915, 2931 9, 0.081544, 2019, 1781 10, 0.0870536, 5911, 1781 11, 0.0490783, 455, 3714 12, 0.0700384, 7106, 2059 13, 0.0929437, 5746, 3247 14, 0.0644039, 2021, 1727 15, 0.0845894, 6924, 4526 16, 0.0945779, 2555, 2825 17, 0.0671523, 2627, 1536 18, 0.0853236, 1411, 2953 19, 0.104048, 3217, 2604 20, 0.0529905, 4790, 874 21, 0.101205, 6577, 3315 22, 0.122236, 4547, 2642 23, 0.0728633, 3113, 2573
These are the matches found, in order of the score, so the closest matches are at the top.
cSort /i%MATCH_LIS% /o%MATCH_LIS2% /h /kScore
CropNum,Score,X,Y 11, 0.0490783, 455, 3714 20, 0.0529905, 4790, 874 8, 0.0631738, 915, 2931 14, 0.0644039, 2021, 1727 6, 0.0648876, 2026, 2811 17, 0.0671523, 2627, 1536 12, 0.0700384, 7106, 2059 23, 0.0728633, 3113, 2573 3, 0.0767293, 2006, 2270 9, 0.081544, 2019, 1781 15, 0.0845894, 6924, 4526 18, 0.0853236, 1411, 2953 10, 0.0870536, 5911, 1781 4, 0.0907304, 7197, 2646 13, 0.0929437, 5746, 3247 5, 0.0943666, 2290, 250 16, 0.0945779, 2555, 2825 21, 0.101205, 6577, 3315 19, 0.104048, 3217, 2604 0, 0.110896, 5671, 3771 1, 0.117396, 6177, 3844 7, 0.121583, 5385, 3661 22, 0.122236, 4547, 2642 2, 0.129868, 6393, 2959
We can markup a copy of the searched image with the locations found.
set mrCOL_X=3 set mrCOL_Y=4 call %PICTBAT%markRect %sa_OTH_SRC% sa_matchB.lis 100 100 %IMG7%magick ^ %mrOUTFILE% ^ %WEB_SIZE% ^ sa_srch_markedB.jpg |
The following matches are correct: 0, 1, 3, 4, 6, 8, 9, 10, 11, 12, 13, 16, 17, 18, 20, 21 and 23. The following matches are incorrect: 2, 5, 7, 14, 15, 19 and 22. By using a mask from the first approximation, we have increased the hit-rate from 13/24 to 17/24.
cProject /isa_matchB.lis /osa_match3B.lis /h /kScore,X,Y cHead /isa_match3B.lis /h1 /x call %PICTBAT%appendLines sa_match3B.lis sa_ali_coordsB.lis >sa_coord_pairsB.lis
Use "modified Thompson tau technique" to remove outliers.
call %PICTBAT%extendCoordPairs sa_coord_pairsB.lis sa_matchMTTEB.lis set rcoAPPEND_NUM=1 set rcoDEBUG_FILE=sa_rco_debugB.lis del %rcoDEBUG_FILE% 2>nul call removeCsvOutliers sa_matchMTTEB.lis sa_matchMTTE_goodB.lis 6 1 7 1 8 1
0.110896,5671,3771,5271,3431,-400,-340,524.97619 , 0 0.117396,6177,3844,5769,3509,-408,-335,527.91003 , 1 0.0767293,2006,2270,1630,1884,-376,-386,538.861763 , 3 0.0907304,7197,2646,6804,2339,-393,-307,498.6963 , 4 0.0648876,2026,2811,1645,2428,-381,-383,540.231432 , 6 0.0631738,915,2931,521,2534,-394,-397,559.325487 , 8 0.081544,2019,1781,1648,1392,-371,-389,537.551858 , 9 0.0870536,5911,1781,5550,1456,-361,-325,485.74273 , 10 0.0490783,455,3714,51,3316,-404,-398,567.115509 , 11 0.0700384,7106,2059,6727,1754,-379,-305,486.483299 , 12 0.0929437,5746,3247,5355,2911,-391,-336,515.535644 , 13 0.0945779,2555,2825,2177,2448,-378,-377,533.866088 , 16 0.0671523,2627,1536,2265,1155,-362,-381,525.552091 , 17 0.0853236,1411,2953,1022,2562,-389,-391,551.545102 , 18 0.101205,6577,3315,6175,2992,-402,-323,515.686921 , 21 0.0728633,3113,2573,2740,2204,-373,-369,524.680855 , 23
This has accepted almost those pairs we have found visually to be good (it incorrectly rejected 21), and rejected all those we found to be bad. The resulting list is nearly perfect.
The debug output sent to sa_rco_debugB.lis is:
removeCsvOutliers: Column=6 IsAbs=1 removeOutliers: removed 15 removeOutliers: removed 22 removeOutliers: removed 5 removeOutliers: removed 19 removeOutliers: removed 2 removeOutliers: removed 20 removeOutliers: removed 14 removeCsvOutliers: Column=7 IsAbs=1 removeOutliers: removed 7 removeCsvOutliers: Column=8 IsAbs=1 removeCsvOutliers: nVAL=24
With these new coordinate pairs, make a perspective distortion:
set COORD_PAIR_LIST2= for /F "tokens=2-5 delims=, " %%A in (sa_matchMTTE_good.lis) do ( set COORD_PAIR_LIST2=!COORD_PAIR_LIST2! %%A,%%B,%%C,%%D ) %IMG7%magick ^ %sa_OTH_SRC% ^ -verbose ^ -virtual-pixel None ^ +distort Perspective "%COORD_PAIR_LIST2%" ^ -write sa_xform_p_B.png ^ %WEB_SIZE% ^ sa_xform_p_B_sm.jpg
Perspective Projection: -distort PerspectiveProjection \ '1.02579, -0.00475227, -398.082, 0.0199438, 1.02372, -457.416, 2.37374e-06, 2.98293e-06' Perspective Distort, FX Equivelent: -size 7464x5042 -page -416-458 xc: +insert \ -fx 'ii=i+page.x+0.5; jj=j+page.y+0.5; rr=-2.25721e-06*ii -2.92431e-06*jj + 1; xx=(+0.976073*ii +0.00339439*jj +390.109)/rr; yy=(-0.0200242*ii +0.977644*jj +439.219)/rr; rr>0 ? v.p{xx-v.page.x-0.5,yy-v.page.y-0.5} : blue' \
%IMG7%magick ^ %sa_ALI_SRC% ^ ( sa_xform_p_B.png -channel A -evaluate Multiply 0.5 ) ^ -layers merge +repage ^ -write sa_xform_comp_p_B.png ^ ( +clone -crop 500x500+510+4526 -write sa_xform_comp_p_cr_B.jpg +delete ) ^ %WEB_SIZE% ^ sa_xform_comp_p_B_sm.jpg
This has created various files in the same directory as the source files.
del %tbdOUTFILE% del %beOUTFILE% del %mrOUTFILE% del sa_xform_*.miff rem Don't delete sa_xform_mask_sm.png del sa_xform_comp*.png del sa_xform_a*.png del sa_xform_c*.png del sa_xform_d*.png del sa_xform_p*.png del sa_xform_s*.png del sa_xform_t*.png
We don't normally want the debugging images or text, so the process boils down to:
set nlDEBUG= set ncDEBUG= set rcoAPPEND_NUM= set rcoDEBUG_FILE= call %PICTBAT%twoBlrDiff %sa_ALI_SRC% call %PICTBAT%blackEdge %tbdOUTFILE% 50 call %PICTBAT%nLightest %beOUTFILE% 24 call %PICTBAT%nCrop %sa_ALI_SRC% sa_ali_coords.lis 100 100 set MATCH_LIS=sa_match.lis del %MATCH_LIS% set CROP_NUM=0 for /F %%F in (%ncLIST_FILE%) do ( echo %%F call %PICTBAT%srchImg %sa_OTH_SRC% %%F if ERRORLEVEL 1 exit /B 1 echo !siCOMP_FLT!, !siCENT_X!, !siCENT_Y! >>%MATCH_LIS% set /A CROP_NUM+=1 ) call %PICTBAT%appendLines %MATCH_LIS% sa_ali_coords.lis >sa_coord_pairs.lis call %PICTBAT%extendCoordPairs sa_coord_pairs.lis sa_matchMTTE.lis call removeCsvOutliers sa_matchMTTE.lis sa_matchMTTE_good.lis 6 1 7 1 8 1 del %tbdOUTFILE% del %beOUTFILE%
For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.
Some commands on this page use utility programs such as cProject.exe and cHead.exe. I do not publish source or binaries of these.
rem %1 is image A, %2 is image B, rem %3 is CSV file with list of coords from image A. rem rem Returns (affine or perspective transformation from B to A?) rem list of coordinate pairs xA,yA,xB,yB: rem Returns environment variables: rem aaCOORDS list of coords rem aaCOORDS_CSV name of CSV file containing the coords @rem @rem Updated: @rem 22-August-2022 Upgraded for IM v7. @rem @if "%3"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave call %PICTBAT%setInOut %1 aa if "%aaDIM%"=="" set aaDIM=100 if not exist %1 exit /B 1 if not exist %2 exit /B 1 if not exist %3 exit /B 1 set SRC_A=%1 set SRC_B=%2 set ALI_COORDS=%3 set ncDEBUG= call %PICTBAT%nCrop %SRC_A% %ALI_COORDS% %aaDIM% %aaDIM% if ERRORLEVEL 1 exit /B 1 type %ncLIST_FILE% set MATCH_LIS=%TEMP%\aa_match.lis del %MATCH_LIS% 2>nul set MATCH_LIS2=%TEMP%\aa_match2.lis set TMP_B=%BASENAME%_aa_tmpb.miff %IMG7%magick %SRC_B% +repage %TMP_B% rem echo %0: CropNum,Score,X,Y >%MATCH_LIS% set CROP_NUM=0 for /F %%F in (%ncLIST_FILE%) do ( echo %0: %%F call %PICTBAT%srchImg %TMP_B% %%F if ERRORLEVEL 1 exit /B 1 echo !siCENT_X!,!siCENT_Y! >>%MATCH_LIS% set /A CROP_NUM+=1 ) rem cProject /i%MATCH_LIS% /oaa_match3.lis /h /kScore,X,Y rem cHead /iaa_match3.lis /h1 /x set COORD_PAIRS=%TEMP%\aa_coord_pairs.lis call %PICTBAT%appendLines %MATCH_LIS% %ALI_COORDS% >%COORD_PAIRS% rem %COORD_PAIRS% has: xB,yB,xA,yA set MATCH_MTTE=%TEMP%\aa_matchMTTE.lis rem call %PICTBAT%extendCoordPairs %COORD_PAIRS% %MATCH_MTTE% rem From CSV file %COORD_PAIRS%, assumed to contain X0,Y0,X1,Y1 rem writes %MATCH_MTTE% containing X0,Y0,X1,Y1,dX,dY,r rem where: rem dX = X1 - X0 rem dY = Y1 - Y0 rem r = sqrt (dX^2 + dY^2) rem rem Files have no headers. del %MATCH_MTTE% 2>nul set sCOORD= for /F "tokens=1-5 delims=, " %%A in (%COORD_PAIRS%) do ( set /A dx=%%C-%%A set /A dy=%%D-%%B set /A dx2=!dx!*!dx! set /A dy2=!dy!*!dy! set /A r2=!dx2!+!dy2! for /F "usebackq" %%L in (`%IMG7%magick identify ^ -precision 9 ^ -format "r=%%[fx:sqrt(!r2!)]" ^ xc:`) do set %%L echo %%A,%%B,%%C,%%D,!dx!,!dy!,!r! >>%MATCH_MTTE% ) set rcoAPPEND_NUM=1 set rcoDEBUG_FILE=aa_rco_debug.lis del %rcoDEBUG_FILE% 2>nul call removeCsvOutliers %MATCH_MTTE% aa_matchMTTE_good.lis 5 1 6 1 7 1 if ERRORLEVEL 1 exit /B 1 rem type aa_matchMTTE_good.lis rem Read coords into env var. set sCOORD= for /F "tokens=1-5 delims=, " %%A in (aa_matchMTTE_good.lis) do ( set sCOORD=!sCOORD! %%A,%%B,%%C,%%D ) @call echoRestore @endlocal & set aaCOORDS=%sCOORD%& set aaCOORDS_CSV=aa_matchMTTE_good.lis echo %0: Written env var aaCOORDS and file aaCOORDS_CSV [%aaCOORDS_CSV%]
@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
rem %1 is image, %2 is height in pixels, sets gpPointsize to height in points. call %PICTBAT%getDpi %1 if "%gdDpi%"=="0" ( set gpPointsize=%2 ) else ( for /F "usebackq" %%L in (`%IMG7%magick identify -format "gpPointsize=%%[fx:%2*%gdDpi%/72]" xc:`) do set %%L )
for /F "usebackq" %%L in (`%IMG7%magick identify -format "gdDpi=%%x\ngdUnits=%%U" %1`) do set %%L if /I "%gdUnits%"=="PixelsPerCentimeter" ( for /F "usebackq" %%L in (`%IMG7%magick identify -format "gdDpi=%%[fx:%gdDpi%*2.54]" xc:`) do set %%L )
@rem From image %1, finds (%2) lightest points. @rem @rem After each point is found, @rem blacks out pixels within radius (r) of that point @rem where r = min(width,height) * %3/100 @rem %3 defaults to 10 (percent). @rem @rem Returns number of points found. Could be < n, or even zero (?). @rem @rem Also uses: @rem nlDEBUG if 1, creates debugging image. @rem nlPOINTSIZE optional, pointsize for debug images. @rem nlSTROKEWIDTH for debug. @rem nlONLY_WHITE if 1, doesn't auto-level, @rem so finds only points that are exactly white. @rem @rem Returns: @rem nl_nFound number of points found, integer >= 0 @rem echos list of coordinates. @rem @rem Updated: @rem 24-May-2016 v7 needs -channel RGB for -auto-level. @rem 7-May-2017 "+antialias" the circles. @rem 2-August-2022 for IM v7 magick. @rem @if "%1"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave call %PICTBAT%setInOut %1 nl for /F "usebackq" %%L in (`cygpath %TEMP%`) do set CYGTEMP=%%L set TMPFILE=%TEMP%\%~n1_%sioCODE%.miff set CYGTMPFILE=%CYGTEMP%\%~n1_%sioCODE%.miff set LISTFILE=%BASENAME%_%sioCODE%.lis set TMPDEBUGFILE=%BASENAME%_%sioCODE%_dbg.miff set DEBUGFILE=%BASENAME%_%sioCODE%_dbg%EXT% set DEBUGDRAW=%TEMP%\%~n1_%sioCODE%_dbgdrw.txt del %DEBUGDRAW% 2>nul if "%nlPOINTSIZE%"=="" set nlPOINTSIZE=20 if "%nlSTROKEWIDTH%"=="" set nlSTROKEWIDTH=1 set MAX_FIND=%2 if "%MAX_FIND%"=="" set MAX_FIND=10 set PC_RAD=%3 if "%PC_RAD%"=="" set PC_RAD=10 set AUTOLEV=-channel RGB -auto-level +channel if "%nlONLY_WHITE%"=="1" set AUTOLEV= for /F "usebackq" %%L in (`%IMG7%magick ^ %INFILE% ^ -format "PIX_RAD=%%[fx:int(min(w,h)*%PC_RAD%/100+0.5)]" ^ info:`) do set %%L %IMG7%magick %INFILE% -colorspace Gray %AUTOLEV% %TMPFILE% if "%nlDEBUG%"=="1" %IMG7%magick %INFILE% %TMPDEBUGFILE% set /A nFound=0 :loop set MAX= set whiteX= for /F "usebackq tokens=1-3 delims=:, " %%W ^ in (`%IM7DEV%magick ^ %TMPFILE% ^ -process onewhite ^ NULL: 2^>^&1`) ^ do ( if "%%W"=="onewhite" ( set MAX=%%W set whiteX=%%X set whiteY=%%Y set /A whiteX2=%%X+%PIX_RAD% ) ) if "!MAX!"=="onewhite" if "!whiteX!" neq "none" ( %IMG7%magick ^ %TMPFILE% ^ +antialias -fill #000 ^ -draw "circle %whiteX% %whiteY% %whiteX2% %whiteY%" ^ %AUTOLEV% ^ %TMPFILE% if "%nlDEBUG%"=="1" ( ( echo fill None stroke #f00 circle %whiteX%,%whiteY%,%whiteX2%,%whiteY% echo fill #f00 stroke None text %whiteX%,%whiteY% '!nFound!' ) >>%DEBUGDRAW% ) set /A nFound+=1 echo %whiteX%,%whiteY% if !nFound! LSS %MAX_FIND% goto loop ) if "%nlDEBUG%"=="1" if exist %DEBUGDRAW% %IMG7%magick ^ %INFILE% ^ -strokewidth %nlSTROKEWIDTH% ^ -pointsize %nlPOINTSIZE% ^ -draw @%DEBUGDRAW% ^ %DEBUGFILE% rem echo %0: nFound=%nFound% call echoRestore @endlocal & set nl_nFound=%nFound%& set nlDEBUG_FILE=%DEBUGFILE%
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 ncREPAGE if 0, does not "+repage" each crop. @rem ncEXT @rem @rem Returns: @rem ncLIST_FILE name of created file with list of names of crop files @rem @rem See also v7 version nCrop7.bat. @rem @rem Updated: @rem 13-April-2018 added ncREPAGE @rem 14-August-2020 for IM v7. @rem @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 echo %0: %1 %2 %3 %4 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 if "%ncREPAGE%"=="0" ( set sREPAGE= ) else ( set sREPAGE=+repage ) set CROP_FILE=%ncAtBASE%_crops.scr 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 echo %0: text files: %CROP_FILE% %RECT_FILE% %LIST_FILE% set nCrop=0 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=%ncAtBASE%_!nCrop!%ncEXT% echo ^( +clone -crop %3x%4+!dx!+!dy! %sREPAGE% -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 ) ) echo -exit >>%CROP_FILE% if %nCrop%==0 ( %0: coordinates text file [%2] seems to be empty. exit /B 1 ) %IMG7%magick ^ %INFILE% ^ -script %CROP_FILE% if ERRORLEVEL 1 ( echo %0: script CROP_FILE [%CROP_FILE%] failed exit /B 1 ) if "%ncDEBUG%"=="1" ( %IMG7%magick ^ %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%
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 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 %5 output file @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 "-strokewidth 10" 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 mrNhead number of lines on header, to skip @rem @rem Updated: @rem 10-December-2017 Stroke has defaults. @rem 26-August-2018 Fixed bug in skip setting. @rem 14-August-2020 for IM v7. @rem @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 "%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 if not "%5"=="" if not "%5"=="." set OUTFILE=%5 set sSKIP= if not "%mrNhead%"=="" if not "%mrNhead%"=="0" ( set sSKIP=skip=%mrNhead% ) 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% %sSKIP% 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 ERRORLEVEL 1 exit /B 1 if "%sRECT%"=="" exit /B 1 if "%mrPIX_HT%"=="0" ( set sTEXT= ) else ( set sTEXT=%mrTEXT% -draw "%sNUMB%" ) %IMG7%magick ^ %INFILE% ^ -stroke #f00 -strokewidth 1 -fill None ^ %mrSTROKE% ^ -draw "%sRECT%" ^ %sTEXT% ^ %OUTFILE% if ERRORLEVEL 1 exit /B 1 @call echoRestore @endlocal & set mrOUTFILE=%OUTFILE%
rem From CSV file %1, assumed to contain Score,X0,Y0,X1,Y1 rem writes %2 containing Score,X0,Y0,X1,Y1,dX,dY,r rem where: rem dX = X1 - X0 rem dY = Y1 - Y0 rem r = sqrt (dX^2 + dY^2) rem rem Files have no headers. @if "%2"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave set INFILE=%1 set OUTFILE=%2 if not exist %INFILE% ( echo %0: can't find %INFILE% exit /B 1 ) del %OUTFILE% 2>nul for /F "tokens=1-5 delims=, " %%A in (%INFILE%) do ( set /A dx=%%D-%%B set /A dy=%%E-%%C set /A dx2=!dx!*!dx! set /A dy2=!dy!*!dy! set /A r2=!dx2!+!dy2! for /F "usebackq" %%L in (`%IM%identify ^ -precision 9 ^ -format "r=%%[fx:sqrt(!r2!)]" ^ xc:`) do set %%L echo %%A,%%B,%%C,%%D,%%E,!dx!,!dy!,!r! >>%OUTFILE% ) @call echoRestore @endlocal
@rem For text files, appends each line of %2 to end of %1, writing output to stdout. @rem Inserts alSEP then a space character between each input pair. @rem Returns number of lines in alOUTNUM @if "%2"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal @call echoOffSave set NumA=0 for /F "tokens=*" %%L in (%1) do ( set lineA_!NumA!=%%L set /A NumA+=1 ) set NumB=0 for /F "tokens=*" %%L in (%2) do ( set lineB_!NumB!=%%L set /A NumB+=1 ) set OutNum=%NumA% if %OutNum% LSS %NumB% set OutNum=%NumB% set /A nLast=%OutNum%-1 for /L %%i in (0,1,%nLast%) do echo.!lineA_%%i!%alSEP% !lineB_%%i! call echoRestore @endlocal & set alOUTNUM=%OutNum%
rem Difference of two blurs, resulting in monochrome RMS. @rem @rem %2 is first (smallest) blur sigma in pixels. @rem %3 is second (largest) blur sigma in pixels. @rem %4, if given, is final blur sigma in pixels. @rem %5, if given, is output filename. @rem @rem Also uses: @rem tbdAUTO if 0, doesn't "-auto-level -auto-gamma" @rem @rem See also *BlrDiff. @rem @rem Updated: @rem 2-August-2022 for IM v7 magick. @rem @if "%1"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave call %PICTBAT%setInOut %1 2bd set BLUR_SIG1=%2 if "%BLUR_SIG1%"=="." set BLUR_SIG1= if "%BLUR_SIG1%"=="" set BLUR_SIG1=4 set BLUR_SIG2=%3 if "%BLUR_SIG2%"=="." set BLUR_SIG2= if "%BLUR_SIG2%"=="" set BLUR_SIG2=6 if "%4"=="" ( set FINAL_BLUR= ) else ( if not "%4"=="." set FINAL_BLUR=-blur 0x%4 ) if not "%5"=="" set OUTFILE=%5 if "%tbdAUTO%"=="0" ( set AUTO= ) else ( set AUTO=-auto-level -auto-gamma ) %IMG7%magick ^ %INFILE% ^ ^( -clone 0 -blur 0x%BLUR_SIG1% ^) ^ ^( -clone 0 -blur 0x%BLUR_SIG2% ^) ^ -delete 0 ^ -compose Difference -composite ^ -grayscale RMS ^ %FINAL_BLUR% ^ %AUTO% ^ %OUTFILE% call echoRestore @endlocal & set tbdOUTFILE=%OUTFILE%
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 simpalign.h1. To re-create this web page, run "procH1 simpalign".
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 29-May-2014.
Page created 29-Aug-2022 09:32:58.
Copyright © 2022 Alan Gibson.