opencv拟合直线并在屏幕上绘出

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

int main()
{
 IplImage *img=cvCreateImage(cvSize(500,500),8,3);//开辟500×500的8位3通道的图像内存空间。
 CvRNG rng=CvRNG(-1);//产生随机数产生器的状态。

 cvNamedWindow("fitline",0);

 for (;;)
 {
  char key;
  int i;
  int count =cvRandInt(&rng)%100+1;//产生1~100之间的随机整数
  int outliers=count/5;//选取1/5数量的点作为outliers。
  float a=cvRandReal(&rng)*200;//产生0~1随机浮点数
  float b=cvRandReal(&rng)*40;
  float angle=cvRandReal(&rng)*CV_PI;//随机产生弧度
  float cos_a=cos(angle);
  float sin_a=sin(angle);
  CvPoint pt1 , pt2;
  CvPoint * points=(CvPoint*)malloc(count *sizeof(points[0]));
  CvMat pointMat=cvMat(1,count,CV_32SC2,points);
  float line[4];
  float d,t;

  b=MIN(a*0.3,b);

  //产生噪声点
  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*cos_a+y*sin_a+img->height/2);
  }

  for (;i<count;i++)//异常点
  {
   points[i].x=cvRandInt(&rng) % img->width;
   points[i].y=cvRandInt(&rng) % img->height;
  }

  //拟合直线
  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);
  }
       


  t=(float)(img->width+img->height);
  pt1.x=cvRound(line[2]-line[0]*t);//将直线上的点(line[2],line[3])沿直线移动一段距离
  pt1.y=cvRound(line[3]-line[1]*t);//将直线上的点(line[2],line[3])沿直线移动一段距离

  pt2.x=cvRound(line[2]+line[0]*t);//将直线上的点(line[2],line[3])沿直线移动一段距离
  pt2.y=cvRound(line[3]+line[1]*t);//将直线上的点(line[2],line[3])沿直线移动一段距离

  cvLine(img,pt1,pt2,CV_RGB(0,255,0),3,CV_AA,0);


  cvShowImage("fitline",img);
  key=(char)cvWaitKey(0);
  if (key==27||key=='q'||key=='Q')
   break;
  free(points);
 }
 cvDestroyWindow("fitline");
 cvReleaseImage(&img);
 return 0;
}

注意:

 (1):(line[0],line[1])不是直线上的点。它表示的是一个与拟合的直线平行的向量。且(line[0]*line[0]+line[1]*line[1]=1),所以直线的倾斜角度=asin(line[1])=acos(line[0])=atg(line[1]/line[0])。

(2):很明显,已知一个直线的方向(即向量)和直线上的一点(line[2],line[3]),当然能唯一确定一条直线。

你可能感兴趣的:(opencv拟合直线并在屏幕上绘出)