使用什么追踪算法能算出旋转角度?

星辰韦 2015-12-04 09:38:59
我需要使用鼠标圈定一副图片
使用云台追踪图片的移动和旋转,需要实时的物体中心点坐标和物体的旋转角度

看了一些追踪算法,例如团块追踪和流光法貌似都没法算旋转角度
看到opencv中camshift的输出是个旋转矩形,以为能算出旋转角度,结果尝试之后发现旋转角度根本就不对

求教,用什么算法比较合适啊???
不会非得用surf或orb,再算单应矩阵吧,算法感觉好慢啊
...全文
500 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
艾薇儿More 2016-01-05
  • 打赏
  • 举报
回复
你把图发给我,我试试,我不会opencv 919357403@qq.com
星辰韦 2015-12-14
  • 打赏
  • 举报
回复
没人能帮我看看的吗
星辰韦 2015-12-11
  • 打赏
  • 举报
回复
引用 9 楼 wangyaninglm 的回复:
笨点的方式是查文档,一般opencv2里面函数没有cv打头,你这个算法写好了能否拿出来分享一下
找到个opencv3的函数,decomposeHomographyMat。
C++: int decomposeHomographyMat(InputArray H, InputArray K, OutputArrayOfArrays rotations, OutputArrayOfArrays translations, OutputArrayOfArrays normals)
Parameters:	
H – The input homography matrix between two images.
K – The input intrinsic camera calibration matrix.
rotations – Array of rotation matrices.
translations – Array of translation matrices.
normals – Array of plane normal matrices.
但是opencv3看不懂啊,,也基本没例子。 想改成opencv2的代码也是搞不懂
星辰韦 2015-12-11
  • 打赏
  • 举报
回复
引用 9 楼 wangyaninglm 的回复:
笨点的方式是查文档,一般opencv2里面函数没有cv打头,你这个算法写好了能否拿出来分享一下
改写了下,编译通过,,但是一运行就出问题。 multiply(invM,h1,r1);出的问题,貌似是矩阵行列不对,,是不是改写有问题啊
static void calcRTfromHomo(Mat H, double t[3], double rodrot[3]){
    double r[9];
    Mat _r(3, 3, CV_64F,r);			//rotation matrix
    double intrinsic[9]={1, 0, 0, 0, 1, 0, 0, 0, 1};
    Mat _M(3, 3, CV_64F, intrinsic); //intrinsic matrix, of no use in this implementation, reserved for future use
    double ones[]={1,1,1};
    Mat _ones (3, 1, CV_64F, ones);
    Mat _rodrot(3, 1, CV_64F, rodrot);
    //for SVD
    Mat U(3, 3, CV_64F);
    Mat W(3, 3, CV_64F);
    Mat V(3, 3, CV_64F);
    Mat invM(3, 3, CV_64F);
    // three columns of Homography matrix
    Mat h1(3, 1, CV_64F);
    Mat h2(3, 1, CV_64F);
    Mat h3(3, 1, CV_64F);
    // three columns of rotation matrix
    Mat r1(3, 1, CV_64F);
    Mat r2(3, 1, CV_64F);
    Mat r3(3, 1, CV_64F);
    // translation vector
    Mat _t(3, 1, CV_64F, t);
    h1=H.col(0);
    h2=H.col(1);
    h3=H.col(2);
    r1=_r.col(0);
    r2=_r.col(1);
    r3=_r.col(2);

    invM=_M.inv();
    multiply(invM,h1,r1);
    multiply(invM,h2,r2);
    multiply(invM,h3,_t);

    normalize(r1,r1);
    multiply(r2, _ones, r2, 1/norm(r1));
    multiply(_t, _ones, _t, 1/norm(r1));
    r3=r1.cross(r2);
    SVD::compute(_r, W, U, V, SVD::FULL_UV);
    _r=U.mul(V);
    multiply(U, V, _r);
    Rodrigues(_r, _rodrot);
}
大树学长 2015-12-10
  • 打赏
  • 举报
回复
圆上两点A、B,知道A坐标和AB夹角,求B坐标,是找这种公式么?
shiter 2015-12-10
  • 打赏
  • 举报
回复
我那个似乎是最小包围盒,那个不能算角度?
shiter 2015-12-10
  • 打赏
  • 举报
回复
引用 7 楼 u010417757 的回复:
[quote=引用 5 楼 wangyaninglm 的回复:] 我那个似乎是最小包围盒,那个不能算角度?
不是,,没用那个最小矩形 我用了surf求出了单应矩阵,再从单应矩阵求旋转角度 找了一段代码
int calcRTfromHomo(CvMat* H, double t[3], double rodrot[3]){
	
	double r[9];
	CvMat _r = cvMat(3, 3, CV_64F, r);			//rotation matrix
	double intrinsic[9]={1, 0, 0, 0, 1, 0, 0, 0, 1};
	CvMat _M = cvMat(3, 3, CV_64F, intrinsic); //intrinsic matrix, of no use in this implementation, reserved for future use
	double ones[]={1,1,1};
	CvMat _ones = cvMat(3, 1, CV_64F, ones);	
//	double rodrot[3];
	CvMat _rodrot = cvMat(3, 1, CV_64F, rodrot);
	//for SVD
	CvMat* U = cvCreateMat(3, 3, CV_64F);
	CvMat* W = cvCreateMat(3, 3, CV_64F);
	CvMat* V = cvCreateMat(3, 3, CV_64F);
	CvMat* invM = cvCreateMat(3, 3, CV_64F);
	// three columns of Homography matrix
	CvMat* h1 = cvCreateMat(3, 1, CV_64F);
	CvMat* h2 = cvCreateMat(3, 1, CV_64F);
	CvMat* h3 = cvCreateMat(3, 1, CV_64F);
	// three columns of rotation matrix
	CvMat* r1 = cvCreateMat(3, 1, CV_64F);
	CvMat* r2 = cvCreateMat(3, 1, CV_64F);
	CvMat* r3 = cvCreateMat(3, 1, CV_64F);
	// translation vector
	CvMat _t =  cvMat(3, 1, CV_64F, t);	
	cvGetCol(H,h1,0);
	cvGetCol(H,h2,1);
	cvGetCol(H,h3,2);
	cvGetCol(&_r,r1,0);
	cvGetCol(&_r,r2,1);
	cvGetCol(&_r,r3,2);
	
	cvInvert(&_M, invM);
	cvMatMul(invM,h1,r1);
	cvMatMul(invM,h2,r2);
	cvMatMul(invM,h3,&_t);
	
	cvNormalize(r1, r1);
	cvMul(r2,&_ones,r2,1/cvNorm(r1));
 	cvMul(&_t,&_ones, &_t,1/cvNorm(r1) );
	cvCrossProduct(r1, r2, r3);
	cvSVD(&_r, W, U, V, CV_SVD_V_T);
	cvMatMul(U,V,&_r);
	cvRodrigues2(&_r, &_rodrot, NULL);
	return 1;
}
但是代码是opencv1.0的 我想改成opencv2.4的,不知道怎么该这些函数 求帮忙 [/quote] 笨点的方式是查文档,一般opencv2里面函数没有cv打头,你这个算法写好了能否拿出来分享一下
星辰韦 2015-12-10
  • 打赏
  • 举报
回复
引用 6 楼 bigtree_mfc 的回复:
圆上两点A、B,知道A坐标和AB夹角,求B坐标,是找这种公式么?
帮忙看下7楼
星辰韦 2015-12-10
  • 打赏
  • 举报
