akorentlab / leptonica

Automatically exported from code.google.com/p/leptonica
0 stars 0 forks source link

pixRotate() leaves shear lines on 1 bpp images #20

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Try rotating an image using
pixd = pixRotate (pixs, radians, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, w, h);

What is the expected output? What do you see instead?
Image is rotated around lower left corner instead of center.
The comment for pixRotate states:
(1) Rotation is about the center of the image.

What version of the product are you using? On what operating system?
leptonlib-1.63.
Microsoft Visual Studio 2008 SP1 with latest updates also applied.
Windows XP Pro SP3.

Please provide any additional information below.
Attached are a sample 300 dpi image, and its deskewed version.

Also attached is a multipage tiff that shows the differences (this was
designed more for images with FEW differences so it's a bit pyschedelic).
The first page shows red for new pixels, green for removed pixels. The 2nd
page is the new image, the 3rd is the original image, the 4th is just the
added pixels, and the 5th is just the erased pixels. (The source for
binImageDiff() is in the LeptonicaVS2008Samples.zip I sent you for
inclusion in the next release).

You can see that the image is mostly unchanged near the lower left corner,
whereas big differences occur near the top right. If pixRotate() was
rotating about the center, I would expect to see the unchanged pixels near
the center instead.

Also note the artifacts introduced by doing L_ROTATE_AREA_MAP (which
implicitly converts the 1bpp image to gray), and then saving the result as
IFF_TIFF_G4.
Text lines that start with:

 causes; and accordingly
 right, it is their duty
 of repeated injuries
 to tyrants only.
 He has dissolved

have noticeable horizontal shifts in the middle of them.

Even using 600 dpi images doesn't eliminate the artifacts.

I've found that instead of directly rotating 1bpp images, its better to
convert explicitly to gray, block convolve, rotate using area mapping, and
then theshold back down to 1bpp.

Original issue reported on code.google.com by tomp2...@gmail.com on 1 Dec 2009 at 10:04

Attachments:

GoogleCodeExporter commented 9 years ago
Ah... actually after further investigation with rotating larger angles (like 5
degrees), I discovered that the problem is NOT with pixRotate() but with my
binImageDiff() routine. That was creating the diff image by starting out with 
the
original image. This means the width & height are wrong unless you center that 
image
within the rotated image's width and height. Sorry for false alarm.

However, the artifacts are still there when you directly rotate 1bpp images.

Original comment by tomp2...@gmail.com on 6 Dec 2009 at 10:35

GoogleCodeExporter commented 9 years ago
You probably thought I forgot about this...

You are right: when you rotate a 1 bpp image you get horizontal and vertical 
shear
lines.  The horizontal ones are most visible when they go through a line of 
text,
making the text even look tilted in some situations.  And the eye is very 
sensitive
to a line of shears, even a single pixel.

There are various ways that have been suggested to prevent this.  One way is to
choose the horizontal shear lines to be in the white background between text 
lines
(for horizontal text).  Another is to put some randomness into the shearing, so 
that
you don't get full lines of shear.

Your suggestion is actually better.  Here is a simple set of operations that 
does a
pretty good job on your declaration of independence.  I've added in some unsharp
masking to counter the blurring in the convolution.

    angletorad = 3.14159 / 180.;
    pix1 = pixRead("doi.tif");
    pix2 = pixConvertTo8(pix1, 0);
    pix3 = pixBlockconv(pix2, 1, 1);
    pixFindSkewSweepAndSearch(pix1, &angle, &conf, 2, 2, 3.0, 0.5, 0.01);
    radangle = angletorad * angle;
    pix4 = pixRotateAM(pix3, radangle, L_BRING_IN_WHITE);
    pix5 = pixUnsharpMasking(pix4, 1, 1.0);
    pix6 = pixThresholdToBinary(pix5, 128);
    pix7 = pixRotateBySampling(pix1, 0, 0, radangle, L_BRING_IN_WHITE);
    pixDisplay(pix6, 100, 100);
    pixDisplay(pix7, 600, 100);
    pixWrite("junkpix6", pix6, IFF_PNG);
    pixWrite("junkpix7", pix7, IFF_PNG);

With some playing around to choose parameters, this would certainly be nice 
enough to
put into the library.

Original comment by dan.bloo...@gmail.com on 4 Jan 2010 at 5:08

GoogleCodeExporter commented 9 years ago
This feature has been added to 1.65.
The function is pixRotateBinaryNice().

Original comment by dan.bloo...@gmail.com on 8 Apr 2010 at 6:00