最近长沙疫情不能出门,就只能在家里玩玩,刚好把项目组的leapmotion带回来了,就把互联网+省赛还未完全实现的代码,给实现下,一周前立下个flag要把手势识别系统做出来,结果几天都在玩游戏,想着不行啊,要动手做了,白天干了2天,熬了两天的夜,困难很多还是给肝出来了
间短介绍:leapmotion是我觉得是一款很不错的“玩具”,3D手模型,三维坐标,优秀的精度,200fps的刷新率,其实从项目组买leapmotion,到我真正上手它,到做完这个小项目,其实不到一个月,所以个人感觉上手不难。强烈建议要看文章末尾的BUG总结
开发语言:C,C++
开发者:杨富超
编译器工具:vs2019
leapmotion版本:4.1.0
opencv版本:4.1.0
CSDN源码下载:项目源码
动图展示
int sum = 0;//计算平均值用
long long int num = 0;//ave_number帧一算
int ave_number = 5;//多少帧一算
然后再调用的函数中用个小算法,num每一帧加一,sum加上每次的hand.grabAngle(),num是五的倍数时,再算平均值,最后把sum归零
static void OnFrame(const LEAP_TRACKING_EVENT* frame) {
printf("Frame %lli with %i hands.\n", (long long int)frame->info.frame_id, frame->nHands);//几只手
num++;
for (uint32_t h = 0; h < frame->nHands; h++) {//几个手
LEAP_HAND* hand = &frame->pHands[h];
printf(" Hand id %i is a %s hand with position (%f, %f, %f).\nthumb:(%f,%f,%f)\n",
hand->id,
(hand->type == eLeapHandType_Left ? "left" : "right"),
hand->palm.position.x,
hand->palm.position.y,
hand->palm.position.z,
hand->thumb.bones->next_joint.x,
hand->thumb.bones->next_joint.y,
hand->thumb.bones->next_joint.z
);
sum += hand->grab_angle;//五次的总值
if (num % ave_number == 0)
{
int average = sum / ave_number;//五次的平均值
if (average >= 2.2)
{
printf("石头");
CAdd(3);
}
else if (average < 0.6)
{
printf("布");
CAdd(1);
}
else
{
printf("剪刀");
CAdd(2);
}
sum = 0;
}
}
}
//1:布 2:剪刀 3:拳头 4:数字一 5:数字二 6:数字三 7:数字四 8:数字五 9:点赞 10:ok
void CAdd(int num)
{
std::cout << "Hello OpenCV4.10!\n";
Mat img;
if (num == 1)
{
img = imread("image/a1.png", IMREAD_ANYCOLOR);
}
else if (num==2)
{
img = imread("image/a2.png", IMREAD_ANYCOLOR);
}
else if (num == 3)
{
img = imread("image/a3.png", IMREAD_ANYCOLOR);
}
else if (num == 4)
{
img = imread("image/a4.png", IMREAD_ANYCOLOR);
}
else if (num == 5)
{
img = imread("image/a5.png", IMREAD_ANYCOLOR);
}
else if (num == 6)
{
img = imread("image/a6.png", IMREAD_ANYCOLOR);
}
else if (num == 7)
{
img = imread("image/a7.png", IMREAD_ANYCOLOR);
}
else if (num == 8)
{
img = imread("image/a8.png", IMREAD_ANYCOLOR);
}
else if (num == 9)
{
img = imread("image/good.png", IMREAD_ANYCOLOR);
}
else if (num == 10)
{
img = imread("image/ok.png", IMREAD_ANYCOLOR);
}
if (!img.data)
{
printf("error,no image!\n");
}
imshow("图片显示", img);
waitKey(1);
}
4.对于数字识别,要先了解leapmotion的另外一个函数:hand->digits[0].is_extended,digits[5]是个包含五个手指的数组,digits[0]是大拇指,is_extended函数是bool类型的,如果这个手指伸直,那么就返回true,否则返回flase,有了这个函数,我们可以识别很多的手势,例如:数字一,食指伸直且其他手指均弯曲。介绍下leapmotion另外一个函数hand.pinch_distance,这个函数是返回大拇指与食指间的距离,多用于捏取手势识别,其实is_extended也能用上面介绍的函数hand.grab_angle来做,只是我还没摸清他们的大致判断范围,之后会把范围发表出来
/** Callback for when a frame of tracking data is available. */
static void OnFrame(const LEAP_TRACKING_EVENT* frame) {
printf("Frame %lli with %i hands.\n", (long long int)frame->info.frame_id, frame->nHands);//几只手
num++;
for (uint32_t h = 0; h < frame->nHands; h++) {//几个手
LEAP_HAND* hand = &frame->pHands[h];
printf(" Hand id %i is a %s hand with position (%f, %f, %f).\nthumb:(%f,%f,%f)\n",
hand->id,
(hand->type == eLeapHandType_Left ? "left" : "right"),
hand->palm.position.x,
hand->palm.position.y,
hand->palm.position.z,
hand->thumb.bones->next_joint.x,
hand->thumb.bones->next_joint.y,
hand->thumb.bones->next_joint.z
);
sum += hand->grab_angle;//五次的总值
//1:布 2:剪刀 3:拳头 4:数字一 5:数字二 6:数字三 7:数字四 8:数字五 9:点赞 10:ok
if (hand->digits[0].is_extended && !hand->digits[1].is_extended && !hand->digits[2].is_extended && !hand->digits[3].is_extended && !hand->digits[4].is_extended)
{
printf("点赞\n");
CAdd(9);
}
else if (hand->pinch_distance < 3.0 && hand->digits[2].is_extended && hand->digits[3].is_extended && hand->digits[4].is_extended)
{
printf("欧克");
CAdd(10);
}
else if (!hand->digits[0].is_extended && hand->digits[1].is_extended && !hand->digits[2].is_extended && !hand->digits[3].is_extended && !hand->digits[4].is_extended)
{
printf("数字一\n");
CAdd(4);
}
else if (!hand->digits[0].is_extended && hand->digits[1].is_extended && hand->digits[2].is_extended && !hand->digits[3].is_extended && !hand->digits[4].is_extended)
{
printf("数字二");
CAdd(5);
}
else if (!hand->digits[0].is_extended && !hand->digits[1].is_extended && hand->digits[2].is_extended && hand->digits[3].is_extended && hand->digits[4].is_extended)
{
printf("数字三");
CAdd(6);
}
else if (!hand->digits[0].is_extended && hand->digits[1].is_extended && hand->digits[2].is_extended && hand->digits[3].is_extended && hand->digits[4].is_extended)
{
printf("数字四");
CAdd(7);
}
else if (hand->digits[0].is_extended && hand->digits[1].is_extended && hand->digits[2].is_extended && hand->digits[3].is_extended && hand->digits[4].is_extended)
{
printf("数字五");
CAdd(8);
}
}
}
看到一篇博客,很有启发
晚上和hxd开黑,遇到了玩的菜的喷子,我当时就想,长了张嘴可惜了,喷子不如日常用手语交流。突然想到leapmotion可以做一个手语交流模型,就有了下面这个备忘录,嗯哼,大二的大创课题有了。
开干,发现问题了,因为下载的官方的SDK,直接打开的文件夹,没有配置,也就是根本不算一个真正的项目,后期配置不了opencv与数据库,所以决定配置完整的项目。
网上找博客,配置vs如何配置leapmotion,链接我放在后面的leapmotion的BUG模块了。过程当然是不出意外的话,要出意外了,一个LeapC.lib一直找不到,exe还打不开了,重新新建了项目,重新配置,删除官方文档多余的.c文件,.h文件,又遇到main函数重复,人麻了从凌晨弄到2点,心态崩了,去刷了会儿抖音,然后接着干,因为OpenCV只能配置到.cpp的文件,期间又遇到了.cpp与官方文档的sample里面的.c文件不兼容的问题,LeapC.lib还是没找到,exe在电脑重启后解决了。项目前后看了不下150篇各种网站的博客,帖子,leapmotion在国内的问题解决方案与案例真的还是太少了。最后的BUG介绍值得一看
凌晨到早上八点一直调bug,熬到了天亮早上8点,去睡觉了,困。
下午两点接着干,在LeapC.lib以几乎碰运气得方式解决后,四点成功配置完成leapmotion
后来继续睡了会儿,起来配置完所有的opencv与.c与.cpp之间函数的互相调用,所有项目配置完成。然后写算法,找图片,写代码框架,以后再添手势,就是参数问题了,简便很多。毕竟项目组今年获得了互联网+的省金,暑假继续出力,希望明年进国赛
解决方案: 1.项目属性的包含目录大概率路径不正确
2.直接把官方文档的LeapC.h复制到项目头文件中
解决方案,1.重启VS,2.重启电脑,是因为.exe已经打开过了,不能再次打开,但是它在哪个端口你并不知道,所以重启关闭端口,解决问题。
解决方案,1,检查目录,标红地方是否正确
2.检查附加依赖项,注意是LeapC.lib,之前很多博主都是Leapd.lib,或是Leap.lib,都是错的
3.用这个代码来找,加上还是错的话,把LeapC.lib直接复制进来,这个方法一样适合于opencv的lib找不到
#pragma comment(lib,"LeapC.lib")
解决方案:
C与C++互相调用
解决方案:解决方案——属性–多个启动项目–选择项目启动
解决方案:新建.cpp文件写入opencv的函数,上面用.c与.cpp互相调用的方法
原理:.c与.cpp(C++)的接口不相容
解决方法:1 .c与.cpp不兼容,更改后缀名
2. lib配置不正确,看上面的lib配置方法
码文不易,期待一间三联!!!