回复
引用 5 楼 wangyaninglm 的回复:
我那个似乎是最小包围盒,那个不能算角度?
不是,,没用那个最小矩形 我用了surf求出了单应矩阵,再从单应矩阵求旋转角度 找了一段代码
int calcRTfromHomo(CvMat* H, double t[3], double rodrot[3]){
	
	double r[9];
	CvMat _r = cvMat(3, 3, CV_64F, r);			//rotation matrix
	double intrinsic[9]={1, 0, 0, 0, 1, 0, 0, 0, 1};
	CvMat _M = cvMat(3, 3, CV_64F, intrinsic); //intrinsic matrix, of no use in this implementation, reserved for future use
	double ones[]={1,1,1};
	CvMat _ones = cvMat(3, 1, CV_64F, ones);	
//	double rodrot[3];
	CvMat _rodrot = cvMat(3, 1, CV_64F, rodrot);
	//for SVD
	CvMat* U = cvCreateMat(3, 3, CV_64F);
	CvMat* W = cvCreateMat(3, 3, CV_64F);
	CvMat* V = cvCreateMat(3, 3, CV_64F);
	CvMat* invM = cvCreateMat(3, 3, CV_64F);
	// three columns of Homography matrix
	CvMat* h1 = cvCreateMat(3, 1, CV_64F);
	CvMat* h2 = cvCreateMat(3, 1, CV_64F);
	CvMat* h3 = cvCreateMat(3, 1, CV_64F);
	// three columns of rotation matrix
	CvMat* r1 = cvCreateMat(3, 1, CV_64F);
	CvMat* r2 = cvCreateMat(3, 1, CV_64F);
	CvMat* r3 = cvCreateMat(3, 1, CV_64F);
	// translation vector
	CvMat _t =  cvMat(3, 1, CV_64F, t);	
	cvGetCol(H,h1,0);
	cvGetCol(H,h2,1);
	cvGetCol(H,h3,2);
	cvGetCol(&_r,r1,0);
	cvGetCol(&_r,r2,1);
	cvGetCol(&_r,r3,2);
	
	cvInvert(&_M, invM);
	cvMatMul(invM,h1,r1);
	cvMatMul(invM,h2,r2);
	cvMatMul(invM,h3,&_t);
	
	cvNormalize(r1, r1);
	cvMul(r2,&_ones,r2,1/cvNorm(r1));
 	cvMul(&_t,&_ones, &_t,1/cvNorm(r1) );
	cvCrossProduct(r1, r2, r3);
	cvSVD(&_r, W, U, V, CV_SVD_V_T);
	cvMatMul(U,V,&_r);
	cvRodrigues2(&_r, &_rodrot, NULL);
	return 1;
}
但是代码是opencv1.0的 我想改成opencv2.4的,不知道怎么该这些函数 求帮忙
星辰韦 2015-12-09
  • 打赏
  • 举报
回复
引用 2 楼 wangyaninglm 的回复:
http://blog.csdn.net/wangyaninglm/article/details/41864251
我还是用surf了,求出了单应矩阵 但是不知道之后怎么求旋转角度了 decomposeProjectionMatrix函数要求是【3×4】的矩阵,单应矩阵是【3*3】 弄不明白了 求的好像是个旋转矩阵吧,也就是能得出3个欧拉角,,用哪个啊?只是平面的左右旋转角度
星辰韦 2015-12-09
  • 打赏
  • 举报
回复
引用 2 楼 wangyaninglm 的回复:
http://blog.csdn.net/wangyaninglm/article/details/41864251
我需要的是角度
shiter 2015-12-07
  • 打赏
  • 举报
回复
http://blog.csdn.net/wangyaninglm/article/details/41864251
shiter 2015-12-07
  • 打赏
  • 举报
回复

 cvFindContours( pSrcImage, storage, &contour, sizeof(CvContour),CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);//这函数可选参数还有不少   
  
  
  
    for(; contour; contour = contour->h_next)   //如果contour不为空,表示找到一个以上轮廓,这样写法只显示一个轮廓   
        //如改为for(; contour; contour = contour->h_next) 就可以同时显示多个轮廓   
    {    
  
        End_Rage2D = cvMinAreaRect2(contour);    //代入cvMinAreaRect2这个函数得到最小包围矩形  这里已得出被测物体的角度,宽度,高度,和中点坐标点存放在CvBox2D类型的结构体中,主要工作基本结束。   
      
    std::cout <<" angle:\n"<<(float)End_Rage2D.angle << std::endl;      //被测物体旋转角度    
      
    }  

