Batch autocrop images to fixed size?

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Karyudo
Posts: 13
Joined: 2018-04-11T21:40:26-07:00
Authentication code: 1152

Batch autocrop images to fixed size?

Post 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.)
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Batch autocrop images to fixed size?

Post 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.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Batch autocrop images to fixed size?

Post 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
Karyudo
Posts: 13
Joined: 2018-04-11T21:40:26-07:00
Authentication code: 1152

Re: Batch autocrop images to fixed size?

Post 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.)
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Batch autocrop images to fixed size?

Post 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
Karyudo
Posts: 13
Joined: 2018-04-11T21:40:26-07:00
Authentication code: 1152

Re: Batch autocrop images to fixed size?

Post 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.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Batch autocrop images to fixed size?

Post 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.
snibgo's IM pages: im.snibgo.com
Karyudo
Posts: 13
Joined: 2018-04-11T21:40:26-07:00
Authentication code: 1152

Re: Batch autocrop images to fixed size?

Post 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 alsoviewtopic.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.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Batch autocrop images to fixed size?

Post 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/
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Batch autocrop images to fixed size?

Post 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.
snibgo's IM pages: im.snibgo.com
Karyudo
Posts: 13
Joined: 2018-04-11T21:40:26-07:00
Authentication code: 1152

Re: Batch autocrop images to fixed size?

Post 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...?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Batch autocrop images to fixed size?

Post by fmw42 »

Have you tried simply using -fuzz XX% -trim +repage after you have deskewed. See http://www.imagemagick.org/Usage/crop/#trim
Karyudo
Posts: 13
Joined: 2018-04-11T21:40:26-07:00
Authentication code: 1152

Re: Batch autocrop images to fixed size?

Post 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.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Batch autocrop images to fixed size?

Post 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
Karyudo
Posts: 13
Joined: 2018-04-11T21:40:26-07:00
Authentication code: 1152

Re: Batch autocrop images to fixed size?

Post by Karyudo »

Ooh! That's definitely better. Going to play around with this....

Thanks for persisting with me!
Post Reply