Click here to Skip to main content
15,881,172 members
Articles / Desktop Programming / MFC

Detect image skew angle and deskew image

,
Rate me:
Please Sign up or sign in to vote.
4.95/5 (41 votes)
13 Feb 2013CPOL8 min read 231.1K   17K   137  
Deskew an image by converting it to grayscale + edges and rotating by the detected skew angle.
// ImageData.cpp: implementation of the ImageData class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ImageData.h"
#include "canny_edge.h"

#include "../ImageFunctions.h"


ImageData::ImageData()
{
	m_data = NULL;
	m_edgeData = NULL;
	m_id = -1;
	m_allocated = false;
	ResetErrorCode();					
}

ImageData::~ImageData()
{
	Cleanup();	
}

void ImageData::Cleanup()
{
	if(m_allocated)
	{
		DeleteData();
	}
	else
	{
		m_data = NULL;
	}
}

bool ImageData::Load(byte* data, unsigned int width, unsigned int height, int bytesPerPixel)
{
	bool bRet = false;
	if(data != NULL)
	{
		m_data = data;
		m_width = width;
		m_height = height;
		m_bytesPerPixel = bytesPerPixel;
		bRet = true;
	}	
	return bRet;
}



ImageData* ImageData::Clone()
{
	ImageData* img_data = new ImageData;		
	img_data->m_bytesPerPixel = m_bytesPerPixel;
	img_data->AllocDataSpace(GetWidth(), GetHeight(), GetBytesPerPixel() * 8);
	memcpy(img_data->m_data, m_data, GetSize());		
	img_data->m_width = m_width;
	img_data->m_height = m_height;

	return img_data;
}

bool ImageData::BlurToEdges(int slices/*=0*/)
{
	bool bRet = false;		

	if(m_edgeData != NULL)
	{
		// already blurred
		return true;
	}

	if(m_data == NULL)
		return false;
	
	byte* edgeData = NULL;
		
	if(slices == 0)
	{		
		canny(m_data, GetHeight(), GetWidth(), (float)10, (float)0.1, (float)0.87, &edgeData, NULL);
		Cleanup();

		m_data = edgeData;			
		m_allocated = true;
		bRet = true;
	}
	else if(slices == 1)
	{
		int topHalfHeight = GetHeight() / 2;
		int bottomHalfHeight = GetHeight() - topHalfHeight;
		
		canny(m_data, topHalfHeight, GetWidth(), (float)10, (float)0.1, (float)0.9, &edgeData, NULL);
		Cleanup();

		memcpy(m_data, edgeData, GetWidth() * topHalfHeight);
		free(edgeData);
		
		canny(m_data + (GetWidth() * topHalfHeight), bottomHalfHeight, GetWidth(), (float)10, (float)0.1, (float)0.9, &edgeData, NULL);
		memcpy(m_data + (GetWidth() * topHalfHeight), edgeData, GetWidth() * bottomHalfHeight);
		free(edgeData);									
		
		m_allocated = true;
		bRet = true;
	}
	
	m_edgeData = m_data;
	
	return bRet;
}
	
bool ImageData::AllocDataSpace(int w, int h, unsigned int bitdepth/*=24*/)
{   
	unsigned int size = ImageFunctions::GetDataSize(w, h, bitdepth);
	m_data = new BYTE [size];
	if (m_data)
	{     
	  m_width = w;
	  m_height = h;  
	  m_allocated = true;	  
	}
   
	return m_data ? true : false;
}

unsigned int ImageData::GetSize()
{
	return ImageFunctions::GetDataSize(GetWidth(), GetHeight(), GetBytesPerPixel() * 8);
}

byte* ImageData::getpixel(byte* pixelBuf, int i, int j)
{
	byte* rowData = &pixelBuf[j * GetRowStride()];
	rowData = rowData + i * GetBytesPerPixel();
	return rowData;
}

void ImageData::putpixel(byte* pixelBuf, int i, int j, byte* color)
{
	byte* rowData = &pixelBuf[j * GetRowStride()];
	rowData = rowData + i * GetBytesPerPixel();
	rowData[0] = color[0];
	rowData[1] = color[1];
	rowData[2] = color[2];
}

void ImageData::BlurToEdgesRobust()
{
	if(m_edgeData != NULL)
		return;

	byte* edges = new byte [GetSize()];

	byte *color, *color1, *color2;
	byte makecolor[3] = {128, 128, 128};
	
	byte r,g,b, r1, g1, b1, r2, g2, b2;
	double bb = 85;
	int w = GetWidth();
	int h = GetHeight();
	for(int i=0;i<w-1;i++)
	{
		for(int j=0;j<h-1;j++)
		{
			color=getpixel(GetData(), i,j);
			r=getr32(color);
			g=getg32(color);
			b=getb32(color);
     
			color1=getpixel(GetData(), i+1,j);
			r1=getr32(color1);
			g1=getg32(color1);
			b1=getb32(color1);

			color2=getpixel(GetData(), i,j+1);
			r2=getr32(color2);
			g2=getg32(color2);
			b2=getb32(color2);
     
			double s1 = sqrt((double)(r-r1)*(r-r1)+(g-g1)*(g-g1)+(b-b1)*(b-b1));
			double s2 = sqrt((double)(r-r2)*(r-r2)+(g-g2)*(g-g2)+(b-b2)*(b-b2));
			if((s1>=bb)||(s2>=bb))
			{
				int clr = 0;
				makecolor[0] = clr;
				makecolor[1] = clr;
				makecolor[2] = clr;
				putpixel(edges,i,j,makecolor);
     
			}
			else
			{
			 	int clr = 255;
				makecolor[0] = clr;
				makecolor[1] = clr;
				makecolor[2] = clr;
				putpixel(edges,i,j,makecolor);
			}
		 }
	}

	Cleanup();
	m_data = edges;
	m_edgeData = m_data;
	m_allocated = true;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Kotha Technologies
Bangladesh Bangladesh
If you are not in - you are out !
- Chapter 1

Written By
Network Administrator
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions