Hacker News new | comments | ask | show | jobs | submit login

This strikes close to home for me, because I've done this "by hand" quite a number of times, using some interactive Gimp filters, with very good results. I've been able to take a perspective photo of a curved page lying on a desk, get it almost perfectly straight, and threshold it to clean black and white or sharp gray scale.

Here is my very quick and dirty manual job of the same example page:


Literally less than five minutes.

First I cropped the image. Then duplicated the layer. Blurred the top layer (Gaussian, 50 radius). Then flipped to Divide mode and merged the visible layers. This leveled the lightness quite well, almost completely eliminating the shadow over he right side of the page and all other lighting differences. There is a hint of the edge of the shadow still present because it is such a sharp contrast; but that can be eliminated in an adjustment of the intensity curves. In such cases it may be helpful to experiment with smaller blur radii, too.

I then did a perspective transform in the lateral direction, squeezing the left side top-bottom and expanding the right, resulting in the warp now being approximately horizontal. (The perspective transform is not just for adding a perspective effect; it is also useful reversing perspective!)

Finally, I used the Curve Bend (with its horrible interactive interface and awful preview) to warp in a compensating way. Basically, the idea is to draw an upper and lower curve which is the opposite of the curve on the page. I made two attempts, keeping the results of the second.

If the preview of this tool wasn't a ridiculous, inscrutable thumbnail, it would be possible to do an excellent job in one attempt, probably close to perfect.

Because the page is evenly light thanks to the divide-by-blurred layer trick, it will nicely threshold to black and white, or a narrow grayscale range.

Hence the tagline on the blog: "Why do it by hand if you can code it in just quadruple the time?" :)

More work up front, less work afterwards.

I really enjoyed the various random thoughts in the wrapping up section of this post, thank you a good read!

Divide by blur is very crafty. Will have to give that a shot next time I have a similar need in Photoshop.

As a comic artist working with scanned images, the "divide by blur" trick is going to save me significant effort in the future.

THIS is exactly the sort of insight I wish I would get when I click one of those "one weird trick" links!

Then you might also like the Grain Extract and Grain Merge layer modes in GIMP (not sure if they exist in photoshop).

They're a bit obscure if you don't know how they work, basically Grain Extract subtracts the layers and adds 128, so you get sort of a fake 8-bit signed integer. Grain Merge does the opposite (add two layers, subtract 128).

I haven't tried to divide-by-blur (but I'm going to :) ). Grain Extract on the other hand, allows to subtract-with-blur, which is more like what I'd do if I were to code such an algorithm myself (the operation is roughly what the Unsharp Mask filter does, but you get a bit more control). Still I'm curious to see how divide-by-blur differs in its results.

Check this Flickr-post which has a nice explanation of using Grain Extract (used for a different purpose here, it's really a very interesting and versatile trick, only discovered it last week myself):


I should mention that I know about Grain Extract's subtraction operation. I've used it for "leveling" also.

Subtraction would be fine if the data were logarithmic: that is to say, if the intensity information we are operating on represents decibels. We figure out the low frequency signal's "floor" over each area of the image, and simply subtract those decibels.

Division is better on the assumption that the intensity values of the pixels are linear. Division of linear samples is subtraction, in the decibel scale.

The right way is somewhere in between, because in RGB displays, pixels are put through some gamma curve. They are neither linear nor logarithmic.

Reminds me of the "frequency separation" [1] technique, used a lot in the high end retouching business.

[1] https://fstoppers.com/post-production/ultimate-guide-frequen...

Echoing what the other comment said, blurring and setting as Divide has never occurred to me. I just tried it and it does a very good job at leveling. Nice one.

The radius of 50 was too large. Reason being: I'm used to working with much higher resolution scans, and without high contrast shadows across them. A blur radius of around 15 does a good job of eliminating the shadow edge in this image after the divide. What we're basically doing is a high pass filter. The radius of 50 is too low a frequency; it lets through the shadow edge noticeably.

By the way, here is a useful trick: blurred layer in Divide mode, plus vary the opacity. You can reduce the amount of contrast between light and dark areas in an image without completely leveling it. Works well with low opacity levels (just a slight blend of the Divide mode layer). If you have a picture with areas that are too dark and too bright, a touch of this can help. High radii tend to work well, with blends of up to 20% or so.

For me, this does what I want Retinex to do! Only better, with intuitive control parameters and predictable results.

Just came up with an improvement to the above: Divide by Blur, with 0-20% blend. However, not over the RGB image, but only over its its L (lightness) channel in a LAB colorspace separation. Then, recompose. That looks really natural for brightening the shadows and reducing highlights.

Look at the picture of the little girl peering out of the back window of a truck on NASA's Retinex page, as enhanced by Retinex:


Now my version:


The reflection in the glass is brought out in a less cheesy way that you might not guess is the result of processing, if you don't already know.

I did a decompose of the image to the LAB color space (Colors/Components/Decompose...). Then I used a blur radius of 200 pixels on a copy of the L layer. Put into Divide mode and blended at a bit over 30%, and recomposed from LAB back to the original RGB image.

(That's a simplification; of course I had to struggle with Gimp to preserve the ID of the L layer, which is destroyed by a straight "merge layer down" after which the recompose operation fails with an error. I in fact made two copies of the L layer, and did the processing and merge operation between those two copies. Then I did a select all to copy the resulting layer to the clipboard and pasted that into the original L layer to replace it.)

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact