欧美另类日韩中文色综合,天堂va亚洲va欧美va国产,www.av在线播放,大香视频伊人精品75,奇米777888,欧美日本道免费二区三区,中文字幕亚洲综久久2021

OpenCV 學(xué)習(xí)(直線擬合) -電腦資料

電腦資料 時(shí)間:2019-01-01 我要投稿
【www.lotusphilosophies.com - 電腦資料】

   

OpenCV 學(xué)習(xí)(直線擬合)

    Hough 變換可以提取圖像中的直線,

OpenCV 學(xué)習(xí)(直線擬合)

。但是提取的直線的精度不高。而很多場(chǎng)合下,我們需要精確的估計(jì)直線的參數(shù),這時(shí)就需要進(jìn)行直線擬合。

    直線擬合的方法很多,比如一元線性回歸就是一種最簡(jiǎn)單的直線擬合方法。但是這種方法不適合用于提取圖像中的直線。因?yàn)檫@種算法假設(shè)每個(gè)數(shù)據(jù)點(diǎn)的X 坐標(biāo)是準(zhǔn)確的,Y 坐標(biāo)是帶有高斯噪聲的?蓪(shí)際上,圖像中的每個(gè)數(shù)據(jù)點(diǎn)的XY 坐標(biāo)都是帶有噪聲的。

    下面就來講講適用于提取圖像中直線的直線擬合算法。

    一個(gè)點(diǎn)(xi,yi)到直線的距離用ri來表示。

    所謂直線擬合,就是找到一條直線,使得:

    ∑ρ(ri)

    最小。

    ρ(r)是距離函數(shù)。ρ(r)函數(shù)取不同的形式,對(duì)應(yīng)不同的直線擬合方法。OpenCV 中支持 6 種不同的ρ(r)函數(shù)形式。分別是:

    CV_DIST_L2

    ρ(r)=r22

    這種方法是以距離平方和為擬合判據(jù)。也就是常見的最小二乘擬合算法,運(yùn)行速度也最快。但是這個(gè)算法也有個(gè)很大的問題,就是當(dāng)干擾點(diǎn)離直線較遠(yuǎn)時(shí),一個(gè)干擾點(diǎn)就可能將整條擬合直線拉偏了。簡(jiǎn)單的說就是對(duì)干擾點(diǎn)的魯棒性不夠。所以后來又提出了其他的函數(shù)。

    CV_DIST_L1

    ρ(r)=r

    CV_DIST_L12

    ρ(r)=2(1+r22??????√?1)

    CV_DIST_FAIR

    ρ(r)=C2(rC?log(1+rC))

    其中 C = 1.3998

    CV_DIST_WELSCH

    ρ(r)=C22(1?exp(?(rC)2))

    其中 C = 2.9846

    CV_DIST_HUBER

    ρ(r)={r22C(r?C2)if r

    其中 C = 1.345

    后面這 5 種函數(shù)我知道第一種,其他的不知道是怎么來的。OpenCV 的幫助文檔給出了一個(gè)鏈接:M-estimator

    但是這個(gè)頁面也被墻了。

    下面來說說 OpenCV 提供的直線擬合函數(shù)。函數(shù)原型如下:

<code class="hljs cs">void fitLine( InputArray points,     OutputArray line,     int distType,    double param,     double reps,     double aeps );</code>

    distType 指定擬合函數(shù)的類型,可以取 CV_DIST_L2、CV_DIST_L1、CV_DIST_L12、CV_DIST_FAIR、CV_DIST_WELSCH、CV_DIST_HUBER。

    param 就是 CV_DIST_FAIR、CV_DIST_WELSCH、CV_DIST_HUBER 公式中的C。如果取 0,則程序自動(dòng)選取合適的值。

    reps 表示直線到原點(diǎn)距離的精度,建議取 0.01。

    aeps 表示直線角度的精度,建議取 0.01。

    計(jì)算出的直線信息存放在 line 中,為 cv::Vec4f 類型。line[0]、line[1] 存放的是直線的方向向量。line[2]、line[3] 存放的是直線上一個(gè)點(diǎn)的坐標(biāo)。

    如果直線用y=kx+b來表示,那么 k = line[1]/line[0],b = line[3] - k * line[2]。

    如果直線用ρ=xcosθ+ysinθ來表示, 那么θ=arctank+π2

    下面是個(gè)測(cè)試圖像:

   

    圖像中有一條直線和一些干擾圖案,

電腦資料

OpenCV 學(xué)習(xí)(直線擬合)》(http://www.lotusphilosophies.com)。<喎?http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPs/Cw+a1xLT6wuu/ydLUtNPNvM/x1tDM4cihs/bQ6NKqtcTX+LHqteOhozwvcD4NCjxwcmUgY2xhc3M9"brush:java;">std::vectorgetPoints(cv::Mat &image, int value){ int nl = image.rows; // number of lines int nc = image.cols * image.channels(); std::vectorpoints; for (int j = 0; j < nl; j++) { uchar* data = image.ptr(j); for (int i = 0; i < nc; i++) { if(data[i] == value) { points.push_back(cv::Point(i, j)); } } } return points;}

    下面的代碼可以在圖中畫一條直線。

<code class="hljs mel">void drawLine(cv::Mat &image, double theta, double rho, cv::Scalar color){    if (theta < PI/4. || theta > 3.*PI/4.)// ~vertical line    {        cv::Point pt1(rho/cos(theta), 0);        cv::Point pt2((rho - image.rows * sin(theta))/cos(theta), image.rows);        cv::line( image, pt1, pt2, cv::Scalar(255), 1);    }    else    {        cv::Point pt1(0, rho/sin(theta));        cv::Point pt2(image.cols, (rho - image.cols * cos(theta))/sin(theta));        cv::line(image, pt1, pt2, color, 1);    }}</code>

    下面的代碼是程序的主體。

<code class="hljs cpp">int main(int argc, char *argv[]){    QCoreApplication a(argc, argv);    cv::Mat image = imread("c:\\line_test.png", cv::IMREAD_GRAYSCALE);    std::vector<cv::point>points = getPoints(image, 0);    cv::Vec4f line;    cv::fitLine(points,                line,                CV_DIST_HUBER   ,                0,                0.01,                0.01);    double cos_theta = line[0];    double sin_theta = line[1];    double x0 = line[2], y0 = line[3];    double phi = atan2(sin_theta, cos_theta) + PI / 2.0;    double rho = y0 * cos_theta - x0 * sin_theta;    std::cout << "phi = " << phi / PI * 180 << std::endl;    std::cout << "rho = " << rho << std::endl;    drawLine(image, phi, rho, cv::Scalar(0));    double k = sin_theta / cos_theta;    double b = y0 - k * x0;    double x = 0;    double y = k * x + b;    std::cout << k << std::endl;    std::cout << b << std::endl;    //cv::line(image, Point(x0,y0), Point(x,y), cv::Scalar(255), 1);    imshow("", image);    return a.exec();}</cv::point></code>

   

    如果直線擬合類型選擇 CV_DIST_L2。那么效果就沒這么好了。代碼不貼了,就貼個(gè)結(jié)果。

   

最新文章