付丽叶变换后的图,主要特点是中间有两条十字线,一横一竖,可能还有其他的线,研究不深,暂不做评论。十字线中间是亮线。如何获取该亮线的方程呢?假定中心点在图的中心,根据直线方程:
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; }
原图:
标注水平线和亮线的图:
旋转后:
这只是一个简单的测试,仅仅根据图像的特征来求的直线,实际上是说:最亮的一条线怎么得到?