Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env ruby
- # How to check image color or back and white -- http://www.imagemagick.org/discourse-server/viewtopic.php?t=19580
- #
- # convert file.jpg -colorspace HSL -verbose info:|grep -A 6 Green # values: absolute (percent)
- # Green:
- # min: 0 (0)
- # max: 255 (1)
- # mean: 70.2043 (0.275311)
- # standard deviation: 99.2055 (0.389041)
- # kurtosis: -0.981812
- # skewness: 0.897517
- #
- # You convert the image to HSL and then output verbose information ("identify"
- # statistics).
- # In HSL space Saturation define how colorful pixels are, and this is returned
- # in the 'Green' channel statistics.
- #
- # If max is 0 so no color was present at all: it is a perfect grayscale or black/white image.
- # If max is 1 so at least one pure color pixel exists: it is not a pure grayscale image.
- #
- # The mean indicates how much colorful in general the image is.
- # A mean of 40% means the image is not even mostly grayscale (white background).
- #
- # Other statistics show how the color ratios was distributed about that mean.
- #
- # NOTE:
- # Due to HSL being a double hexcone model, this colorspace does not work properly
- # for measuring saturation for L>50% as it approaches the top peak. There white
- # is going to be indetermined saturation and turns out is interpreted as high
- # saturation. In its place, use HCL, HCLp, HSI or HSB above. These are all single
- # hexcone type models and should work fine in the above equation.
- #
- # convert file.jpg -colorspace HSI -channel g +channel -format "%[fx:mean.g]" info:
- #
- # ------------------------------------------------------------------------------
- #
- # How to retrive the single values from the statistics:
- # Retrieving individual Image Channel Statistics -- http://www.imagemagick.org/discourse-server/viewtopic.php?t=21008
- # FX Expressions as Format and Annotate Escapes -- http://www.imagemagick.org/Usage/transform/#fx_escapes
- # Format and Print Image Properties -- http://www.imagemagick.org/script/escape.php
- # The Fx Special Effects Image Operator -- http://www.imagemagick.org/script/fx.php
- #
- # ------------------------------------------------------------------------------
- #
- # Robust command to get H/S/I statistics in the R/G/B sections:
- # convert file.jpg -colorspace HSI -verbose info: | grep -A 20 Red
- #
- # Get the single value of a statistic (saturation mean):
- # convert file.jpg -colorspace HSI -channel g +channel -format "%[fx:mean.g]" info:
- #
- # Get image colors histogram for a restricted number of colors (64):
- # convert file.jpg -dither FloydSteinberg -colors 64 -colorspace HSB -format %c histogram:info:-
- def die(msg); STDERR.puts "ERROR: #{msg}!"; exit 1; end
- fname = ARGV[0].to_s
- die 'file not found' if fname.size == 0 || !File.exists?(fname)
- # computing histogram
- histlines = `convert '#{fname}' -dither FloydSteinberg -colors 64 -colorspace HSB -format %c histogram:info:-`.split("\n")
- puts histlines if ARGV.include?('-h')
- print fname.ljust(25)
- # extract values from histogram (num.pixels, hue, saturation, intensity)
- hist = histlines.grep(/hs[ib]/i).map{|line|
- # http://www.imagemagick.org/Usage/files/#histogram
- # pixel count: R G B #HEX hsi(hue, saturation, intensity)
- # 9274: ( 1, 89,135) #015987 hsi(0.582895%,35.0103%,53.0617%)
- next unless m = line.match(Regexp.new ' +([0-9]+):.+hs[ib]\(([^%]+)%,([^%]+)%,([^%]+)%')
- {
- npix: m.captures[0].to_i,
- hue: m.captures[1].to_f,
- sat: m.captures[2].to_f,
- int: m.captures[3].to_f,
- }
- }.compact
- die "histogram size (#{hist.size}) < 2" if hist.size < 2
- # compute saturation mean and unique hue std.deviation
- stats = hist.each_with_index.inject({
- tot_pixels: 0,
- hue_outlayered_pixels: 0,
- sat_sum: 0,
- hue_num: 0,
- hue_mean: 0,
- hue_m2: 0,
- }){|stats, pair|
- row, i = pair
- stats[:tot_pixels] += row[:npix]
- stats[:sat_sum] += row[:npix] * row[:sat]
- # incremental/online formula for std.deviation
- # https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
- if i != 0 && i != (hist.size - 1) # remove extreme values/outlayers for a better st.dev
- delta = row[:hue] - stats[:hue_mean]
- stats[:hue_num ] += 1
- stats[:hue_mean] += delta / stats[:hue_num]
- stats[:hue_m2 ] += delta * (row[:hue] - stats[:hue_mean])
- else
- stats[:hue_outlayered_pixels] += row[:npix]
- end
- stats
- }
- sat_mean = stats[:sat_sum] / stats[:tot_pixels]
- hue_sd = (stats[:hue_m2] / (hist.size - 3)) ** 0.5
- hue_outl = stats[:hue_outlayered_pixels].to_f / stats[:tot_pixels] * 100
- print [
- 'S:%5.2f' % sat_mean ,
- 'H:%5.2f' % hue_sd ,
- 'N:%3d' % hist.size,
- 'O:%3d%%' % hue_outl ,
- '=> '
- ].join(' ')
- def is_colored?(sat_mean, hue_sd, hist_size)
- return false if hist_size < 4
- if sat_mean < 10; return false # low saturation
- elsif sat_mean < 30; return hue_sd > 25 # middle sat., hue must be big for a colored image
- else ; return true # high saturation
- end
- end # is_colored?
- puts is_colored?(sat_mean, hue_sd, hist.size) ? 'color' : 'grey'
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement