ArUco----一个微型现实增强库的介绍及视觉应用(二)

一、第一个ArUco的视觉应用

  首先介绍第一个视觉应用的Demo,这个应用场景比较简单,下面具体介绍:

1. 应用场景

  主线程:通过摄像头检测环境中的视觉标志,看到ID为100的标志后在图像中圈出标志,在标志上绘制坐标系,得到视觉标志相对于相机坐标系的位置和姿态参数;

  子线程:将得到的视觉标志进一步转换成需要的数据类型并发送给机器人。

2. 编程环境

  Ubuntu14.04(安装有OpenCV以及ArUco)

3. 编译工具

  Cmake

4. 源码下载地址

  https://github.com/Zhanggx0102/Aruco_Blog_Demo.git

5. 源码处理

  下载完成后重新编译即可。

  cd Aruco_Blog_Demo-master

  rm -r build/

  mkdir build

  cd build

  cmake ..

  make

二、源码解读

源码中已经做了比较详细的注释,这里主要讲解程序框架。

程序流程图如下所示:

程序流程图

执行后的效果如下图所示:

下面是源码截取的两个主要的函数。

/*******************************************************************************************************************
main function
********************************************************************************************************************/
int main(int argc,char **argv)
{ int thread_return;
pthread_t Message_Send_Thread_ID;
//init thread lock
pthread_mutex_init(&IK_Solver_Lock, NULL);
//creat new thread
thread_return = pthread_create(&Message_Send_Thread_ID,NULL,Thread_Func_Message_Send,NULL); //import the camera param (CameraMatrix)
float camera_matrix_array[9] = { 1.0078520005023535e+003, 0., 6.3950000000000000e+002,
0.0, 1.0078520005023535e+003, 3.5950000000000000e+002,
0.0, 0.0, 1.0 };
cv::Mat Camera_Matrix(3,3,CV_32FC1);
InitMat(Camera_Matrix,camera_matrix_array);
cout << "Camera_Matrix = " << endl << "" << Camera_Matrix << endl ;
//import the camera param (Distorsion)
float Distorsion_array[5] = {-4.9694653328469340e-002, 2.3886698343464000e-001, 0., 0.,-2.1783942538569392e-001};
cv::Mat Distorsion_M(1,5,CV_32FC1);
InitMat(Distorsion_M,Distorsion_array);
cout << "Distorsion_M = " << endl << "" << Distorsion_M << endl ; CameraParameters LogiC170Param;
//LogiC170Param.readFromXMLFile("LogitchC170_Param.yml");
LogiC170Param.CameraMatrix = Camera_Matrix.clone();
LogiC170Param.Distorsion = Distorsion_M.clone();
LogiC170Param.CamSize.width = 1280;
LogiC170Param.CamSize.height = 720; float MarkerSize = 0.04;
int Marker_ID;
MarkerDetector MDetector;
MDetector.setThresholdParams(7, 7);
MDetector.setThresholdParamRange(2, 0); CvDrawingUtils MDraw; //read the input image
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
cv::Mat frame;
cv::Mat Rvec;//rotational vector
CvMat Rvec_Matrix;//temp matrix
CvMat R_Matrix;//rotational matrixs
cv::Mat Tvec;//translation vector cap>>frame;//get first frame
//LogiC170Param.resize(frame.size()); printf("%f, %f\n",cap.get(CV_CAP_PROP_FRAME_WIDTH),cap.get(CV_CAP_PROP_FRAME_HEIGHT));
cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
//cap.set(CV_CAP_PROP_FPS, 10);
printf("%f, %f\n",cap.get(CV_CAP_PROP_FRAME_WIDTH),cap.get(CV_CAP_PROP_FRAME_HEIGHT)); while(1)
{
//get current frame
cap>>frame;
//Ok, let's detect
vector< Marker > Markers=MDetector.detect(frame, LogiC170Param, MarkerSize);
//printf("marker count:%d \n",(int)(Markers.size())); //for each marker, estimate its ID and if it is 100 draw info and its boundaries in the image
for (unsigned int j=0;j<Markers.size();j++)
{
//marker ID test
Marker_ID = Markers[j].id;
printf("Marker ID = %d \n",Marker_ID); if(Marker_ID == 100)
{
//cout<<Markers[j]<<endl;
Markers[j].draw(frame,Scalar(0,0,255),2); Markers[j].calculateExtrinsics(MarkerSize, LogiC170Param, false);
//calculate rotational vector
Rvec = Markers[j].Rvec;
cout << "Rvec = " << endl << "" << Rvec << endl ;
//calculate transformation vector
Tvec = Markers[j].Tvec;
cout << "Tvec = " << endl << "" << Tvec << endl ; //lock to update global variables: Rotat_Vec_Arr[3] Rotat_M[9] Trans_M[3]
pthread_mutex_lock(&IK_Solver_Lock); //save rotational vector to float array
for (int r = 0; r < Rvec.rows; r++)
{
for (int c = 0; c < Rvec.cols; c++)
{
//cout<< Rvec.at<float>(r,c)<<endl;
Rotat_Vec_Arr[r] = Rvec.at<float>(r,c);
}
}
printf("Rotat_Vec_Arr[3] = [%f, %f, %f] \n",Rotat_Vec_Arr[0],Rotat_Vec_Arr[1],Rotat_Vec_Arr[2]); //save array data to CvMat and convert rotational vector to rotational matrix
cvInitMatHeader(&Rvec_Matrix,1,3,CV_32FC1,Rotat_Vec_Arr,CV_AUTOSTEP);//init Rvec_Matrix
cvInitMatHeader(&R_Matrix,3,3,CV_32FC1,Rotat_M,CV_AUTOSTEP);//init R_Matrix and Rotat_M
cvRodrigues2(&Rvec_Matrix, &R_Matrix,0);
printf("Rotat_M = \n[%f, %f, %f, \n %f, %f, %f, \n %f, %f, %f] \n",Rotat_M[0],Rotat_M[1],Rotat_M[2],Rotat_M[3],Rotat_M[4],Rotat_M[5],Rotat_M[6],Rotat_M[7],Rotat_M[8]); //save transformation vector to float array
for (int r = 0; r < Tvec.rows; r++)
{
for (int c = 0; c < Tvec.cols; c++)
{
Trans_M[r] = Tvec.at<float>(r,c);
}
}
printf("Trans_M[3] = [%f, %f, %f] \n",Trans_M[0],Trans_M[1],Trans_M[2]); //unlock
pthread_mutex_unlock(&IK_Solver_Lock); // draw a 3d cube in each marker if there is 3d info
if (LogiC170Param.isValid() && MarkerSize != -1)
{
MDraw.draw3dAxis(frame,LogiC170Param,Rvec,Tvec,0.04);
}
}
}
//*/
cv::waitKey(150);//wait for key to be pressed
cv::imshow("Frame",frame);
}
//wait for the IK solver thread close and recover resources
pthread_join(Message_Send_Thread_ID,NULL); pthread_mutex_destroy(&IK_Solver_Lock); //destroy the thread lock
return 0
}
/**********************************************************
function: new thread to send messages
input: void
return :null
***********************************************************/
void * Thread_Func_Message_Send(void *arg)
{
printf("IK solver thread is running!\n");
//original pose and position
float P_original[4];
float N_original[4];
float O_original[4];
float A_original[4];
//final pose and position
float P[3];
float N[3];
float O[3];
float A[3]; P_original[3] = 1;
N_original[3] = 0;
O_original[3] = 0;
A_original[3] = 0; while (1)
{
//get the spacial pose
pthread_mutex_lock(&IK_Solver_Lock);
//memcpy(P_original, Trans_M, sizeof(Trans_M));
for(int i=0;i<3;i++)
{
P_original[i] = Trans_M[i];
N_original[i] = Rotat_M[3*i];
O_original[i] = Rotat_M[3*i+1];
A_original[i] = Rotat_M[3*i+2];
}
pthread_mutex_unlock(&IK_Solver_Lock);
//debug printf
///*
printf("N_original[4] = [%f, %f, %f, %f] \n",N_original[0],N_original[1],N_original[2],N_original[3]);
printf("O_original[4] = [%f, %f, %f, %f] \n",O_original[0],O_original[1],O_original[2],O_original[3]);
printf("A_original[4] = [%f, %f, %f, %f] \n",A_original[0],A_original[1],A_original[2],A_original[3]);
printf("P_original[4] = [%f, %f, %f, %f] \n",P_original[0],P_original[1],P_original[2],P_original[3]);
//*/ printf("I send the message to robot here! \n");
/*
add message send function here!
*/
//uodate every 5 s
sleep(5);
}
//kill the message send thread
pthread_exit(0);
}

 

