Page 1 of 2

Detecting multiple images in one image file

Posted: 2019-09-24T15:28:39-07:00
by dcotto
Hello, i have one big image that has other images in them. What i want to be able to do is detect each image and then crop them.

for instance i may have 3 images in one JPG file

image 1 is 300 x 300
image 2 is 400 x 400
image 3 is 500 x 500

each image has a black border of lets say 2px around them

How can i tell imagemagick to find each image and then crop it out for each one.
more importantly i just need imagemagick to be able to detect other images.
thanks

Re: Detecting multiple images in one image file

Posted: 2019-09-24T15:39:35-07:00
by snibgo
What version of IM? On what platform? Please show sample inputs.

Re: Detecting multiple images in one image file

Posted: 2019-09-25T08:21:29-07:00
by dcotto
im using ImageMagick 7.0.8-59 Q16 x86_64 2019-08-05

im using it on a macOS Sierra10.12.6

i will be using BASH terminal and Python <- each one separately, not together.


below is the image.
this jpeg contains 5 other images. i want to crop each one out..eliminate all the whitespace..its also possible that other images that i have may contain text right above each picture that would say 300x200 etc... i want to avoid that text too and not crop it

Image

https://ibb.co/dBPxPLQ

Re: Detecting multiple images in one image file

Posted: 2019-09-25T10:09:06-07:00
by fmw42
See my bash unix shell script that uses ImageMagick called multicrop2 at my link below. It runs on Mac OSX, Linux and Windows Unix.

Input:
Image

Code: Select all

multicrop2 -f 25 -b white -d 1000 -u 3 crop-me.jpg result.png
Image

Image

Image

Image

Re: Detecting multiple images in one image file

Posted: 2019-09-25T12:34:37-07:00
by dcotto
hey thank you chief but i am not looking for a paid solution at the moment.

i am looking to learn how to solve this technical issue as a programmer and how i would go about it.

would anyone know how to best do that using this or what are some generic steps i have to take to achieve my goal?

thanks guys!

Re: Detecting multiple images in one image file

Posted: 2019-09-25T14:35:02-07:00
by snibgo
In Subimage rectangles I describe two methods of segmentation: (1) by guillotine (finding where to "cut" the main image into horizontal or vertical segments) and (2) by connected-components.

Re: Detecting multiple images in one image file

Posted: 2019-09-25T16:19:02-07:00
by fmw42
Threshold your image to get black rectangles on white background. Then use -connected-components to get the bounding boxes of the black rectangles. Then use this to crop your input image.

Re: Detecting multiple images in one image file

Posted: 2019-09-30T17:36:52-07:00
by dcotto
fmw42 wrote: 2019-09-25T16:19:02-07:00 Threshold your image to get black rectangles on white background. Then use -connected-components to get the bounding boxes of the black rectangles. Then use this to crop your input image.
awesome man thank you so much! im going to try your method

Re: Detecting multiple images in one image file

Posted: 2019-10-01T18:26:20-07:00
by dcotto
fmw42 wrote: 2019-09-25T16:19:02-07:00 Threshold your image to get black rectangles on white background. Then use -connected-components to get the bounding boxes of the black rectangles. Then use this to crop your input image.
Hey, would you be able to give an example how i would threshold an image and perform these steps using imagicmagick. I'm new to it and don't know.. Would it require creating a layer and then masking and applying the layer.

Re: Detecting multiple images in one image file

Posted: 2019-10-01T19:36:42-07:00
by fmw42
Do a fuzzy flood fill at some pixel that is the background. See -fuzz XX% -draw "alpha x,y floodfill" at https://imagemagick.org/Usage/draw/#matte (alpha replaces matte in IM 7). Use as small a fuzz value as you can. For JPG images, the compression makes the background uneven. I have found values for fuzz of about 15% usually works. If the background less uniform, increase it. If you know your background is perfectly uniform, then you can go down to 0%. Note that if any interior image's color around its boundary is close to the background color, then you might get a bounding box smaller than your interior image, if too large a fuzz value is used.

Then do connected components and extract the bounding boxes for each white area representing the images. See https://imagemagick.org/script/connected-components.php. Use the various defines for area-threshold=XXX, verbose=true and mean-color=true to remove small objects that might be from the background and to get the data you need.

Then extract each bounding box and use that to crop your image, one bounding box at a time in a script loop.

Re: Detecting multiple images in one image file

