Get, or Calculate the Entropy of an Image with Ruby and Imagemagick

Get, or calculate the entropy of an image with Ruby and imagemagick

Entropy is explained here (with MATLAB source, but hopefully the qualitative explanation helps):

Introduction to Entropy (Data Mining in MATLAB)

For a more formal explanation, see:

"Elements of Information Theory" (Chapter 2), by Cover and Thomas

Image histogram with mini_magick or image_science?

A workaround is to use mini_magick to convert the file to PNG format, store the result in a temporary file, and then use the "almost-pure Ruby" png library or the actually-pure Ruby chunky_png to go over the result. Both libraries make it easy to iterate over the image pixel by pixel.

I'm suspecting you specified mini_magick/image_science because these are a lot easier to install than, say, rmagick. The reason this workaround might work for you, then, is that png and chunky_png are pain-free installs due to a lack of dependencies.

The only thing you'd be giving up is a little performance but if it's a real problem, oily_png can extend chunky_png with some extra C magic.. so there'll be a compile, but it shouldn't be a painful one.

OK, I've come up with some code for this that works:

require 'mini_magick'
require 'chunky_png'

i = MiniMagick::Image.open("a.jpg")

i.format('png')

p = ChunkyPNG::Image.from_io(StringIO.new(i.to_blob))

p.height.times do |y|
p.width.times do |x|
p[x, y] # => here's your pixel..
end
end

You can take the histogram creation part from there ;-)

Also, I just noticed that ImageMagick itself can create histograms from the command line. This might not help if you want something specific but I thought I'd throw it out there.

Image histogram with mini_magick or image_science?

A workaround is to use mini_magick to convert the file to PNG format, store the result in a temporary file, and then use the "almost-pure Ruby" png library or the actually-pure Ruby chunky_png to go over the result. Both libraries make it easy to iterate over the image pixel by pixel.

I'm suspecting you specified mini_magick/image_science because these are a lot easier to install than, say, rmagick. The reason this workaround might work for you, then, is that png and chunky_png are pain-free installs due to a lack of dependencies.

The only thing you'd be giving up is a little performance but if it's a real problem, oily_png can extend chunky_png with some extra C magic.. so there'll be a compile, but it shouldn't be a painful one.

OK, I've come up with some code for this that works:

require 'mini_magick'
require 'chunky_png'

i = MiniMagick::Image.open("a.jpg")

i.format('png')

p = ChunkyPNG::Image.from_io(StringIO.new(i.to_blob))

p.height.times do |y|
p.width.times do |x|
p[x, y] # => here's your pixel..
end
end

You can take the histogram creation part from there ;-)

Also, I just noticed that ImageMagick itself can create histograms from the command line. This might not help if you want something specific but I thought I'd throw it out there.

How to deal with histogram zero count when computing image entropy?

Since you are porting the function into another programming framework, a good answer to your question, in my opinion, would be: "the same thing that Matlab does".

Matlab drops counts equal to 0 before normalizing the histogram. If you open the original function using the command open entropy, you will find what you are looking for into its code:

% calculate histogram counts
p = imhist(I(:));

% remove zero entries in p
p(p==0) = [];

% normalize p so that sum(p) is one.
p = p ./ numel(I);

E = -sum(p.*log2(p));

ImageProcessing::Error when passing crop argument to variant

Try my_model.file.variant(combine_options: { crop: '1440x560+580+120')

How to copy an image line and insert it at specified positions n-times with imagemagick?

Thanks to @fmw42 I could script the following solution which gets the image size and then calculates the number of lines to increase the image to a height of 48/49 pixel.
First it adds the lines at the image bottom and after this it adds the same number of lines at the image top. While keeping the first/last lines.

@echo off
setlocal ENABLEDELAYEDEXPANSION
set image=Welcome1.gif
rem use %1 for comanndline argument

set image2=%TEMP%\temp1.gif
set image3=%TEMP%\temp2.gif

magick identify -format "%%w" %image% > %TEMP%\imwidth.txt
set /P width=<%TEMP%\imwidth.txt
del %TEMP%\imwidth.txt

magick identify -format "%%h" %image% > %TEMP%\imheight.txt
set /P height=<%TEMP%\imheight.txt
del %TEMP%\imheight.txt

set /A addlines=(49 - %height%) / 2
set /A lastline=%height% - 2

magick %image% -crop %width%x1+0+2 %TEMP%\copyLine.gif

rem Add lines at end of image
set image1=%image%
FOR /L %%i IN (1,1,%addlines%) DO (
magick !image1! -background black -splice 0x1+0+%lastline% %image2%
magick composite %TEMP%\copyLine.gif %image2% -geometry 99x1+0+%lastline% %image3%
del %TEMP%\%image%
ren %image3% %image%
set image1=%TEMP%\%image%
)

rem Add lines at top of image
set image1=%TEMP%\%image%
FOR /L %%i IN (1,1,%addlines%) DO (
magick !image1! -background black -splice 0x1+0+2 %image2%
magick composite %TEMP%\copyLine.gif %image2% -geometry 99x1+0+2 %image3%
del %TEMP%\%image%
ren %image3% %image%
set image1=%TEMP%\%image%
)
copy %TEMP%\%image% %image:~0,-4%touch.gif

del %TEMP%\copyLine.gif %TEMP%\temp1.gif %TEMP%\temp2.gif %TEMP%\%image%
endlocal
exit /b 0


Related Topics



Leave a reply



Submit