Alvie Mahmud
Alvie Mahmud

Reputation: 194

ImageMagick to crop image based on based on rectangular border color

I have some images that I would like to crop but hopefully via command line rather than doing each one manually.

I would like to crop the image (I've cropped top half, desaturated other colours and split frames with ffmpeg) based on where there is a border of a certain color (#31393C in this case). For example, I would like this image: enter image description here to be cropped like this:
enter image description here

I have tried some commands but they aren't working for me unfortunately.

convert image.jpg -bordercolor "#31393C" -border 2x2 -fuzz 10% -trim output.jpg

I have also tried to make the parts that aren't #31393C to be filled with white and then cropping which may potentially work as a solution as I want to improve the ability to use OCR:

convert image.jpg -fill white -fuzz 11% +opaque "#31393c" result.jpg
convert result.jpg -bordercolor white -border 10x10 -fuzz 10% -trim output.jpg

which works somewhat but not perfectly: enter image description here

Upvotes: 0

Views: 946

Answers (2)

fmw42
fmw42

Reputation: 53089

Here is how you can do that using connected components processing in ImageMagick. I specify the color you want and a fuzz value for how much variation to allow. This assumes that you want the largest box of that color and it is larger than 500 pixels. This is Unix syntax. But similar code can be developed for Windows.

The -fuzz ... -fill ... +-opaque ... essentially thresholds on the desired color so that that color becomes white and the rest of the image becomes black.

The connected components arguments do the follow:

  • exclude the header from the verbose list
  • keep only areas larger than 500 pixels
  • keep only the region with the largest non-background color (white) and the background region (black)
  • make a verbose listing of the selected regions
  • get the average color of the regions in the verbose listing

After that it pipes to grep to filter to keep only the white regions, i.e. gray(255) and then pipes to awk to select the bounding box from the listing.

Input:

enter image description here

color="srgb(49,57,60)"
fuzzval=10
bbox=`convert \
textbox.png \
-fuzz $fuzzval% \
-fill black +opaque "$color" \
-fill white -opaque "$color" \
-type bilevel \
-define connected-components:exclude-header=true \
-define connected-components:area-threshold=500 \
-define connected-components:keep-top=1 \
-define connected-components:verbose=true \
-define connected-components:mean-color=true \
-connected-components 8 null: | \
grep "gray(255)" | awk '{print $2}'`
echo "$bbox"
convert textbox.png -crop $bbox +repage textbox_crop.png

Cropped Result:

enter image description here

Upvotes: 4

Mark Setchell
Mark Setchell

Reputation: 207415

Not sure if there might be an easier way, or if desaturating your colours was the wisest idea, but the following approach seems to work. Note that we are going to make an unholy mess of a copy of your original image just to get the trim-box and then apply that to the untouched original image.

So, the plan is as follows:

  1. use a sub-image search to find a nice big 50x50 block of your dark grey which we are assured will be in the large grey area you want to crop

  2. once we have found that 50x50 block, do a flood-fill with red starting there and then make everything else black

  3. get the trim-box and apply that to the original

So, for step 1:

compare -metric RMSE -subimage-search N6rL3.png -size 50x50 "xc:#31393c" locations.png
0 (0) @ 106,351

This is locations-1.png and you can see it is bright white, meaning a good match at the top-left of your desired rectangle and we have the coordinates of that point, i.e. 106,351

enter image description here

Step 2) Flood fill from that point with red, making all else black:

magick N6rL3.png -fill red -draw "color 106,351 floodfill" -fill black +opaque red interim.png

enter image description here

Step 3) Get the trim box this time rather than creating an output image:

magick N6rL3.png -fill red -draw "color 96,351 floodfill" -fill black +opaque red -format %@ info:
1560x152+96+304

Now we can crop the original using that trim-box:

magick N6rL3.png -crop 1560x152+96+304 result.png

Note that I did this rather in a rush and you may need to adjust a few small things...

Upvotes: 3

Related Questions