How to Detect a Blank Column in a Page Using Imagemagick to Distinguish Two Column Papers

How to detect a blank column in a page using ImageMagick to distinguish two column papers

One way to do this is to calculate a "projection" (i.e. mean) of all the pixels down the vertical columns by resizing the image to just 1pixel tall. I have inverted/negated the image so you can see the colours better and stretched the 1pixel tall image to 20pixels tall so you can see it at the bottom:

magick paper.png -alpha off -negate -scale x1\! -auto-level -scale x20\! result.png

Sample Image

So, if you take that a little further and make the output a single row of 100 pixels and look at it as text, you might hope for some particularly low values around the 50% position at the centre of the page:

magick paper.png -alpha off -colorspace gray -negate -scale x1\! -scale 100x\! -auto-level txt:

Sample Output

# ImageMagick pixel enumeration: 100,1,65535,gray
0,0: (0) #000000 gray(0)
1,0: (0) #000000 gray(0)
2,0: (0) #000000 gray(0)
3,0: (56.1923) #383838 gray(22.0362%)
4,0: (209.168) #D1D1D1 gray(82.0267%)
5,0: (187.374) #BBBBBB gray(73.4801%)
6,0: (180.066) #B4B4B4 gray(70.6143%)
7,0: (188.581) #BDBDBD gray(73.9534%)
8,0: (197.288) #C5C5C5 gray(77.368%)
9,0: (230.555) #E7E7E7 gray(90.4138%)
...
...
45,0: (221.296) #DDDDDD gray(86.7826%)
46,0: (234.086) #EAEAEA gray(91.7985%)
47,0: (239.522) #F0F0F0 gray(93.93%)
48,0: (191.323) #BFBFBF gray(75.0288%)
49,0: (44.6977) #2D2D2D gray(17.5285%) <--- HERE IS THE CENTRAL GUTTER
50,0: (27.1557) #1B1B1B gray(10.6493%) <--- AND HERE - AROUND 50% ACROSS
51,0: (145.663) #929292 gray(57.1227%)
52,0: (154.567) #9B9B9B gray(60.6144%)
53,0: (184.97) #B9B9B9 gray(72.5372%)
...
...
91,0: (156.178) #9C9C9C gray(61.2462%)
92,0: (151.242) #979797 gray(59.3107%)
93,0: (146.532) #939393 gray(57.4635%)
94,0: (149.511) #969696 gray(58.6319%)
95,0: (185.506) #BABABA gray(72.7475%)
96,0: (21.7851) #161616 gray(8.54316%)
97,0: (0) #000000 gray(0)
98,0: (0) #000000 gray(0)
99,0: (0) #000000 gray(0)

Other ideas:

  • You could let ImageMagick do the thresholding for you with something like this and look around line 572:

    magick paper.png -alpha off -colorspace gray -negate -scale x1\! -threshold 2% txt:

  • You could shave 10% off the left and right edges first, to get rid of edge-effects:

    magick paper.png -shave 10%x ... result.png

Equality test of images using ImageMagick

ImageMagick provides the compare function to properly compare images.

Checking the md5 checksum of two images is not the correct approach, since some image formats (e.g. PNG and JPEG with EXIF for example), contain the date and time the file was created (see example 1) below, and some files can be visually identical but represented completely differently internally (see example 2), or have different bit-depths (see example 3).

Example 1

# Create two identical images (100x100 pixels, bright red) but with different file contents
convert -size 100x100 xc:red r1.png
convert -size 100x100 xc:red r2.png

# MD5 checksum them
md5 r?.png
MD5 (r1.png) = 9f6d612615efd88c3fd8521d717e9811
MD5 (r2.png) = 996911bec0e0da75af46a1e78c052998 # Mmmm different

# Ask IM to tell us absolute error between the two (number of differing pixels)
compare -metric AE r1.png r2.png null:
0 # No difference - that's better

Why do these two differ in MD5? Because the date is in them...

identify -verbose r[12].png | grep -i date
date:create: 2015-03-03T14:57:26+00:00
date:modify: 2015-03-03T14:57:26+00:00
date:create: 2015-03-03T14:57:43+00:00
date:modify: 2015-03-03T14:57:43+00:00

Example 2

# Create PNG and identical GIF
convert -size 100x100 xc:red r.png
convert -size 100x100 xc:red r.gif

# Compare with MD5 sums
md5 r.png r.gif
MD5 (r.png) = 692ef06b62a15b799d5dc549b0dd3737
MD5 (r.gif) = 549feea78dc438924fbb3e0ef97dc0b3 # Ooops

# Compare properly
compare -metric AE r.gif r.png null:
0 # Identical

Example 3

# Create 8-bit PNG and 16-bit PNG
convert -size 100x100 xc:red PNG8:8.png
convert -size 100x100 xc:red PNG48:48.png

# MD5 sum them
md5 8.png 48.png
MD5 (8.png) = eb3fc9a06e1632c3b41ebb986b81a816
MD5 (48.png) = 32fdf1c30793a4fed941c91d27084e0a # Ooops

# Let ImageMagick compare them
compare -metric AE 8.png 48.png null:
0

Fuzzy Comparison of Images

As Kurt alludes to, this also leads to the possibility of doing a fuzzy compare of images. We can explore that like this:

# Create a grey image, 100x100 and put some noise in it
convert -size 100x100 xc:gray +noise gaussian noise.png

Sample Image

Now multiply all pixels by 1.01 to make them an imperceptible 1% brighter:

# Make pixels 1% brighter
convert noise.png -evaluate multiply 1.01 brighternoise.png

# ... and compare the statistics of the two images
identify -verbose *noise* | grep -E "^Image|mean"

Image: brighternoise.png
mean: 127.235 (0.498959) <--- The brighter image is, well, brighter
Image: noise.png
mean: 126.175 (0.494805)

And now compare them, a few different ways:

# Pixels may differ by up to 2% before being considered different
compare -fuzz 2% -metric AE noise.png brighternoise.png null:
0 # All pixel values within 2% between the 2 images

# Pixels may only differ by 0.5% before being considered different
compare -fuzz 0.5% -metric AE noise.png brighternoise.png null:
594 # 594 of the 10,000 pixels differ by more than 0.5%

# Calculate Root Mean Square Error (RMSE) to see how much pixels tend to differ
compare -metric RMSE noise.png brighternoise.png null:
278.96 (0.00425666) # On average, the pixels differ by 0.4% - i.e. hardly at all

Trim image with transparency around and know it's location

There are lots and lots of words but no image in your question so I am trying to guess what you want. I made this input image:

magick -size 100x100 xc:black -fill white -draw "rectangle 10,20 50,80" image.png

Sample Image

And I think you want to know the trim box, which is where it would trim to if you ran -trim:

magick image.png -format "%@" info:
41x61+10+20

So that's a 41x61 box with the top-left at (10,20).

efficient way to detect if an image is empty

Sure, divide the image by a set amount, for each set start a new thread to only check for non blank pixels (eg not white/transparent).

Create an event that fires (and sets a flag) only if a non empty pixel is found. Have each thread to check this flag (basically a while loop).

Ruby on rails Paper clip and ImageMagick issue

image_tag @pin.image.path

@pin.image is just the image info. you still need image_tag

Perform Resize and Fill canvas using Mogrify

I was able to accomplish the above by using the following:

mogrify -resize 300x300 *.jpg
mogrify -extent 300x300 -gravity Center -fill white *.jpg

This will make the largest dimension of the images to 300 pixels. It will then fill the canvas on the shorter dimension to 300 pixels and fill in the empty space with white.



Related Topics



Leave a reply



Submit