OpenCV的vcFitLine函數

文章轉載於:http://blog.csdn.net/augusdi/article/details/9014067?reload

以下代碼是從文件中讀取數據數據格式是,整形數據有空格分隔,然後用OpenCV曲線擬合顯示:

#include <stdio.h>
#include <cv.h>
#include <highgui.h>

#pragma comment(lib, "cv.lib")
#pragma comment(lib, "cxcore.lib")
#pragma comment(lib, "highgui.lib")

void put_data_into_array(CvPoint dataarray[], CvPoint data, int n)
{
    for(int i = 0; i < n - 1; i++)
        dataarray[i] = dataarray[i+1];

    dataarray[n - 1] = data;
}

int main(int argc, char* argv[])
{
    IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
    cvNamedWindow( "fitline", 1 );

    CvPoint pt1, pt2;    // 直線的兩個端點
    CvPoint* points = (CvPoint*)malloc( 6 * sizeof(points[0])); // 存放隨機產生的點點,數目爲count
    CvMat pointMat = cvMat(1, 6, CV_32SC2, points); // 點集, 存儲count個隨機點points
    float line[4];        // 輸出的直線參數。2D 擬合情況下,它是包含 4 個浮點數的數組 (vx, vy, x0, y0)
    //其中 (vx, vy) 是線的單位向量而 (x0, y0) 是線上的某個點
    float t;

    FILE *fp = fopen("data.txt", "r");
    int v = 0;

    while( !feof(fp) )
    {
        v++;

        int x, y;
        fscanf(fp,"%d", &x);
        fscanf(fp,"%d", &y);
        put_data_into_array(points, cvPoint(x, y), 6);
        printf("[%d, %d]\n", x, y);
        if( v > 6 )
        {

            // find the optimal line 曲線擬合
            cvFitLine(&pointMat, CV_DIST_L1, 1, 0.001, 0.001, line);

            // 畫出線段的兩個端點(避免線太短,以線上一個隨機點向兩側延伸line[0]*t )
            t = (float)(img->width + img->height) ;
            pt1.x = cvRound(line[2] - line[0] * t);
            pt1.y = cvRound(line[3] - line[1] * t);
            pt2.x = cvRound(line[2] + line[0] * t);
            pt2.y = cvRound(line[3] + line[1] * t);
            cvZero( img );
            cvLine(img, pt1, pt2, CV_RGB(0,255,0), 3, CV_AA, 0);
            cvCircle(img, cvPoint(x, y), 2,  CV_RGB(255, 0, 0), CV_FILLED, CV_AA, 0);
            char key = cvWaitKey(200);  
            cvShowImage("fitline", img);
        }
    }

    fclose(fp);
    free( points );
    cvWaitKey(-1);

    cvDestroyWindow( "fitline" );
    cvReleaseImage(&img);

    return 0;
}

opencv中 2D 或 3D 點集的直線擬合

代碼參考:

http://hi.baidu.com/yuzaihuan/item/283d12f260513b43922af269

#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>

#pragma comment(lib, "cv.lib")
#pragma comment(lib, "cxcore.lib")
#pragma comment(lib, "highgui.lib")

int main(int argc, char* argv[])
{
    IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
    CvRNG rng = cvRNG(-1); //cvRNG()跟一般的C語言srand()使用方法一樣,要先給它一個種子,
    //但srand()用到的是unsigned int的32位種子範圍,而cvRNG()用的是64位長整數種子。
    //初始化CvRNG資料結構,假如seed給0,它將會自動轉成-1    cvRNG(64位種子)
    cvNamedWindow( "fitline", 1 );

    for(;;)
    {
        char key;
        int i;
        int    count = cvRandInt(&rng)%100 + 1; //產生1-100 之間的數
        int outliers = count/5; // 奇異點的個數。0--20 之間的數
        printf("count = %d", count);
        float a = cvRandReal(&rng)*200;  // 0~ 199 之間的浮點數 [cvRandReal 浮點型隨機數並更新 RNG ,範圍在 0..1 之間,不包括 。
        float b = cvRandReal(&rng)*40; //返回0 ~ 39之間的數
        float angle = cvRandReal(&rng)*CV_PI;  
        printf("count = %f", angle);
        float cos_a = cos(angle), sin_a = sin(angle);
        printf("cos_a = %f\n", cos_a);

        CvPoint pt1, pt2; //直線的兩個端點
        CvPoint* points = (CvPoint*)malloc( count * sizeof(points[0])); //存放隨機產生的點點,數目爲count
        CvMat pointMat = cvMat( 1, count, CV_32SC2, points ); //點集, 存儲count個隨機點points
        float line[4]; //輸出的直線參數。2D 擬合情況下,它是包含 4 個浮點數的數組 (vx, vy, x0, y0)
        //其中 (vx, vy) 是線的單位向量而 (x0, y0) 是線上的某個點
        float d, t;
        b = MIN(a*0.3, b);

        // generate some points that are close to the line
        for( i = 0; i < count - outliers; i++ )
        {
            float x = (cvRandReal(&rng)*2-1)*a;
            float y = (cvRandReal(&rng)*2-1)*b;
            points[i].x = cvRound(x*cos_a - y*sin_a + img->width/2);
            points[i].y = cvRound(x*sin_a + y*cos_a + img->height/2);
        }
        // generate "completely off" points
        for( ; i < count; i++ )
        {
            points[i].x = cvRandInt(&rng) % img->width;
            points[i].y = cvRandInt(&rng) % img->height;
        }

        // find the optimal line 曲線擬合
        cvFitLine(&pointMat, CV_DIST_L1, 1, 0.001, 0.001, line);
        cvZero( img );


        //畫出產生的隨機分佈的點點
        for( i = 0; i < count; i++ )
        {
            cvCircle( img, points[i], 2, i < count - outliers ? CV_RGB(255, 0, 0) :CV_RGB(255,255,0), CV_FILLED, CV_AA, 0 );
        }

        // ... and the long enough line to cross the whole image
        d = sqrt((double)line[0]*line[0] + (double)line[1]*line[1]);  //line[0 & 1]存儲的是單位向量,所以d=1
        //printf("\n %f\n", d);
        line[0] /= d;
        line[1] /= d;

        //畫出線段的兩個端點(避免線太短,以線上一個隨機點向兩側延伸line[0]*t )
        t = (float)(img->width + img->height) ;
        pt1.x = cvRound(line[2] - line[0] * t);
        pt1.y = cvRound(line[3] - line[1] * t);
        pt2.x = cvRound(line[2] + line[0] * t);
        pt2.y = cvRound(line[3] + line[1] * t);
        cvLine( img, pt1, pt2, CV_RGB(0,255,0), 3, CV_AA, 0 );

        cvShowImage( "fitline", img );
        key = (char) cvWaitKey(2000);
        if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
            break;
        free( points );
    }

    cvDestroyWindow( "fitline" );
    return 0;
}