用findcontour找完后 CvBox2D 这个结构的属性就有个角度,具体我没有深入看
一、平衡小车原理: 自平衡小车是利用车模自身动力使小车保持相对的平衡,是一个动态平衡的过程。维持车模平衡的动力来自车轮的运动,由两个直流电机驱动。对车模的控制可以分解为三个控制任务: 1、控制小车平衡:通过控制小车车轮正反转使小车保持直立平衡。 2、控制小车速度:通过控制小车的倾角实现小车前后运动和速度的控制,其实最终的仍是通过控制电机的转速实现。 3、控制小车方向:通过控制小车两个电机之间的转速差来实现转向控制。 分解为三个控制任务显得相对简单一点,但是在最终的控制过程中都归结为对一个控制量的控制,这样三个任务之间就会存在耦合,会相互干扰。三个任务中控制平衡是关键,所以对小车的速度和方向控制应该尽量的平滑。 二、硬件方案设计 小车的硬件分为三个部分,分别是主控部分、小车姿态获取部分以及电机驱动部分。主控板采用目前常用的arduino UNO,同时也可以使用其他arduino通用控制板做主控。 小车姿态获取可以有很多方案,使用最多的就是通过加速度计和陀螺仪获取小车姿态。理论上只需要两轴加速度计(垂直方向Z轴和沿小车运动方向X轴)和一个单轴陀螺仪(沿小车车轮轴方向,获取绕小车轮轴的角速度)。陀螺仪通过角度积分可以获得小车角度,但是经过积分会产生累计误差,并且会越来越大,X轴与Z轴加速度计的值也可以算出小车的倾角,但是加速度计的瞬时误差较大,所以结合陀螺仪和加速度计两者获得的角度做数据融合可得真实角度。我们使用一个集成了三轴加速度计和三轴陀螺仪的集成芯片MPU6050,这样极大的简化了我们的传感器电路。 小车通过两个直流电机驱动车轮运动来获得动力,直流电机的驱动电路设计关系到整个系统的稳定性,因为电机反转时会产生反向电动势会干扰到电源系统内其他设备的运行。我们选用L298P做电机驱动器,它内部包含4通道逻辑驱动电路,可同时驱动两个直流电机,输出电流可达2.5A。 三、软件设计之小车姿态获取---卡尔曼滤波 在开始之前应该对MPU6050进行设置,主要设置角速度以及加速度的量程,加速度量程有±2g、±4g±8g与±16g,角速度量程分别为±250、±500、±1000与±2000°/sec (dps),可准确的追踪快速动作与慢速动作。在使用之前先设置好量程以便后面的换算。我们小车轮轴与传感器Y轴平行,即绕Y轴旋转则有: 那竖直方向弧度计算公式为: angle = atan2(x, z) //结果以弧度表示并介于 -pi 到 pi 之间(不包括 -pi) 如果要换算成具体角度: angle = atan2(x, z) *(180/3.14) 陀螺仪获取角速度积分得到角度公式为:anglen = anglen-1 + gyronn*dt ,式中anglen 为第N次采样的角度值,anglen-1 为第N-1次的角度值,gyronn为两次采样值之间的角速度值,dt为两次采样之间的时间。然后将换算后的两个角度数据进行卡尔曼滤波融合,可获得小车真实角度,也可以采用更简单的互补滤波算法。 注意加速度计所得角度与陀螺仪积分角度的方向。 四、软件设计之小车姿态调整---PID参数整定 小车的姿态获取最终结果是一个角度,就是小车偏离平衡位置的倾角。通过以小车的这个倾角为变量进行PID控制,输出用于控制车轮转速的PWM值,那么相当于小车只有一个角度反馈环路,虽然能使小车平衡,但是增加了控制难度,所以通常会使用带测速的电机,再加入一个小车速度反馈环路,这样使得小车更容易控制。关于PID的有下面一个简单易懂的描述: 假设我们想把一个小球稳定在一个光滑的坡顶,这显然是一个不平衡的系统,稍有扰动小球就会滚下来。假设恰好平衡的位置坐标是L,我们可以测量到小球的位置是x,那么怎么给小球施加f(x)的力反馈,让它能够平衡呢? 最直观的想法就是f(x) =Kp*(L-x),简单的说就是你在左边我就向右推,你在右边我就向左推,这就是比例因子P; 现在考虑两种情况,同样是在x位置,小球静止和小球具有速度V这两种情况。很明显,如果V>0,我们只需要施加更小的力,因为小球自身的惯性会让它运动向平衡位置。所以可以修正f(x) = Kp*(L-x) – Kd*V。因为速度一般不容易测量,我们常常用位置的变化Δx除以测量的时间差Δt来计算速度,所以这就是微分因子D; 情况继续发生变化,上面考虑的是斜坡静止的情况,如果这个变态的斜坡是移动的怎么办呢?(例如两轮平衡机器人实际上是可以运动的,对于静止的磁悬浮来说,不需要考虑这个参数)这时候我们需要不断的累加并平均x值,来计算平衡位置的L,这个就是积分因子I; 当PID用在我们自平衡小车中时,我们使用角度PD环与速度PI环进行控制。 pwm=angle*k1+angle_dot*k2+range*k3+wheel_speed*k4; PID参数整定步奏如下: 1、将k1,k2,k3,k4均设为0; 2、逐步增大k1,使得小车刚好能够来回摆动。 3、再逐步增大k2,使得小车相对平稳,太大会使小车发生抖动; 4、增大k3,使得小车能够来回走动(不是摆动也不是抖动); 5、增大k4,使得小车能稳定自平衡。 具体参数调整过程比较繁琐,需要自己体会每个参数的作用。

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