第3章
机械臂控制图像识别项目设计
第3章机械臂控制图像识别
设计者:刘泽萱马铭阳
3.1项目背景
本章根据刘泽萱、马铭阳项目设计整理而成。
机械臂是一类能够模仿人手臂的某些动作功能,按固定程序抓取、搬运物件或操作工具的自动操作装置。第一代机械臂能够按事先示教的位置和姿态重复地执行动作。目前,国际上使用的机械臂大多仍是这种工作方式。人脸肖像绘制机器人是当今的热点研究方向之一,基于机器视觉的技术在生产和生活等各个方面都有广泛的应用。本项目基于Arduino开发板,通过蓝牙控制摄像头,在后台对人脸进行艺术化处理。
3.2创新描述
外接摄像头搭载在可控的机械臂上,通过调节机械臂来调控摄像头朝向,以寻找最佳的取图角度。当找到合适角度后进行拍照并将照片存储在后台,进而识别程序可以自动识别图片中的人脸,并进行精确的器官识别,进行艺术化处理。
与网上常见的处理方法相比,本项目的程序可以自动识别图片相关部分并进行处理,不需要额外的人为调控,节约了时间与人力成本。另外,处理后的彩图效果较为美观,对于边缘部分与细节的处理比较好。
3.3功能及总体设计
本作品主要分为三部分进行设计: 可自由调控的机械臂与摄像头; 图像采集程序; 人脸识别与图像处理程序。通过控制机械臂的转动可以调节摄像头角度; 图像采集程序可以通过摄像头进行拍照; 人脸识别与图像处理程序可以对已拍下的照片进行艺术化处理。搭载摄像头的机械臂可以在人工操控下调节方向,寻找一个合适的角度进行拍照; 图像采集程序可以实时显示摄像头拍摄的内容,以确定拍照时存储照片; 人脸识别与图像处理程序可以读取拍下的照片并对照片中的人脸进行识别,精确地分析并提取出人脸器官轮廓后进行预设的艺术化处理。
3.3.1功能介绍
人脸识别与图像处理程序可以读取预定目录中的图片,并识别图片中的人脸。当图中有人脸时,程序可以继续运行并精确地识别出图中的左眼、右眼、鼻子与嘴巴。在识别完五官后,可以按照设定的方法对图片进行处理并输出处理好的图片。
3.3.2总体设计
要实现上述功能需要将作品分成输入与处理两部分进行设计。输入部分选用基于Arduino开发板可自由转动的机械臂搭载USB摄像头进行图像采集; 处理部分由基于OpenCV的库文件完成。
1. 整体框架图
项目整体框图如图31所示。
图31整体框架图
2. 系统流程图
系统流程图如图32所示。
图32系统流程图
3. 总电路图
系统总电路图如图33所示。
图33总电路图
扩展板与Arduino开发板直接连接,底部旋转舵机连接扩展板的9引脚,右边舵机接5引脚,
左边舵机接6引脚。蓝牙模块的T、R、G和V 4个引脚直接与扩展板对应的引脚相连。
3.3.3模块介绍
本项目包括机械臂模块,图像采集模块、人脸识别模块、图像预处理模块和添加文字模块。下面对各模块的功能和相关代码进行介绍。
1. 机械臂模块
1) 功能介绍
通过编程和Arduino开发板的控制,完成对USB摄像头的蓝牙控制,为获取不同角度的照片,提供角度的旋转等功能。可通过手机控制机械臂转动,由蓝牙进行通信。安装APP ServoControl,打开APP后,选取HC06蓝牙编号,实现手机与舵机的连接,手机操控界面如图34所示,通过拖动滑块可调节舵机角度。
图34舵机控制界面
2) 相关代码
#include"CommProtocolData.h"//通信协议
BYTE buf_len = 0;
BYTE buffer[10];
void PrintChar(BYTE c)
{
Serial.print(c);
}
void copyBuf(BYTE *data)
{
for (int i = 0; i {
data[i] = buffer[i];
} //写入二进制数据(data,buf_len)到串口
}
void InitComm(int Baud)
{
Serial.begin(Baud);
}
BYTE GetBuffer(BYTE *data)
{
while (Serial.available())
{
buffer[buf_len] = Serial.read();
//串口输出数据函数,写二进制数据到串口
buf_len++;
}
return buf_len;
}
BYTE GetFrameDataPart(BYTE *data)
{
//串口输出数据函数,写二进制数据到串口
GetBuffer(data);
if ((buf_len >= 8) && (buffer[buf_len - 1] == 0X0A))
{
copyBuf(data);
for (int i = 6; i {
if (data[i] == 0X0D)
{
data[9] = i;
break;
}
}
data[1] -= '0';
data[3] -= '0';
data[4] -= '0';
data[5] -= '0';
if (data[9] == 7)
{
data[6] -= '0';
}
buf_len = 0;
return 1;
}
else
{
return 0;
}
}
void ClearBuffer()
{
buf_len = 0;
}
#include"def.h"
#include
#ifndef MEM_H_
#defineMEM_H_
#defineMEM_LEN 512
#defineMEM_START 0x10
#defineMEM_ENDMEM_LEN
BYTE Write_section(uint16_t addr, BYTE *buf, BYTE len); //设定舵机旋转角度
BYTE Read_section(uint16_t addr, BYTE *buf, BYTE len); //读取舵机旋转角度
BYTE Save_toE2PROM(Servo_info* pInfo); //保存舵机的旋转模式
BYTE Read_fromE2PROM(Servo_info* pInfo); //读取保存舵机的旋转模式
BYTE Write_section(uint16_t addr, BYTE *buf, BYTE len) //设定舵机旋转角度
……