void cvFitLine( const CvArr* points, int dist_type, double param, double reps, double aeps, float* line );

points 

2D 或 3D 點集,32-比特整數或浮點數座標

dist_type
擬合的距離類型 (見討論).

param
對某些距離的數字參數,如果是 0, 則選擇某些最優值

reps, aeps
半徑 (座標原點到直線的距離) 和角度的精度,一般設爲0.01。

line
輸出的直線參數。2D 擬合情況下,它是包含 4 個浮點數的數組 (vx, vy, x0, y0),其中 (vx, vy) 是線的單位向量而 (x0, y0) 是線上的某個點.

對 3D 擬合,它是包含 6 個浮點數的數組 (vx, vy, vz, x0, y0, z0), 其中 (vx, vy, vz) 是線的單位向量,而 (x0, y0, z0) 是線上某點。


函數 cvFitLine 通過求 sumi:ρ(ri) 的最小值方法,用 2D 或 3D 點集擬合直線,其中 ri 是第 i 個點到直線的距離, ρ(r) 是下面的距離函數之一:

dist_type=CV_DIST_L2 (L2): ρ(r)=r2/2 (最簡單和最快的最小二乘法)

dist_type=CV_DIST_L1 (L1): ρ(r)=r

dist_type=CV_DIST_L12 (L1-L2): ρ(r)=2?[sqrt(1+r2/2) - 1]

dist_type=CV_DIST_FAIR (Fair): ρ(r)=C2?[r/C - log(1 + r/C)], C=1.3998

dist_type=CV_DIST_WELSCH (Welsch): ρ(r)=C2/2?[1 - exp(-(r/C)2)], C=2.9846

dist_type=CV_DIST_HUBER (Huber): ρ(r)= r2/2, if r < C; C?(r-C/2), otherwise; C=1.345 


opencv中隨機數的生成


產生標準正態分佈的隨機數或矩陣的函數

概念

1. 一般計算機的隨機數都是僞隨機數,以一個真隨機數(種子)作爲初始條件,然後用一定的算法迭代產生隨機數序列。

2. 隨機數的“種子”就是產生隨機數的第一次使用值,機制是通過一個比較複雜函數,將這個種子的值映射到隨機數空間的某一個點上,並且產生的隨機數均勻地(或者符合正態分佈等)散步在空間中,以後產生的隨機數都與前一個隨機數有關。

3. RNG : random number generation 隨機數生成

(版權聲明):參考網絡

二、opencv中的函數

1. CvRNG cvRNG(int64 seed);
使用64位長整形種子,初始化隨機數生成器狀態。


cvGetTickCount();
返回64位長整形的時間數據,在opencv中是爲CvRNG設置的專用種子。


2. unsigned cvRandInt(CvRNG* rng);

返回均勻分佈的隨機32位無符號整型值,並更新RNG的狀態 ; 使用模操作可以獲得確定邊界的整形數值。

3. double cvRandReal(CvRNG* rng);

返回均勻分佈的隨即浮點數,範圍在0-1(不含1),並更新RNG的狀態。

4. void cvRandArr( CvRNG* rng, CvArr* arr, int dist_type, CvScalar param1, CvScalar param2 );

用隨機數填充數組,並更新RNG的狀態
arr 輸出數組
dist_type 分佈類型: CV_RAND_UNI - 均勻分佈 ; CV_RAND_NORMAL - 正態分佈 或者 高斯分佈
param1 分佈的第一個參數。如果是均勻分佈它是隨機數範圍的閉下邊界。如果是正態分佈它是隨機數的平均值。
param2 分佈的第二個參數。如果是均勻分佈它是隨機數範圍的開上邊界。如果是正態分佈它是隨機數的標準差。

http://blog.csdn.net/timidsmile/article/details/8455608
發佈了2 篇原創文章 · 獲贊 11 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章