12,074,494 members (63,184 online)
alternative version

317.9K views
128 bookmarked
Posted

# Detect image skew angle and deskew image

, 13 Feb 2013 CPOL
 Rate this:
Deskew an image by converting it to grayscale + edges and rotating by the detected skew angle.

## So! What is image skew?

Using the above drawn figure as reference, I can say - the theta pointed out by that bluish arrow sign is the image skew .

To put it in proper words, the angle by which the image seems to be deviated from its perceived steady position is the image skew.

## Some pre-requisites for detecting the skew

Before detecting the skew, the first step is to differentiate between a text image and a regular image. By text image, I mean images which are scanned documents or screenshot of a text document, or in other words, images that contains letters and texts.

And a regular image in my terms is a picture, or photo of a scenery, or something drawn by Mr. Van Gogh and Co.

In one of my articles, I have covered the topic of a basic algorithm to differentiate between regular image and text images.

However, although the skew detection of a text image is relatively easier to implement, for a regular image, it's quite difficult and next to impossible in some cases. Suppose I have a picture of only the head part of my favourite celebrity Ms. Julia Roberts, ... there is no way to know from the image whether she really has her head slanted towards one direction, or the camera man who took the beautiful picture had a problem with the camera angle.

Therefore, for regular images, we have to make some sort of assumptions. The case we are going to discuss here will assume, the pictures to be deskewed will be framed. Which means, the pictures that we are dealing with are pictures taken from another picture having frames/border around them. You can refer to the application screenshot at the very top as an example. The screenshot you see is of a camera captured image of another picture having a thick white-ish border around it.

## The basic concept of detecting the skew

The main idea to detect skew for a regular image and a text image is the same. We have to first turn the pictures to Gray Scale.

Then, for regular (non text) images, we have to find the edges or feature lines of the image. There are many algorithms to detect the edges of an image, and in our case, we used the canny edge detection algorithm. We can wish to skip this part for text images.

The next step and the most important step is to cast rays from one side of the picture to the other, and by using the intersection info of the rays with the various parts of the images, we come up with a good skew angle.

As you can see from the above image, we have first converted the image (the one you see in the application screenshot) to its very basic feature lines/edges and have casted horizontal rays from one side to the other. The rays which we have casted (I mean the horizontal lines) intersect with the border/frame of the image. If I put the intersection points of the rays and the left edge of the picture in an X, Y plot (where X is horizontal and Y is vertical), I will end up with some sort of straight line curve that has a slope angle close to 2 degrees with respect to the Y axis. So, there you have it, your skew angle for the image in the application screenshot is close to 2 degrees or 0.035 radians.

This is more or less the basic concept used for detecting the skew of a regular framed image. You have to keep in mind this idea is applicable only to regular images and not text images.

