付丽叶变换后的图,主要特点是中间有两条十字线,一横一竖,可能还有其他的线,研究不深,暂不做评论。十字线中间是亮线。如何获取该亮线的方程呢?假定中心点在图的中心,根据直线方程:
y=kx+b (1)
直线过点P(w/2,h/2),代入公式(1)得:
b=(h-kw)/2 (2)
因此直线方程可表示为:
y = k(x - w/2) + h/2 (3)
绕点P旋转,旋转步长为0.1度,最大倾角45度,因此总步长为450,求每个步长对应的直线,统计该线上的点的灰度累加值。越白的像素,灰度值越大,累加值最大的线为所求直线。
//倾斜校正
void CBmptestApp::OnLeanAdjust(){
char* sMax = new char[100];
int w = objCDib->GetWidth();
int h = objCDib->GetHeight();
DWORD size = w * h;
BYTE* img = objCDib->GetData();
BYTE* ftImg = new BYTE[size];
memcpy(ftImg,img,size);
CDC* pDC = m_pMainWnd->GetDC();
int s = 27; /*工具条高度*/
double pi = 3.1415926;
int count = 450; //每次旋转0.1度
long lines[450];
for(int i=0;i<450;i++){
lines[i] = 0;
}
AfxMessageBox("here0");
for(i=0;i<count;i++){
for(int j=0;j<w/2;j++){
int x = w/2 + j;
int y = tan(0.1*i*pi/180) * (x-w/2) + h/2;
lines[i] += ftImg[w*y +x];
}
}
AfxMessageBox("here1");
int maxV = 0;
int maxIdx = 0;
for(i=0;i<count;i++){
if(lines[i] > maxV){
maxV = lines[i];
maxIdx = i;
}
}
sprintf(sMax,"maxV=%d,maxIdx=%d", maxV, maxIdx);
AfxMessageBox(sMax);
delete[] sMax;
//标识倾斜线
int h0 = h/2 + w/2 * tan(0.1*maxIdx*pi/180) + s;
CPen* pPen = new CPen;
pPen->CreatePen(PS_SOLID,2,RGB(255,0,0));
// 选中新画笔
CGdiObject* pOldPen = pDC->SelectObject(pPen);
pDC->MoveTo(0,0);
pDC->LineTo(w,0);
pDC->MoveTo(0,s);
pDC->LineTo(w,s);
pDC->MoveTo(w/2,h/2+s);
pDC->LineTo(w,h0);
pDC->MoveTo(w/2,h/2+s);
pDC->LineTo(w,h/2+s);
// 选回以前的画笔
pDC->SelectObject(pOldPen);
delete pPen;
//旋转图片
BYTE* newImg =new BYTE[size];
rotateImage(ftImg, w, h, newImg, w, h, -0.1*maxIdx);
int rv = ShowGrayImg(pDC,3,s,newImg,w,h,NULL,NULL);
delete[] ftImg;
}
原图:
标注水平线和亮线的图:
旋转后:
这只是一个简单的测试,仅仅根据图像的特征来求的直线,实际上是说:最亮的一条线怎么得到?