<-- 本篇完-->

欢迎留言、私信、邮箱、微信等任何形式的技术交流。

作者信息:

名称:Shawn

邮箱:zhanggx0102@163.com

微信二维码:↓

ArUco----一个微型现实增强库的介绍及视觉应用(二)的更多相关文章

  1. ArUco----一个微型现实增强库的介绍及视觉应用(一)

    ArUco----一个微型现实增强库的介绍及视觉应用(一) 一.ArUco简介 ArUco是一个开源的微型的现实增强库,目前好像已经集成在OpenCV3.0以上的版本内了,它除了用于现实增强,还很用于 ...

  2. 用 Lua 实现一个微型虚拟机-基本篇

    用 Lua 实现一个微型虚拟机-基本篇 目录 介绍 机器指令模拟 最终核心代码 虚拟机内部状态可视化 完整项目代码 后续计划 参考 介绍 在网上看到一篇文章 使用 C 语言实现一个虚拟机, 这里是他的 ...

  3. 介绍一个python视频处理库:moviepy

    由于博客园的插件和我自己博客的插件不一致,代码以及视频插入转换很麻烦,所以还是我原来博客的地址查看吧. 介绍一个python视频处理库:moviepy

  4. dotweb——go语言的一个微型web框架(一)

    dotweb是16年正式托管到github的一个开源项目,go语言的web框架目前也有很多,出名的有bee和echo.它们都是很优秀的框架,但是我们喜欢更轻.更小的东西,经历一些之后我们更青睐微服务这 ...

  5. 【Tool】Augmentor和imgaug——python图像数据增强库

    Augmentor和imgaug--python图像数据增强库 Tags: ComputerVision Python 介绍两个图像增强库:Augmentor和imgaug,Augmentor使用比较 ...

  6. Python常用的库简单介绍一下

    Python常用的库简单介绍一下fuzzywuzzy ,字符串模糊匹配. esmre ,正则表达式的加速器. colorama 主要用来给文本添加各种颜色,并且非常简单易用. Prettytable ...

  7. Go语言标准库log介绍

    Go语言标准库log介绍 无论是软件开发的调试阶段还是软件上线之后的运行阶段,日志一直都是非常重要的一个环节,我们也应该养成在程序中记录日志的好习惯. log Go语言内置的log包实现了简单的日志服 ...

  8. C 封装一个简单二叉树基库

    引文 今天分享一个喜欢佩服的伟人,应该算人类文明极大突破者.收藏过一张纸币类型如下 那我们继续科普一段关于他的简介 '高斯有些孤傲,但令人惊奇的是,他春风得意地度过了中产阶级的一生,而  没有遭受到冷 ...

  9. JavaFX的扩展控件库ControlsFX介绍

    声明:   本博客文章原创类别的均为个人原创,版权所有.转载请注明出处: http://blog.csdn.net/ml3947,另外本人的个人博客:http://www.wjfxgame.com. ...

