数字图像处理
将图像信号数据转换成数字信号数据,供计算机进行相关的处理
Mat - 基本图像容器
目的
获取并存储像素值,最终在计算机世界里所有图像都可以简化为数值矩以及矩阵信息。
Mat
相比较其他的存储格式:1.不必手动为其开辟空间 2.不必在不需要时立即将空间释放。
- Mat是一个类,由两个数据部分组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的矩阵(根据所选存储方法的不同矩阵可以是不同的维数)的指针。
- 为了解决拷贝矩阵的运算量太大,OpenCV使用引用计数机制。其思路是让每个Mat对象有自己的信息头,但共享同一个矩阵。这通过让矩阵指针指向同一地址实现。而拷贝构造函数则只拷贝信息头和矩阵指针,而不拷贝矩阵。
- 拷贝矩阵本身(不只是信息头和矩阵指针),这时可以使用函数clone或者copyTo。
现在改变F或者G就不会影响Mat信息头所指向的矩阵。
1.OpenCV函数中输出图像的内存分配是自动完成的。
2.使用OpenCV的C++接口时不需要考虑内存释放问题。
3.赋值运算符合拷贝构造函数只拷贝信息头。
4.使用函数clone或者copyTo来拷贝一副图像的矩阵。
上位机程序步骤
串口相关
串口类的定义
1,将ICom类加到std命名空间中
2,构造函数,析造函数,串口读,串口写,串口设置,串口数据整理。
3,文件描述符,epoll标志符,事件集合,线程ID,线程函数。
串口类成员函数初始化
线程相关:
1,根据析造函数,初始化文件ID,创建eopll_create。
2,打开端口号对应的com口,并创建线程,设置相关的线程属性(包括绑定属性,线程分离属性)
3,线程创建完成后就会一直监听,当有端口线程时,进入线程执行相关的操作。
3.1,epoll事件设置,、epoll_ctl(添加读事件到epoll的事件队列中)
3.2,while循环中等待epoll事件到来。
3.3,有事件数据就执行读串口数据。
成员函数初始化:
1,Com口读数据函数。
2,Com口设置函数。
Kinect相关
回调函数和Generator相关
- 定义UserGenerator、DepthGenerator、ImageGenerator、GestureGenerator。
- 创建
Mat cameraImg
用来保存图像数据,创建xn::Context context
用来管理OpenNI的资源和环境状态。 - 创建连线起始和终点的关节点数组。
- 创建手势注册回调函数、手势检测回调函数。创建NewUser回调函数、LostUser回调函数。创建校准回调函数(包括start和end)。创建PoseDetected回调函数。
openni初始化
- 配置输出模式
- 创建imageGenerator、depthGenerator、userGenerator
- depthGenerator.GetAlternativeViewPointCap().SetViewPoint( imageGenerator ) ; 如果深度图和颜色图在一张图上显示,则必须对深度图像进行校正,校正的方法是调用深度图的如下方法:.GetAlternativeViewPointCap().SetViewPoint();
- 新用户事件的注册。
- 配置骨架轮廓。
- 注册校准骨架开始和结束事件。
- 启动所有的节点生成器。
user_track用户追踪
- 等待所有生成器节点有新的数据产生。
- 获取原始彩色图像,并将彩色图像转换成灰度图像并保存在某个Mat的对象中。
- 有用户出现,依次判断生成的userCount的个数,并将每个userCount的数据处理出来。
3.1 利用GetCoM来获取用户的三维坐标(绝对坐标)。
3.2 绝对坐标转换成相对坐标(三维---->二维)。
3.3 根据这些坐标信息转换成角度信息。
3.4 判断是否还在跟踪。
3.4.1 如果还在跟踪的话,利用GetSkeletonCap(Capability获取关节点)来获取特定关节的位置。结构体,包含世界坐标和置信度。
3.4.2 将这些数据用depthGenerator进行绝对坐标和相对坐标之间的变换。
3.4.3 通过imshow显示。
下位机程序步骤
整个程序采用时间片轮询的方法,每个时间段处理不同的任务。
主要分为三个部分:1.传感器数据采集,向电机驱动发布速度指令。2. 在单位采样时间内对数据进行处理、计算,对当前速度、角度以及目标速度和角度采取PID控制。3.将处理好的数据包括位姿、线速度、角速度打包成里程计数据通过串口发布出去。
传感器采集数据,向电机驱动发布速度指令
1.通过定时器和中断采集超声波、红外和编码器的数据。
2.将处理好的速度数据发到电机驱动板
里程计数据处理以及PID控制
里程数据处理
-
在单位时间内采集经过变频之后的编码器数据。
result=(MOTOR1_ROUND_COUNT)*(4*ppr)-(now_encoder_motor1-last_encoder_count_motor1); // 反转 result=(now_encoder_motor1-last_encoder_count_motor1)+(MOTOR1_ROUND_COUNT)*(4*ppr); // 正转
-
计算单个计数值走过的角度(比例,单位长度/周长),长度(变频之后的单位)。
-
在很短的时间内 ,小车行驶的路程为两轮速度之后,小车的角度为两轮速度之差。
-
计算里程计方向角位数变化。
-
经过里程计方向角位数变化计算得到小车的x、y坐标,最后得到线速度、角速度以及方向角。
-
方向角度纠正。
PID控制
1.将目标数据和当前数据进行PID控制,多则减,少则补。
串口接受和发送里程计数据
- 串口指定数据头和数据尾,发送里程计数据
- 接受串口数据,包括人体距离和角度。