Page 1 of 1
Categorising Images By Background
Posted: 2019-04-23T15:21:28-07:00
by FUrn
I am looking to make a number of batch modifications to a set of product images, with the end purpose of getting them all to look somewhat aligned. The following portion of code trims each image and then re-borders it so that each fills the same proportion of the canvas:
Code: Select all
magick $filename -fuzz 10% -trim +repage -bordercolor white -border 12%% "$filename"
The issue I am having is that this works well for images on a white background, but less well on images with any other non-solid background. So for example it works well on this first image but less so on the second:
To complicate things, there are images that lie somewhere 'between' these...the first one has some shadows, whilst the second one uses a predominantly light grey, rather than white, background. If possible, I'd also like to apply the trim and re-border operation to images such as these:
Given I have several thousand images to go through, I need some way to process images that will come out well and ignore those that can't be operated on in this way. I thought of doing this by detecting the proportion of white (or if need be the colours/shades close to white) in each image and setting a threshold, above which I will trim and re-border those images and below which I will have to leave untouched. To find the right threshold and avoid mistakenly edited images, I thought it would make sense to have ImageMagick first categorise the images into two different directories based on the percentage of white in each image - so those above x% would go into the 'whiteBackground' folder and those below x% go into the 'otherBackground' folder. Is this possible, or for that matter is there a more efficient way to achieve what I am trying to do?
I am using using ImageMagick 7.0.8-14 on a Windows PC, with BASH syntax.
Re: Categorising Images By Background
Posted: 2019-04-23T15:32:09-07:00
by fmw42
I cannot help with images with real world background. I don't think that is possible. But for images with some gray-like color, you can use -filter point -distort SRT 0 with a virtual canvas to extend the background using -virtual-pixel edge or whatever method you want. That may or may not look good. Otherwise, a simpler method is to measure the background color from the average of each edge and then use -border or -extent to pad it out with that average color.
See
https://imagemagick.org/Usage/distorts/#srt
https://imagemagick.org/Usage/distorts/#distort_virtual
https://imagemagick.org/Usage/distorts/ ... t_viewport
Re: Categorising Images By Background
Posted: 2019-04-23T15:51:43-07:00
by snibgo
FUrn wrote:... categorise the images into two different directories based on the percentage of white in each image - so those above x% would go into the 'whiteBackground' folder and those below x% go into the 'otherBackground' folder.
Finding the proportion of pixels that are white is easy. Turn the other pixels black ("-fill Black +opaque White"), and the mean ("-format %[fx:mean]") is the required proportion, on a scale of 0.0 to 1.0. If you want a percentage, multiply by 100 ("-format %[fx:mean*100]").
Re: Categorising Images By Background
Posted: 2019-04-23T15:58:13-07:00
by FUrn
Thanks Fred. I think a simpler method would be best for now, as I don’t want to risk distorting images wrongly and would therefore prefer a more cautious approach. The issue with taking the average colour of each edge is that this approach would work for images that need additional background, and not those for which I need to reduce the background (i.e. trim it to in essence make the image contents take up more of the canvas). Unless I’ve misunderstood your suggestion, would it not be more suitable to take the percentage of the image that is white vs non-white? Either way, I’d appreciate your guidance of how to actually code this in IM and how to use this to sort images into different folders depending on the percentage of white in the image. Thanks once again, Fred!
Re: Categorising Images By Background
Posted: 2019-04-23T16:00:02-07:00
by fmw42
How do decide visually which to pad and which to trim?
Re: Categorising Images By Background
Posted: 2019-04-23T16:01:35-07:00
by FUrn
snibgo wrote: ↑2019-04-23T15:51:43-07:00
Finding the proportion of pixels that are white is easy. Turn the other pixels black ("-fill Black +opaque White"), and the mean ("-format %[fx:mean]") is the required proportion, on a scale of 0.0 to 1.0. If you want a percentage, multiply by 100 ("-format %[fx:mean*100]").
Thanks @snibgo! I’ll give this a try. Assuming I have no issues getting this to work on my end, how would I then use a percentage threshold (eg 70%) to categorise/move images into the ‘whiteBackground’ (for images with mean >70%) and ‘otherBackground’ (for images with mean <70%) folders?
Re: Categorising Images By Background
Posted: 2019-04-23T16:04:57-07:00
by FUrn
fmw42 wrote: ↑2019-04-23T16:00:02-07:00
How do decide visually which to pad and which to trim?
If they have white background, there is no need to explicitly make this decision. Once each image is trimmed and then given a 12% border, the end outcome is that each chair (in these example images) takes up the Sam proportion of the canvas, regardless of the image resolution. Those that were originally quite ‘small’ chairs, in that there was a lot of white background, now appear the same size as those that originally filled the whole canvas. I hope that answers your question...
Re: Categorising Images By Background
Posted: 2019-04-23T16:09:49-07:00
by fmw42
Not really.
The issue with taking the average colour of each edge is that this approach would work for images that need additional background, and not those for which I need to reduce the background (i.e. trim it to in essence make the image contents take up more of the canvas
What exactly are you questioning here as the "issue"? How do you decide which need additional background and which need padding. Both could have a white background. So it might depend upon the size of the image. What do you do for near solid color backgrounds such as gray? How do you decide whether to trim or pad -- by size? Is not size the only issue? Some images that real-world background cannot be trimmed or padded meaningfully!
Re: Categorising Images By Background
Posted: 2019-04-23T16:18:18-07:00
by FUrn
I’m worried I won’t use the correct technical terms, but if you look at the original images I posted the 3rd image (with two chairs) would need trimming as the chairs appear considerably smaller than the chairs in the other images. Conversely, if you imagine an image with the chair going all the way to the canvas edge, that would require padding. Given some images will require trimming and others padding, would finding the average edge colour still be of use? To be on the cautious side, I’m tempted to ignore images with non-white backgrounds and only amend those with white backgrounds. Obviously I’d prefer, in an ideal world, to modify grey background images too, however perhaps focussing on white background images alone would strike the right balance between simplicity vs correctness (i.e. being cautious and doing something that I, as somewhat of a beginner, can replicate).
Re: Categorising Images By Background
Posted: 2019-04-23T16:57:04-07:00
by snibgo
FUrn wrote:...how would I then use a percentage threshold (eg 70%) to categorise/move images into the ‘whiteBackground’ (for images with mean >70%) and ‘otherBackground’ (for images with mean <70%) folders?
A Windows BAT script could be something like this (untested):
Code: Select all
for %%F in (*.jpg) do (
for /F "usebackq" %%L in (`magick ^
%%F ^
-fill Black +opaque White ^
-format "ISWHITE=%[fx:mean>0.7?1:0] ^
info:`) do set %%L
if %ISWHITE%==1 (
copy %%F whiteBackground\%%F
) else (
copy %%F otherBackground\%%F
)
)
This loops through all the jpg files in the current directory. For each one, it sets ISWHITE to 1 if more than 70% of pixels are white, otherwise 0. It uses that value to copy to the appropriate directory.
You use bash, not BAT, so you will need to translate.
Re: Categorising Images By Background
Posted: 2019-04-24T13:34:38-07:00
by FUrn
snibgo wrote: ↑2019-04-23T16:57:04-07:00
Code: Select all
for %%F in (*.jpg) do (
for /F "usebackq" %%L in (`magick ^
%%F ^
-fill Black +opaque White ^
-format "ISWHITE=%[fx:mean>0.7?1:0] ^
info:`) do set %%L
if %ISWHITE%==1 (
copy %%F whiteBackground\%%F
) else (
copy %%F otherBackground\%%F
)
)
Thanks for this, @snibgo. I'm not too familiar with translating from BAT to Bash, and so thought I'd execute this as a BAT file via the Git Bash command line. However I'm getting a variety of errors, however much I try adjusting things ever so slightly. Errors include:
- else was unexpected at this time - at the ) else ( point in the code
- ( was unexpected at this time - after the if ==1 (
- the syntax of the command is incorrect - with reference to a (
Any help you can give to get me round this would be great!
I'm also trying to understand the code you've drafted, and have a couple of questions if I may:
- Why have you added a ` after the info:
- The part I'm having most difficulty understanding is the second for command. How exactly does the part reading 'for /F "usebackq" %%L in...do set %%L' work? What is the purpose of the "usebackq"? I get in general that this line applies the IM code to set whether or not the image in question has >70% white pixels, but don't get the BAT syntax here.
Thanks once again, @snibgo.
Re: Categorising Images By Background
Posted: 2019-04-24T14:14:19-07:00
by snibgo
It was untested, so had some bugs. This works:
Code: Select all
for %%F in (*.jpg) do (
for /F "usebackq" %%L in (`%IMG7%magick ^
%%F ^
-fill Black +opaque White ^
-format "ISWHITE=%%[fx:mean>0.7?1:0]" ^
info:`) do set %%L
if !ISWHITE!==1 (
copy %%F whiteBackground\%%F
) else (
copy %%F otherBackground\%%F
)
)
For help on "for" (or other Windows command) type "help for" at the Windows command prompt.
An equivalent bash script is:
Code: Select all
for FILENM in *.jpg
do
echo $FILENM
ISWHITE=`magick \
$FILENM \
-fill Black +opaque White \
-format "%[fx:mean>0.7?1:0]" \
info:`
if [ $ISWHITE -eq 1 ]; then
cp $FILENM whiteBackground/$FILENM
else
cp $FILENM otherBackground/$FILENM
fi
done
Re: Categorising Images By Background
Posted: 2019-04-24T15:24:55-07:00
by FUrn
This is excellent, @snibgo, and worked like a charm! Thanks so much - you've saved me a *lot* of time