4

I'm attempting to write a script which thumbnails our many thousands of assets. The assets use Flash for the most part, and I'm capturing them via chromium-browser on the command line. I pretty much need to stand over it to make it work at the moment and it's a PITA. What would help would be a way for my script to know when it had made a failed thumbnail, which seems to happen a lot.

The "fails" tend to be a uniform colour, either dark grey or white, and I thought I might be able to use this "degree of uniformity" as a way of programmatically rating the success of the thumbnail. Here's some examples:

https://dl.dropboxusercontent.com/u/846812/permanent/thumb_examples/fail_1.jpg https://dl.dropboxusercontent.com/u/846812/permanent/thumb_examples/fail_2.jpg https://dl.dropboxusercontent.com/u/846812/permanent/thumb_examples/success1.jpg https://dl.dropboxusercontent.com/u/846812/permanent/thumb_examples/success2.jpg

What makes this (I would assume) more difficult is that the dark grey one is not a uniform color, but is rather a repeated pattern of pixels, which looks like this in close up:

enter image description here

So it is uniform, but it's a uniform repeated pattern.

Can anyone think of a way I could do this at the command line?

2

I don't know how you can programatically do this and it is not a 100% accurate thing but, since you are doing something close to screen scraping, I would suggest actually launching the image on the screen and using xdtool, you can sample many random points on the image and detect the pixel color. If all or say more than 95% of them are coming up the same color, it is safe to say the image is a flat color.

Another way is to store commonly encountered erroneous images and compare the image size to the size of erroneous images. I am extracting stills from videos using VLC for my video library and while doing this, I realized, higher the contrast in an image, larger the size of a png file I capture. So, see if the image sizes are too small. After all, image compression is all about minimizing the amount of storage of a repeating pattern. You can use this fact to your advantage.

  • Thanks - i'm actually using xdotool already to do the capturing. If i was to sample pixels and count the unique colors then i think that would cope with my oddly-patterned grey image as well. The image size one works for the white image, since it's a jpeg and thus compressed then the uniformity allows a small size, as you say, but it feels a bit too much like guesswork. Do you know how i might sample a pixel? I'm doing the screengrab like so: sudo import -display :1 -window root -crop 800x600+11+83 <dest file> – Max Williams Mar 11 '16 at 15:58
  • Really not a graphics manipulation expert. Fell into it because there is nothing to accomplish what I want to do, from the command line. So, I am on the same boat as you are when it comes to guesswork. I just notice patterns in the process. This is how I figured higher contrast images (screen captures from videos) are (even slightly) larger than softer toned images. If you haven't looked into it, imagemagick may provide some more insight into the image info. I am not sure. I only use it to resize my frames or sometimes convert from one image format to the other. I know it has more features – MelBurslan Mar 11 '16 at 16:11
  • Thanks. I am using imagemagick and thought that it might provide some way, hopefully someone will tell me (us) :) – Max Williams Mar 11 '16 at 16:34
2

You could try a method that Neal Krawetz, of FotoForensics fame, does:

  1. Reduce size. Krawetz "smashes" the image into an 8x8 square.
  2. Reduce color of the 8x8 image to grayscale.
  3. Compute the mean value of the resulting 64 colors.
  4. Compute a 64-bit number (8 * 8 = 64) - "Each bit is simply set based on whether the color value is above or below the mean.
  5. Construct a hash. Looks like Krawetz just uses the 64 bits as a hash value.

That sort of thing would make your grey scale images, and black-n-white images fall out as very distinct hash values. You'd probably have to write or find some non-shell-script-code for that.

Another one that comes to mind is finding dominant colors in an image. That guy uses Imagemagick and awk, but I'm not sure how you would test for equality or similarity in your case.

UPDATE

I just found libpuzzle, "A library to find similar pictures" by chance. It would take but a little coding to do what you want with it.

There's also pHash, an open source perceptual hashing library. Probably the same amount of coding would be required for this one.

Neither of these exactly meets your requirements, as libpuzzle has a PHP interface, and pHash seems to require you to write a C program.

  • Thanks Bruce. My solution was to start off in a similar way to this but then do something (probably) less sophisticated, see my answer. – Max Williams Mar 21 '16 at 15:28
1

You can use imagemagick to compute an FFT and compare it to a known bad image:

http://www.fmwconcepts.com/imagemagick/fourier_transforms/fourier.html#im_fft

  • Clever! Although it does require you to have a compendium of bad images to compare it too. – Max Williams Mar 23 '16 at 8:52
1

Writing my own answer, since i figured it out. Well, it seems to work with my test images anyway. It's explained in the comments.

#!/bin/sh

#Tests whether an image is uniform (ie a simple repeated pattern or a single colour.)  

#The logic is as follows:
# - convert the image to an 8x8 px temp BMP image.  
#(we need to use bitmaps because we need exact pixel values 
#with no random compression artifacts)
# - convert THAT to a 1x1 px BMP image
# - convert the 1 px image back to an 8x8 px BMP image.

#If the first 8x8 image is the same (according to `diff`)   
#as the scaled-to-1px-and-back-again image, 
#then we can conclude that the first 8x8 image was totally uniform,
#(ie every pixel exactly the same) 
#and from this we can conclude that the original full size image 
#was also uniform:  not necessarily the same colour in every pixel,  
#but not varied enough for our requirements.

source=$1
small1=/tmp/small_image.bmp
small2=/tmp/small_image2.bmp
tiny=/tmp/tiny_image.bmp

#the \! after 8x8 tells it to ignore the aspect ratio and just squash it to those dimensions
convert "$source" -resize 8x8\! "$small1"
convert "$small1" -resize 1x1 "$tiny"
convert "$tiny" -resize 8x8 "$small2"
diff "$small1" "$small2" > /dev/null
result=$?
if [ $result -eq 0 ]; then
  #diff gives an empty return, so the files are the same, which means there wasn't variation
  echo "Image is uniform" >&1
else
  #we found a difference between the pre-squashed and resized versions which means there WAS variation
  echo "Image is not uniform" >&1
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.