By the way, the uploaded source code's skew detection algorithm does a little more than what I have explained above. What it does is - cast rays from left to right to intersect with the left edge, then top to bottom, then right to left, and then bottom to top. The algorithm considers the one with the most intersection points, and creating consistently occurring slopes as the edge to consider as the reference edge. For example, if the bottom to top rays intersects most with the bottom edge of the image and more frequently occurring slopes are observed, then that edge has the priority and the points of the bottom to top rays would be considered to be put in the X,Y plot. All these extra effort is just for the fact that, in some images, the border edges might be broken and not as beautifully framed fully around the image, like you are seeing in the application screenshot image. So, we'll have a set of rays with different slopes for such images, because the rays will go beyond the border edge wherever there is a broken edge line, and will create a different angle with another intersected point that lies somewhere inside the image bounded by the frame. So, the most occurring slopes (if two slopes have less than 0.0349 radians / 2.0 degrees difference between them - we'd consider the slopes as same valued) will be taken into consideration to detect the skew.

In order to detect the skew of text images, we don't have to worry too much about the picture having border edges or not. As mentioned before, we cast rays from left to right and find how many blackish pixels the rays intersect with. Then, we rotate the angle of the rays by a small amount and cast the rays again, and do the same process again and again.

The angle at which most white space is encountered (in other words, most black pixels are shot down, i.e., intersected), we consider that to be the skew angle. Most likely, we would start from 0 degree and go down to 90 degrees, and then again, from 0 degree go up to 90 degrees with the angle of the rays. Whenever the white ratio reaches the maximum peak and then starts to come down again, we stop immediately, and we know we have found our skew angle. This is the basic idea of detecting skew for text images.

The deskewing of an image is less of a trouble. All you need to do is rotate the image by the same amount of the skew, only to the reverse direction.

The code for the rotation is available in the ImageFunctions.h header file of the uploaded source.

However, if you want a real nice quality rotated image, you can use the wonderful `aarot` class by Mark Gordon (http://codeguru.earthweb.com/cpp/cpp/algorithms/math/article.php/c10677/Anti-Aliased-Image-Rotation-Aarot.htm). Since the rotation code inside this class performs antialiasing, the performance is a little slow, but the output image quality is very good.

## Using the code

In the uploaded source code, mainly two classes are used for detecting the skew. One class, the main class, is named `SkewManager`, which has code to detect the skew, and the other class is `ImageData`, which is just a wrapper for the bitmap bits and also keeps the width and the height of the image to be used by the `SkewManager` to apply its algorithms to the bitmap bits.

The `SkewManager` expects the bitmap that will be passed to be gray scaled. The blurring of the image to its edges (if required) is done inside the `ImageData` class.

Following is the example of the usage of the two classes (the `m_` prefixed variables as well as the `skewMan` variable are member variables of the `CScannedDocTestDoc` class).

```BOOL CScannedDocTestDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
m_Image.Destroy();

if(SUCCEEDED(hr))
{
int nPitch = m_Image.GetPitch();
int nWidth = m_Image.GetWidth();
int nHeight = m_Image.GetHeight();

int nBytesPerPixel = m_Image.GetBPP() / 8;
if(nBytesPerPixel)
{
byte* pGrayScaleBits = NULL;
// Get a gray scaled bitmap and bitmap bits from the original image
m_hBmpGrayScale = ImageFunctions::GetGrayScaleImage((HBITMAP)m_Image,
nWidth, nHeight, nBytesPerPixel, nPitch, &pGrayScaleBits);
if(pGrayScaleBits != NULL)
{
// Find out if the image is a regular image or text image
m_bTextImage = ImageFunctions::IsTextImage(pGrayScaleBits, nWidth, nHeight);

// get the skew angle
double angle = 0.0;
skewMan.GetSkewAngle(m_bTextImage, m_imgData, angle);
m_dSkewAngle = angle;
}
}
return TRUE;
}
return FALSE;
}```

## Points of interest

In order to achieve skew detection and deskewing of images, I had to go through a lot of trouble to perform basic image operations such as creating a gray scaled image, rotating an image etc., and I have put all those functionalities inside one header, ImageFunctions.h. Most of it was improvisation on already available materials in the Internet and MSDN. The canny edge detection algorithm can be found in the the header canny_edge.h.

## CSharpClient

This is a cut down version of the deskewimage code built to compile into a DLL.  A small C# demo application is included in the solution showing how to call the code contained in within the DLL,  pass in a file name to be analysed and the skew angle in radians is returned and displayed on the screen.

## Acknowledgements

• Kathey Marsden, Professor Richard J. Fateman
• for the OCRchie project - the foundation upon which, the text image skew detection algorithms of this article's codes are based upon.

• Also, thanks to Archie Russell, James Hopkin, and Cynthia Tian, who contributed significantly to the original design.
• Heath, M., Sarkar, S., Sanocki, T., and Bowyer, K. Comparison of edge detectors: a methodology and initial study, Computer Vision and Image Understanding 69 (1), 38-54, January 1998.
• Heath, M., Sarkar, S., Sanocki, T. and Bowyer, K.W. A Robust Visual, Method for Assessing the Relative Performance of Edge Detection Algorithms, IEEE Transactions on Pattern Analysis and Machine Intelligence 19 (12), 1338-1359, December 1997.
• for the excellent canny edge detection algorithm.

• for providing with reading materials related to deskewing text and framed images.

## History

• Article uploaded: 24 August, 2010.
• Article Updated 29 May 2012 CsharpClient Added
• Article Updated 14 February 2013 CSharpClient.zip 1.1 Added
Updated to compile in Visual Studio 2008 (Professional Edition)
Combined into a single VS Solution containing two projects (for easier debugging)
Minor Bug Fixes
Angle of 999 is now returned if the document could not be analysed (not a 8bpp image)
Added a Text box to show the name of the file analysed

## Share

 Chief Technology Officer Rational Technologies Bangladesh
If you are not in - you are out !
- Chapter 1

No Biography provided

## You may also be interested in...

 Re: thanks for the code but.. Mukit, Ataul7-Feb-13 6:21 Mukit, Ataul 7-Feb-13 6:21
 exception HRESULT 0x8007000B; which image format(s)? cinderbdt10-Sep-12 9:36 cinderbdt 10-Sep-12 9:36
 Re: exception HRESULT 0x8007000B; which image format(s)? Mukit, Ataul10-Sep-12 19:42 Mukit, Ataul 10-Sep-12 19:42
 Re: exception HRESULT 0x8007000B; which image format(s)? gupta_san417-Nov-12 20:11 gupta_san41 7-Nov-12 20:11
 Re: exception HRESULT 0x8007000B; which image format(s)? Mukit, Ataul7-Nov-12 20:20 Mukit, Ataul 7-Nov-12 20:20
 I need this project as dll to reference it to vb.net app sseerraajj27-May-12 18:03 sseerraajj 27-May-12 18:03
 Re: I need this project as dll to reference it to vb.net app Mukit, Ataul27-May-12 19:47 Mukit, Ataul 27-May-12 19:47
 Re: I need this project as dll to reference it to vb.net app sseerraajj29-May-12 0:02 sseerraajj 29-May-12 0:02
 Thank you very much! I tried too many times to do that but I failed.. I don’t know anything about C++ or MFC . Please and please and please, help me by creating the DLL (that works with .net) project and upload it. I do not need to deskew the image, but I need to know the angle and to know if the image is text image or not. These two functions I want it in the DLL, by sending the bitmap object to them. Function IsText(b as bitmap) as Boolean Function GetSkewAngle(b as bitmap) as single I hope you will help me! Thanks..
 Re: I need this project as dll to reference it to vb.net app Mukit, Ataul29-May-12 1:17 Mukit, Ataul 29-May-12 1:17
 Re: I need this project as dll to reference it to vb.net app Mukit, Ataul30-May-12 1:00 Mukit, Ataul 30-May-12 1:00
 Re: I need this project as dll to reference it to vb.net app tlhintoq5-Jun-12 12:48 tlhintoq 5-Jun-12 12:48
 Re: I need this project as dll to reference it to vb.net app Mukit, Ataul5-Jun-12 21:22 Mukit, Ataul 5-Jun-12 21:22
 Re: I need this project as dll to reference it to vb.net app tlhintoq6-Jun-12 4:00 tlhintoq 6-Jun-12 4:00
 Re: I need this project as dll to reference it to vb.net app sseerraajj7-Jun-12 6:42 sseerraajj 7-Jun-12 6:42
 Re: I need this project as dll to reference it to vb.net app Mukit, Ataul7-Jun-12 10:33 Mukit, Ataul 7-Jun-12 10:33
 Re: I need this project as dll to reference it to vb.net app sseerraajj9-Jun-12 1:03 sseerraajj 9-Jun-12 1:03
 My vote of 5 manoj kumar choubey26-Feb-12 21:06 manoj kumar choubey 26-Feb-12 21:06
 Re: My vote of 5 Mukit, Ataul26-Feb-12 21:14 Mukit, Ataul 26-Feb-12 21:14
 How to use aarot to rotate the image? Member 19710844-Aug-11 15:31 Member 1971084 4-Aug-11 15:31
 Re: How to use aarot to rotate the image? Member 19710844-Aug-11 17:51 Member 1971084 4-Aug-11 17:51
 Re: How to use aarot to rotate the image? Mukit, Ataul6-Aug-11 21:47 Mukit, Ataul 6-Aug-11 21:47
 My vote of 5 Member 191619813-Oct-10 19:30 Member 1916198 13-Oct-10 19:30
 Re: My vote of 5 Mukit, Ataul13-Oct-10 19:57 Mukit, Ataul 13-Oct-10 19:57
 Cool Stuff Harrison H6-Oct-10 11:52 Harrison H 6-Oct-10 11:52
 Re: Cool Stuff Mukit, Ataul18-Oct-10 19:41 Mukit, Ataul 18-Oct-10 19:41
 Last Visit: 31-Dec-99 19:00     Last Update: 11-Feb-16 5:06 Refresh « Prev123 Next »