Detect the Angle of a Line in an Image






4.60/5 (15 votes)
How to detect the angle of a line in an image
Introduction
Today's image processing technology helps us in many areas such as determining tumors, text extraction, checking images,... In this algorithm, we can get the angle of a line in an image. Of course, there are several ways to do this with advanced algorithms, but this is a simple algorithm.
Features
- Works in real images with several colors
- Simple to implement
- Gets the length of the line
- Very light-weight code
Source Code
I have commented the code clearly. First, we must define a global CImage
and then load the image file from the hard disk:
CImage i;
After that, we need to draw an image when cleared with the OnPaint()
function:
void CDetectangleoflineDlg::OnPaint()
{
if(!i.IsNull()){//image isn't null
//get handle device content from this dialog
CClientDC dc(this);
//draw picture in dialog background
i.BitBlt(dc.m_hDC,0,0,SRCCOPY);
}
}
Next, we load the image:
void CDetectangleoflineDlg::OnBnClickedButton1()//load image
{
CFileDialog f(1);//to call open file dialog
TCHAR tc[260];
CString s;
GetCurrentDirectory(260,tc);
s=tc;
if(f.DoModal()==IDOK){//image selected
if(!i.IsNull())//image isn't null
i.Destroy();//destroy image
i.Load(f.GetFolderPath()+_T("\\")+f.GetFileName());
//load image to i (CImage)
OnPaint();//call draw image
b.EnableWindow(1);
}
}
Finally, we use the Process algorithm to determine the angle:
void CDetectangleoflineDlg::OnBnClickedButton2()//process
{
CImage i1;
i1=i;//copy 'i' to 'i1'
CDC cdc;//to get device content of 'i1'
//get device content of i to cdc to draw or getbitmap
cdc.Attach(i1.GetDC());
//define pens and choose them in 'cdc'
CPen p(PS_SOLID,1,RGB(255,255,0)),p1(PS_SOLID,1,RGB(0,0,255));
cdc.SelectObject(&p);
//define necessary variables
register int x1,x2,y1,y2;
x1=x2=y1=y2=-1;
double pi=3.1415926535;
register long r,g,b,r1,g1,b1;
register COLORREF c,c1;
//'tol':toleranc;defference between colors.
//'d':the most width of line
register int tol=30,d=20;
//get first color as background color
c=i1.GetPixel(0,0);
r=GetRValue(c);
g=GetGValue(c);
b=GetBValue(c);
bool ar[600][450];
//clear the array
for(register int y=0;y<i.GetHeight();y++)for(register int x=0;x<i.GetWidth();x++)
ar[y][x]=0;
//convert the image to grey status
for(register int y=0;y<i.GetHeight();y++)
for(register int x=0;x<i.GetWidth();x++){
c1=i.GetPixel(x,y);r1=GetRValue(c1);g1=GetGValue(c1);b1=GetBValue(c1);
if((abs(r-r1)>tol)&&(abs(g-g1)>tol)&&(abs(b-b1)>tol))
ar[y][x]=1;
else ar[y][x]=0;
}
//process to detect the arc
for(register int y=0;y<i.GetHeight();y++)
for(register int x=0;x<i.GetWidth();x++){
if(ar[y][x]){//line detect
if(x1==-1){//first point of line
x1=x2=x;y1=y2=y;
}else if(sqrt(pow(x-x2,2.0)+pow(y-y2,2.0))<=d){//next point
x2=x;y2=y;
ar[y][x]=1;
}else ar[y][x]=0;
}
}
//draw the detected arc
for(register int y=0;y<i.GetHeight();y++)
for(register int x=0;x<i.GetWidth();x++)
if(ar[y][x])
cdc.SetPixel(x,y,RGB(255,255,0));
//compute line's length width: r^2=x^2+y^2
register float radius=sqrt(pow(x1-x2,2.0)+pow(y1-y2,2.0));
//end:to get angle of line
float t=atan((float)(y2-y1)/(x2-x1))*180/pi;
cdc.SelectObject(&p1);//set 'p1' for blue color
//draw lines around Line
cdc.MoveTo((x1+x2)/2-radius/2,(y1+y2)/2);
cdc.LineTo((x1+x2)/2+radius/2,(y1+y2)/2);
cdc.MoveTo((x1+x2)/2,(y1+y2)/2-radius/2);
cdc.LineTo((x1+x2)/2,(y1+y2)/2+radius/2);
CClientDC dc(this);//get device content of dialog to draw 'i1'
if(t>=-180&&t<=180){//to skip error
//convert 't'int to 's'CString
char a[10]="";
itoa(t,a,10);
CString s;
s=a;
dc.TextOut(0,300,s+_T(" degree"));
//print the result
}
i1.ReleaseDC();
cdc.Detach();
i1.BitBlt(dc.m_hDC,i.GetWidth()+10,0,SRCCOPY);//draw 'i1'
i1.Destroy();
}
Algorithm
First, we need a color for the backcolor
, 'c
', and a color to get the points of the image, 'c1
'. We have to find the first and last points of the line (x1, y1)
and (x2, y2)
. We set -1 as the default value of x1
. This means we don't find the first point yet. For detecting the first point, we move and look around the image at (x, y)
. When c1!=c && x==-1
, we find (x1, y1)
. We imagine a virtual radius like 'd
' and with a default value 10
. After that, we move and look again, and when c!=c && sqrt((x-x2)^2+(y-y2)^2))<=d
, this point is related to the previous point and line. We continue this till the end. Finally, we'll find (x1,y2),(x2,y2)
and we can get the length of the line and get the angle of the line with arctan
.
teta=arttan((y2-y1)/(x2-x1))