随机推荐

  1. Java对象流的使用

    为了让对象持久化(把对象存储到本地),可以使用java的对象流处理对象,把对象的内容写到本地存储的文件中,也可以从本地文件中读取出来.也就是常说的序列化和反序列化 主要用到了ObjectInputSt ...

  2. 【XML】 XML格式一些记录

    XML XML格式常用于网络通讯,本身不会有作为而是作为纯文本传输,可以说它是一种独立于应用和硬件的数据传输工具.虽然看起来XML比HTML要更加简单,也知道的更加晚一点,但是需要知道的是,XML才是 ...

  3. curl的使用基本流程,HTTP的get请求,post请求

    使用CURL的PHP扩展完成一个HTTP请求的发送一般有以下几个步骤: 1.初始化连接句柄: 2.设置CURL选项: 3.执行并获取结果: 4.释放VURL连接句柄. 下面的程序片段是使用CURL发送 ...

  4. virtualbox主机与虚拟机之间互相通信教程

    前言 在使用虚拟机搭建集群时,需要实现虚拟机与虚拟机之间互相ping通,并且主机与虚拟机也可以互相ping通. 一.环境准备: 1.主机为win7 2.virtualbox下创建两台ubuntu虚拟机 ...

  5. Java基础笔记(1)----语言基础

    变量 变量:是内存中的一块存储空间,是存储数据的基本单元. 使用:先声明,后赋值,在使用. 声明:数据类型 + 变量名 = 值.(例:int a = 5:) 数据类型 分类:如图: 详解: Strin ...

  6. Beta 凡事预则立

    写在Beta冲刺前 关于组长是否重选的议题和结论 总体结论 组长无需更换 队内无人替代 理由 当前组长能够较好的号召和组织团队成员进行工作 当前组长能够对项目有合理的规划 当前组长被大家一致认可可以继 ...

  7. C语言博客作业—字符数组

    一.PTA实验作业 题目1:字符串转换成十进制整数 1. 本题PTA提交列表 2. 设计思路 (1)定义i为循环变量,number用于存放每一次转化的结果,flag用于判断是否为负数,p用于修改结果的 ...

  8. 201621123062《java程序设计》第13周作业总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 思维导图: 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多 ...

  9. Python2.x的编码问题

    1. 计算机编码历史 ASCII Python的默认编码,其是一种单字节的编码.刚开始计算机世界里只有英文,而单字节可以表示256个不同的字符.最开始ASCII只定义了128个字符编码,包括96个文字 ...

  10. 201621123050 《Java程序设计》第5周学习总结

    1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 答:接口.has-a.comparable 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导图一般不需要出现过多的字. ...