問題:
2D 或 3D 點集,32-比特整數或浮點數坐標 ,存放輸入點。
Char* cvSeqPush(CvSeq* seq,void* element=NULL)
功能:存放元素到序列尾部。
dist_type
擬合的距離類型.
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
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) 是線上某點。
1 float *line = new float[4]; 2 CvMemStorage* storage = cvCreateMemStorage(0); 3 4 //往點序列中存放需要參與擬合直線的點 5 CvSeq* point_seq = cvCreateSeq( CV_32FC2, sizeof(CvSeq), sizeof(CvPoint2D32f), storage ); 6 for(int j=0;j<temp.size();j++) 7 { 8 cvSeqPush(point_seq, &cvPoint2D32f(temp[j].stPot().x,temp[j].stPot().y)); 9 cvSeqPush(point_seq, &cvPoint2D32f(temp[j].enPot().x,temp[j].enPot().y)); 10 } 11 12 cvFitLine(point_seq,CV_DIST_L2,0,0.01,0.01,line); //CV_DIST_L2表示最小二乘法 13 14 //line[0],line[1]為x,y的單位方向向量 15 //line[2],line[3]為直線經過某點的X,Y值 16 //正好組成參數方程 17 //X=line[0]t+line[2] 18 //Y=line[1]t+line[3] 19 20 //根據line[4]計算自己需要的直線或線段 21 Point A(0,line[3]-(line[1]*line[2]/line[0])); 22 Point B(src->width,(src->width-line[2])*line[1]/line[0]+line[3]); 23 cvLine(src,A,B,CV_RGB(255,0,0),3,8,0); 24 25 cvClearSeq(point_seq); 26 cvReleaseMemStorage(&storage);
思路二:
自己寫算法,但是需要注意,openCV中原點在屏幕的左上角,與我們數學中的直角坐標系不太一樣。
1 //最小二乘法擬合直線 2 void line_fit(vector<MyLine>& h,IplImage* src) 3 { 4 int n = 2*h.size(); 5 int k; //目標直線斜率 6 int b; //目標直線截距 7 vector<MyLine>::iterator it = h.begin(); 8 int sumx=0,sumy=0,sumxy=0,sumxsq=0; 9 while(it != h.end()) 10 { 11 sumx += it->stPot().x; 12 sumx += it->enPot().x; 13 sumy += it->stPot().y; 14 sumy += it->enPot().y; 15 sumxy += it->stPot().x*it->stPot().y; 16 sumxy += it->enPot().x*it->enPot().y; 17 sumxsq += it->stPot().x*it->stPot().x; 18 sumxsq += it->enPot().x*it->enPot().x; 19 it++; 20 } 21 22 if(sumxsq == (sumx*sumx/n)) 23 k = atan2(0,1.0); 24 else 25 k = (sumxy-((sumx*sumy)/n))/(sumxsq-(sumx*sumx/n)); 26 b = (sumy-k*sumx)/n; 27 cvLine(src,Point(0,b),Point(src->width,k*src->width+b),CV_RGB(255,0,0),1,8,0); 28 }
