Reputation: 67
I am looking for a method that i can use for cropping several plots automatically.. without I manually have to set the box size of the cropping.
I need to crop a list of spectrogram plots like these,
In which I only need the the actual plot, and nothing else. Just the plot.
Currently I am cropping it like this.
print "Hstacked Image"
images1 = Image.open(spectogram_path_train+"/"+name+"_plot_static_conv.png")
images2 = Image.open(spectogram_path_train+"/"+name+"_plot_delta_conv.png")
images3 = Image.open(spectogram_path_train+"/"+name+"_plot_delta_delta_conv.png")
box = (100,55,592,496)
cropped1 = images1.crop(box)
cropped2 = images2.crop(box)
cropped3 = images3.crop(box)
width1, height1 = cropped1.size
width2, height2 = cropped2.size
width3, height3 = cropped3.size
sum_width = width1 + width2 + width3
max_height = max(height1,height2,height3)
new_im = Image.new('RGB',(sum_width,max_height))
x_offset = 0
for im in [cropped1,cropped2,cropped3]:
new_im.paste(im,(x_offset,0))
x_offset+=im.size[0]
new_im.save(spectogram_path_train+"/"+name+"_plot_hstacked.png")
These box values are set to crop this image.. the left and lower parameter of the box is always the same for each plot, but the right might differ, which has to be automatically determined for each plot.
I am looking for a smart crop that is capable of removing everything besides the coloured plot.
Upvotes: 0
Views: 1120
Reputation: 67
So.. I decided to follow @martineau suggestion an made a solution that made use of that.
images1 = Image.open(static)
images2 = Image.open(delta)
images3 = Image.open(delta_delta)
data_numpy = np.array(images1)
number = 0
right = 0
for i in data_numpy[55,:]:
# print i
number+=1
if i[0] == 234 and i[1] == 234 and i[2] == 242 and i[3] == 255 and number > 100:
# print "Found it!"
right = number
break
if i[0] == 255 and i[1] == 255 and i[2] == 255 and i[3] == 255 and number > 100:
right = number
break
#print right
box = (100,55,right,496)
cropped1 = images1.crop(box)
cropped2 = images2.crop(box)
cropped3 = images3.crop(box)
I hope the code speaks for itself if not..
The for loop iterates (One row only need to be checked, due to the size of the plot) through the images, and find the pixel position which is the same as the grey one. when that is found will the for loop break, and a box will be created fitted to the desired size.
Upvotes: 1
Reputation: 207425
I don't know Python, but you can do it without any high-level language at the Terminal with ImageMagick which is installed on most Linux distros and is available for macOS and Windows.
First, note that your image has a superfluous alpha channel for some reason, so I turn that off.
Then, I note that all the stuff you are interested in is saturated colour and all the extraneous text is black/grey and unsaturated, so I would turn to the saturation to be the discriminant. This command, typed into the Terminal, loads your image and sets all pixels to black, i.e. zero, where they are unsaturated and retains their current values everywhere else. It then trims the borders and saves the result.
convert spectrum.png -alpha off -fx "saturation<0.2?0:u" -trim z.png
If I now run that command again, but extract just the top single row of pixels, and look for the first black one, I will know where to crop:
convert spectrum.png -alpha off -fx "saturation<0.2?0:u" -trim +repage -crop x1! txt: | awk -F, '/black/{print $1;exit}'
496
So, I need to crop at column 496, which I do with:
convert spectrum.png -alpha off -fx "saturation<0.2?0:u" -trim +repage -crop 496x+0+0 z.png
If I wanted to automate the entire process, I could do:
x=$(convert spectrum.png -alpha off -fx "saturation<0.2?0:u" -trim +repage -crop x1! txt: | awk -F, '/black/{print $1;exit}')
convert spectrum.png -alpha off -fx "saturation<0.2?0:u" -trim +repage -crop ${x}x+0+0 y.png
Upvotes: 1