Page 1 of 3
Batch autocrop images to fixed size?
Posted: 2018-04-11T21:57:18-07:00
by Karyudo
I'd like to deskew and auto-crop several thousand images of postal covers on a black background. Ideally, I'd want all the processed output images to be the same pixel dimensions.
The deskewing I've figured out from other threads:
Code: Select all
magick convert g82217.jpg -deskew 40% g82217_deskew.jpg
works perfectly.
The wrinkle is the cropping to a fixed size, where the portion of the image I'm interested varies quite a bit within the black background "borders" between images.
Is it possible to somehow identify the area of interest, and then "best fit" a constant cropping size to each deskewed image? Thanks!
(I'm on Win10, command line, ImageMagick-7.0.7-28-Q16-x64-dll.)
Re: Batch autocrop images to fixed size?
Posted: 2018-04-11T23:07:46-07:00
by snibgo
Karyudo wrote:Is it possible to somehow identify the area of interest, and then "best fit" a constant cropping size to each deskewed image? Thanks!
How do you define "area of interest"? You might define an area manually for each image: the width, height, x-offset and t-offset. Or you might simply trim off the black background.
On the other hand, I've written a BAT script that automatically finds the area of most detail. See my page
Crop to detail.
Re: Batch autocrop images to fixed size?
Posted: 2018-04-12T09:48:31-07:00
by fmw42
Please show an example image. If you have a large black background, then you can use -fuzz XX% -trim +repage to trim the image to remove the black background and have only the stamp part left behind. If you want the result to be the same size after the crop, then use -backgroundcolor black -gravity center -extent WxH to add black back to the size you want.
See
https://www.imagemagick.org/Usage/crop/#trim
https://www.imagemagick.org/Usage/crop/#extent
Re: Batch autocrop images to fixed size?
Posted: 2018-04-12T20:22:13-07:00
by Karyudo
Here are a couple of examples that I processed manually:
Original files:
https://www.dropbox.com/s/2i052ek34f0v5 ... l.jpg?dl=0
https://www.dropbox.com/s/ch1e0u70q8umg ... l.jpg?dl=0
Deskewed using IM:
https://www.dropbox.com/s/nuihjr5520fjw ... w.jpg?dl=0
https://www.dropbox.com/s/znfbifcva00na ... w.jpg?dl=0
Manually-placed, fixed-size bounding box showing where the cropping should go:
https://www.dropbox.com/s/d5xa039e8zbbb ... x.jpg?dl=0
https://www.dropbox.com/s/dnukib967voo5 ... x.jpg?dl=0
Cropped to final fixed size (1120 x 660 in this case):
https://www.dropbox.com/s/l25n7y1x5zlbg ... 0.jpg?dl=0
https://www.dropbox.com/s/zwlxrmhdf7ogz ... 0.jpg?dl=0
I'll also take a good look at the -gravity and -extent parameters. If they do what they sound like they'll do, I'll probably be in business! Then all I'll have to do is figure out how to process batches.
(Huh. Dropbox sucks.)
Re: Batch autocrop images to fixed size?
Posted: 2018-04-12T21:37:00-07:00
by fmw42
It may have been an issue with the img tag and the spaces in your file names that were HTLM encoded. I removed the img tags and made them simple links, which seems to make them accessible. You could try to rename your file without spaces and then post again with the img tags if you want.
Try these commands. But the issue is that your background is not a constant color, but has texture in it. That makes it hard to trim the background.
Code: Select all
magick Sample1.jpeg -background black -deskew 40% -fuzz 20% -trim +repage -gravity center -extent 1120x660 result1.jpg
magick Sample2.jpeg -background black -deskew 40% -fuzz 20% -trim +repage -gravity center -extent 1120x660 result2.jpg
Re: Batch autocrop images to fixed size?
Posted: 2018-04-13T07:26:27-07:00
by Karyudo
That code worked pretty well on a few more test images, actually, despite the sub-par background. I tried larger values of fuzz, and that didn't work as well. Smaller values seemed about the same. Deskewing seems to be rock-solid.
But overall, the strategy doesn't seem to do what I would do manually, which is to find the "best fit" lines (ignoring the tiny "ears" that sometimes stick out at the corners) on all sides, and try to minimize the average distance to those lines when overlaying a rectangle of fixed size. From what I understand of fuzz/trim, it quite conservatively "gives up" in finding an edge of the bounding box of the image at the most extreme pixel where it finds non-near-background colour.
I guess there's no Excel-like "best fit" straight line function—where the height of the tiny ear would essentially be ignored by averaging over the entire length of the discovered image/background interface? Or maybe even a way to start the fuzz-finding from inside the area one would like to keep? Or by thresholding at the edges, or ignoring the areas within some radius of the corners, or something?
Overall, the results are pretty fantastic for a one-line-of-instruction solution, though, and I know I'm just splitting hairs by wondering if it's possible to add a little complexity and do just that little bit better algorithmically to preempt what problems might be found with the few outliers that surely exist in 5000+ images.
Re: Batch autocrop images to fixed size?
Posted: 2018-04-13T08:22:38-07:00
by snibgo
wrote:..."best fit" straight line function...
"-hough-lines" does that, more or less. See
http://www.imagemagick.org/discourse-se ... =4&t=25476 . But then you need to do some arithmetic to get the coordinates of the line intersections, which are the fours of the postcard. You can then feed those to "-distort perspective" to deskew and crop the image.
Re: Batch autocrop images to fixed size?
Posted: 2018-06-05T18:02:24-07:00
by Karyudo
I did even more searching, and this is not the first time this type of problem has been asked about and only sort of half-answered (see also
viewtopic.php?f=1&t=28434, in particular). I don't suppose there's a solution out there someplace that actually shows how to get the data into an IM batch processing flow from h.mvg, or the arithmetic needed to find corners from four Hough lines (which must be a step that many—most?—uses of Hough lines need). It basically makes this function of IM useless to the casual user—even one good at searching—when that step is left as an exercise every. single. time.
Also, even if that were solved once and easy to find, it's still not clear at all how to batch process multiple directories of images.
Re: Batch autocrop images to fixed size?
Posted: 2018-06-05T20:45:36-07:00
by fmw42
I don't suppose there's a solution out there someplace that actually shows how to get corners [line intersections] from four Hough lines
Short Answer -- for pairs of lines that are not parallel see
https://en.wikipedia.org/wiki/Line–line_intersection
https://www.topcoder.com/community/data ... lications/
Re: Batch autocrop images to fixed size?
Posted: 2018-06-05T22:59:52-07:00
by snibgo
@Karyudo: If I had published a page that includes this processing, I would have linked to it. For line intersection, Fred gives a link to the maths. Implementing that in a script depends on the script language, and how the data is organised, and what error-checking is needed.
For example, lineIntersect.bat (a Windows BAT script) finds the intersection of two lines:
Code: Select all
rem Given %1 and %2 are two lines
rem returns coordinates of the intersection (if any) of the lines in %3.
rem All may be floating-point.
rem %3 environment variable for output.
rem %4 Fractional threshold for BAD. [0.0 or above, eg 0.25]
rem Larger numbers are more tolerant.
rem If either line needs to be extended by proportional fraction %4 to intersect,
rem it is marked as bad.
rem %4 can be zero, meaning all intersections that need extending are marked bad.
rem If blank or ".", no intersections are marked bad.
@rem This assumes "enabledelayedexpansion" is in effect.
set FRAC_THRESH=%4
if "%FRAC_THRESH%"=="." set FRAC_THRESH=
call :vect AB %1.A %1.B
call :vect CD %2.A %2.B
call :vect CA %2.A %1.A
call :perp Dp AB CD
if %Dp%==0 exit /B 1
call :perp sp CD CA
call :perp tp AB CA
call :doCalc sI %sp%/(%Dp%)
call :doCalc tI %tp%/(%Dp%)
call :doCalc %3.x !%1.A.x!+%sI%*%AB.x%
if ERRORLEVEL 1 exit /B 1
call :doCalc %3.y !%1.A.y!+%sI%*%AB.y%
if ERRORLEVEL 1 exit /B 1
call :doCalc %3.liNeedExtend "(%sI%<0||%sI%>1||%tI%<0||%tI%>1)?1:0"
if ERRORLEVEL 1 exit /B 1
set %3.sI=%sI%
set %3.tI=%tI%
if not "%FRAC_THRESH%"=="" if !%3.liNeedExtend!==1 (
call :doCalc siBAD "(%sI%<(-%FRAC_THRESH%)||%sI%>(1+%FRAC_THRESH%))?1:0"
if ERRORLEVEL 1 exit /B 1
call :doCalc tiBAD "(%tI%<(-%FRAC_THRESH%)||%tI%>(1+%FRAC_THRESH%))?1:0"
if ERRORLEVEL 1 exit /B 1
if !siBAD!==1 set %3.BAD=1
if !tiBAD!==1 set %3.BAD=1
)
echo %0: sI=%sI% tI=%tI% %3.liNeedExtend=!%3.liNeedExtend!
exit /B 0
rem -----------------------------------------------------
rem Subroutines
:vect
call :doCalc %1.x !%3.x!-!%2.x!
call :doCalc %1.y !%3.y!-!%2.y!
exit /B 0
:perp
call :doCalc %1 !%2.x!*!%3.y!-!%2.y!*!%3.x!
exit /B 0
:doCalc
set %1=
for /F "usebackq" %%L in (`%IM%identify -precision 19 -format "%1=%%[fx:%~2]" xc:`) do set %%L
rem echo %1 is !%1!
if "!%1!"=="" exit /B 1
exit /B 0
It can be called like this:
Code: Select all
set Line1.A.x=0
set Line1.A.y=0
set Line1.B.x=10
set Line1.B.y=0
set Line2.A.x=4.5
set Line2.A.y=-1
set Line2.B.x=7.5
set Line2.B.y=1
call %PICTBAT%lineIntersect Line1 Line2 OutLine
if ERRORLEVEL 1 echo Bad result
set OutLine
Code: Select all
OutLine.liNeedExtend=0
OutLine.sI=0.59999999999999998
OutLine.tI=0.5
OutLine.x=6
OutLine.y=0
This tells us the intersection is at (6,0), which is 0.5999 along the first line and 0.5 along the second line.
Re: Batch autocrop images to fixed size?
Posted: 2018-06-06T22:02:21-07:00
by Karyudo
Well, dammit. Thanks very much for the code snippets, but I think I'm just about officially way out of my league. I can just barely follow the batch file, but I have serious doubts as to my ability to synthesize a complete solution from even the copious code chunks that do the heavy lifting. Especially since what I'm trying to do is merely a bit of a deep dive into a tangent of my main focus, which is (believe it or not) stamp collecting.
I don't suppose anyone takes commissions...?
Re: Batch autocrop images to fixed size?
Posted: 2018-06-06T22:13:21-07:00
by fmw42
Have you tried simply using -fuzz XX% -trim +repage after you have deskewed. See
http://www.imagemagick.org/Usage/crop/#trim
Re: Batch autocrop images to fixed size?
Posted: 2018-06-07T19:15:07-07:00
by Karyudo
I have now. Adding "-fuzz XX% - trim +repage" seems to do either nothing or almost nothing (fuzz = 1% to 87%), something—but not the right thing (fuzz = 88%), crop the whole image file except for a line segment of width 1 pixel (fuzz = 89% or 90%), or even crop everything except for a single pixel (fuzz = 91%).
There are no example images in the help file to show what is supposed to happen (or not), so I have no idea how to fix this.
I also tried adding "-border 10" or "-bordercolor black -border 5" ahead of the fuzz/trim/repage, and those did nothing, either.
Re: Batch autocrop images to fixed size?
Posted: 2018-06-07T19:58:31-07:00
by fmw42
You need to use -background ... -deskew so that the background color is nearly the same as your scanning background. This works for me. I had to shave some off the background area first to remove some white areas on the right and then shave a few more off the final result to get rid of a this background on the edges.
Code: Select all
convert Sample1.jpg -shave 20x20 -background "gray(60)" -deskew 40% -fuzz 25% -trim +repage -shave 5x5 Sample1_test1.png
Re: Batch autocrop images to fixed size?
Posted: 2018-06-07T20:32:22-07:00
by Karyudo
Ooh! That's definitely better. Going to play around with this....
Thanks for persisting with me!