1. 程式人生 > >光條中心線提取-Steger演算法(基於Hessian矩陣)

光條中心線提取-Steger演算法(基於Hessian矩陣)

採用結構光進行掃描檢測時,需要提取鐳射條紋的中心線,本文采用經典的Steger演算法提取光條中心。

Steger演算法原理

Steger演算法基於Hessian矩陣,能夠實現光條中心亞畫素精度定位:首先通過Hessian矩陣能夠得到光條的法線方向,然後在法線方向利用泰勒展開得到亞畫素位置。
對於影象中鐳射條紋上的任意一點(x,y),Hessian矩陣可以表示為:

H(x,y)=[rxxrxyrxyryy]
其中rxx表示影象沿x的二階偏導數,其他引數類似。需要注意的是在求Hessian矩陣之前需要對影象進行高斯濾波,高斯濾波時,根據文獻[1]中,設定高斯方差σ<w3,其中w
為光條寬度。Hessian矩陣最大特徵值對應的特徵向量對應於光條的法線方向,用(nx,ny) 表示,以點(x0,y0) 為基準點,則光條中心的亞畫素座標為:
(px,py)=(x0+tnxy0+tny)
公式中
t=nxrx+nyryn2xrxx+2nxnyrxy+n2yryy
如果(tnx,tny)[0.5,0.5]×[0.5,0.5] ,即一階導數為零的點位於當前畫素內,且(nx,ny) 方向的二階導數大於指定的閾值,則該點(x0,y0) 為光條的中心點,(px,py) 則為亞畫素座標。

示例程式碼

根據Steger演算法的原理,藉助opencv的Mat資料結構,實現Steger演算法如下:

void StegerLine()
{ 
    Mat img0 = imread("image_0.png", 1);
    Mat img;
    cvtColor(img0, img0, CV_BGR2GRAY);
    img = img0.clone();

    //高斯濾波
    img.convertTo(img, CV_32FC1);
    GaussianBlur(img, img, Size(0, 0), 6, 6);

    //一階偏導數
    Mat m1, m2;
    m1 = (Mat_<float>(1, 2) << 1, -1);  //x偏導
m2 = (Mat_<float>(2, 1) << 1, -1); //y偏導 Mat dx, dy; filter2D(img, dx, CV_32FC1, m1); filter2D(img, dy, CV_32FC1, m2); //二階偏導數 Mat m3, m4, m5; m3 = (Mat_<float>(1, 3) << 1, -2, 1); //二階x偏導 m4 = (Mat_<float>(3, 1) << 1, -2, 1); //二階y偏導 m5 = (Mat_<float>(2, 2) << 1, -1, -1, 1); //二階xy偏導 Mat dxx, dyy, dxy; filter2D(img, dxx, CV_32FC1, m3); filter2D(img, dyy, CV_32FC1, m4); filter2D(img, dxy, CV_32FC1, m5); //hessian矩陣 double maxD = -1; int imgcol = img.cols; int imgrow = img.rows; vector<double> Pt; for (int i=0;i<imgcol;i++) { for (int j=0;j<imgrow;j++) { if (img0.at<uchar>(j,i)>200) { Mat hessian(2, 2, CV_32FC1); hessian.at<float>(0, 0) = dxx.at<float>(j, i); hessian.at<float>(0, 1) = dxy.at<float>(j, i); hessian.at<float>(1, 0) = dxy.at<float>(j, i); hessian.at<float>(1, 1) = dyy.at<float>(j, i); Mat eValue; Mat eVectors; eigen(hessian, eValue, eVectors); double nx, ny; double fmaxD = 0; if (fabs(eValue.at<float>(0,0))>= fabs(eValue.at<float>(1,0))) //求特徵值最大時對應的特徵向量 { nx = eVectors.at<float>(0, 0); ny = eVectors.at<float>(0, 1); fmaxD = eValue.at<float>(0, 0); } else { nx = eVectors.at<float>(1, 0); ny = eVectors.at<float>(1, 1); fmaxD = eValue.at<float>(1, 0); } double t = -(nx*dx.at<float>(j, i) + ny*dy.at<float>(j, i)) / (nx*nx*dxx.at<float>(j,i)+2*nx*ny*dxy.at<float>(j,i)+ny*ny*dyy.at<float>(j,i)); if (fabs(t*nx)<=0.5 && fabs(t*ny)<=0.5) { Pt.push_back(i); Pt.push_back(j); } } } } for (int k = 0;k<Pt.size()/2;k++) { Point rpt; rpt.x = Pt[2 * k + 0]; rpt.y = Pt[2 * k + 1]; circle(img0, rpt, 1, Scalar(0, 0, 255)); } imshow("result", img0); waitKey(0); }

示例結果

這裡寫圖片描述

  1. Steger C. An unbiased detector of curvilinear structures. IEEE Trans Pattern Anal Mach Intell[J]. IEEE Transactions on Pattern Analysis & Machine Intelligence, 1998, 20(2):113-125.