Posted: 2019-10-11T07:19:45-07:00
by dcotto
fmw42 wrote: 2019-10-01T19:36:42-07:00 Do a fuzzy flood fill at some pixel that is the background. See -fuzz XX% -draw "alpha x,y floodfill" at https://imagemagick.org/Usage/draw/#matte (alpha replaces matte in IM 7). Use as small a fuzz value as you can. For JPG images, the compression makes the background uneven. I have found values for fuzz of about 15% usually works. If the background less uniform, increase it. If you know your background is perfectly uniform, then you can go down to 0%. Note that if any interior image's color around its boundary is close to the background color, then you might get a bounding box smaller than your interior image, if too large a fuzz value is used.

Then do connected components and extract the bounding boxes for each white area representing the images. See https://imagemagick.org/script/connected-components.php. Use the various defines for area-threshold=XXX, verbose=true and mean-color=true to remove small objects that might be from the background and to get the data you need.

Then extract each bounding box and use that to crop your image, one bounding box at a time in a script loop.

yeah fmw42 so i did a fuzzy flood fill and you were right.
The Fuzzy flood fill leaked into the picture. The background color matched with colors on the edges of some of the pictures. im wondering if theres some sort of other command option that can recognize the squares, close the square and remove the leaked in fill.

heres a picture of the results. Once again. thank you immensely for helping me with this.. this is super cool stuff i didnt know imagemagick was this powerful and that you could do so much via the commandline like this.

https://ibb.co/wgxV9qg

Re: Detecting multiple images in one image file

Posted: 2019-10-11T09:15:05-07:00
by fmw42
You should do your fuzzy flood fill. Then use connected components to find each region. Then get the bounding boxes from the the connected components. Then use the bounding boxes to crop out each image from the original, not the flood filled images.

If I misunderstand your question, please elaborate.

Re: Detecting multiple images in one image file

Posted: 2019-10-11T12:31:37-07:00
by dcotto
after doing the fuzzy fill the images are not covered in white so when i tried to use -connected-components -depth 8 or -depth 20 i get an error saying too many objects.. im guessing cause i have to transform to the boxes/images to white . .. im still trying to find that technique.

you said "Then do connected components and extract the bounding boxes for each white area representing the images" but i dont know the technique to transform the images now to white...i only transformed white background to black

Re: Detecting multiple images in one image file

Posted: 2019-10-11T13:40:15-07:00
by fmw42
Using your posted image, try this:

Code: Select all

convert crop-me.jpg -fuzz 5% -fill none -draw "matte 0,0 floodfill" -background black -alpha background -fill white +opaque none -alpha off crop_me_floodfill.png
Image

You should now have a black image with white regions mostly rectangles with some "eaten" partially away. But the bounding boxes will still be rectangles.

If the fuzz value is too low or you have a noisy background, then you will get other small regions. That is why you must use some area-threshold smaller than the estimated area of the smallest pictures in the connected components to remove these regions so you do not get that message.

Re: Detecting multiple images in one image file

Posted: 2019-10-11T14:39:46-07:00
by dcotto
okay awesome, your one liner is great. im going to use that one instead but below is how i did it:

so i did it one by one since i dont know how to combine all commands just yet

// flood fill an image with fuzz (fuzz to blend more pixels in and out of selection)
convert chopped_off_top.jpg -fuzz 10% -draw "alpha 1,10 floodfill" flood-filled.jpg

// Create a threshold of crop_
convert flood-filled -threshold 6% threshold.jpg

// copy the threshold imaged (black and white image) to the alpha channel of crop_me.jpg
convert crop_me.jpg threshold.jpg -alpha Off -compose CopyOpacity -composite hopeful.png

i was able to successfully copy/combine the mask to the alpha channel of the original file.

now what i have to learn is how to create a bounding rectangle box and fill in those rectangles with white...

i tried to use the connected components method using the document you sent me https://imagemagick.org/script/connected-components.php
but i get so many objects back

convert threshold.jpg -connected-components 4 -auto-level -depth 8 segmented.jpg
convert segmented.jpg -define connected-components:verbose=true -connected-components 4 componented.jpg

so i still have to figure out how to do it properly.. you said
That is why you must use some area-threshold smaller than the estimated area of the smallest pictures in the connected components to remove these regions so you do not get that message.

so im going to mess around with the area-threshold in connect-components to see what i get.

the other thing i have to figure out is the next steps.. I'm not sure if i first have to use connect-components to separate the areas where the images live, create a bounding box and then fill it with white ... or create a bounding box first around each image area, separate using connect-components and then fill in..

im also not sure how to create a rectanagle bounding box so thats what i have to figure out next too

hey thanks for help man. this is coming along great! thank you