宝马7系红外手势识别原理传感器是摄像头的还是红外的

 > 手势识别
手势识别0人关注
手势识别技术
手势识别资讯
手势识别资料下载
手势识别帖子
手势识别DIY创意
关注此标签的用户(0人)
版权所有 & 深圳华强聚丰电子科技有限公司宝马7系将支持遥控泊车和手势操控
还记得宝马那块带显示屏的超级车钥匙吗?更酷炫的功能来了——宝马刚刚宣布,旗下2016款7系轿车将支持远程遥控停车/出车位,这将使得宝马7系成为支持这一功能的首个量产车型。而操作遥控泊车的正是那个带显示屏的车钥匙。
  和市面上所有自动泊车功能不同的是,宝马7系的自动泊车将不需要驾驶员坐在驾驶室。你可以在驾车到家后,打开车门下车,然后轻松自如地用带显示屏的车钥匙遥控爱车完成泊车。
  这并不是新款宝马7系将配备的唯一炫技功能——它还将支持手势操控。你可以用手势来接听或挂断电话,抑或调节音响的音量。它的行车电脑能够识别单个手指、多个手指甚至是整只手的各种手势,你还可以自定义手势来控制某些功能。好吧,虽然包括我在内的不少人还是更喜欢在汽车上使用方便盲操作的物理按键,但不得不说隔空手势的科技感和高价位的宝马7系还是挺搭的。
  此外,新款宝马7系还将大量使用碳纤维材质,来加强车身强度,同时大幅度减轻车重,以获取更好的燃油经济性。不过要买到具备如此多新技术的豪车,你的钱包必然要大出血了。虽然宝马尚未公布其价格,但2015款美版7系的价格可以大致参考——乞丐版68500美金(折合人民币424700余元),顶配则需要130000美金(折合人民币806000余元)。如果引入国内的话,其价格会更高。
Related Articles
03/08 11:37
机型名称 机型名称 简介 文件格式 rar 应用平台 Win9x,WinNT,WinME,Win2000,WinXP 下载说明 1. 本站提供的程序.图纸.资料或文章部分为网上搜集.网友提供,目的是让大家进行学习,这些资料和文章的版权归原著作者所有.而我们愿意为提供资料的单位.公司及个人提供广告宣传的便利,如果该资料涉及或侵害到您的版权或利益请立即写信通知我们删除. 2. 如发现不能链接下载,请立即写信通知我们处理. 浏览工具 EasyEDA,史上最强大的电路设计工具 简介 文件格式 pdf.r
01/01 16:37
电视机虽然进入到了智能时代,但操控方式一直并不让人满意,目前看来拥有5种方式,分别传统遥控器.新一代智能遥控器.语音识别.摄像头手势识别以及通过手机/PAD的APP应用操控. 智能电视的人机接口方案(NPD DisplaySearch) 智能电视目前一大重点就是内容,所以优秀的人机互动对于用户来说是非常重要的.目前最常见的一种是基于一般的遥控器推出加强版本,内置加速仪和陀螺仪,从而可以进行空中鼠标.体感的操控,这种做法有一打缺陷就是需要依附在把手上,并且透过RF(如2.4GHz)或是蓝芽将定位数
06/02 08:13
微软的Xbox 360 Kinect不再局限于Xbox游戏,越来越多地运用于科技和生活当中,许多企业都在开发使用手势或其它动作来操作设备.近日丰田展示了一个通过Windows 8平板和Kinect来用手势操控滑板的概念技术,相信这一技术在未来会被汽车制造商整合进汽车里面,带来更多的新鲜的驾驶体验. 通过手势可以就操控电动滑板的速度,当你将手靠近Kinect的时候,滑板的速度会渐渐慢下来.丰田公司表示,这类手势可以用于在驾车时控制车内音响的音量,而不需要驾驶员转移注意力. 丰田和微软去年宣布成为合
12/10 14:59
此前曾有消息称Intel将在9系芯片组中提供对SATA Express接口的支持,但随后却取消了这一计划,仅会帮助厂商去通过第三方芯片来实现对SATA Express接口的支持.如此一来9系芯片组可能就彻底沦为8系芯片组的马甲了,但目前最新的消息却显示Intel 9系芯片组并不是马甲,磁盘方面虽然它不支持SATA Express,但还是加入了对PCI-E M.2接口的支持. 外媒Fudzilla报道称Intel要在下一代芯片组中加入了PCI-E M.2接口的支持,其速度比SATA 6Gbps要快
10/14 07:15
壳牌优质机油-壳牌超凡喜力以及鹏斯白金助力宝马赛车运动 壳牌V-Power成为宝马M系汽车推荐高端燃油 继成为宝马原厂发动机机油的推荐供应商和宝马集团全球唯一推荐的售后用油供应商之后,壳牌继续扩大与宝马公司的合作范围.壳牌超凡喜力和鹏斯白金系列润滑油携手宝马赛车运动部门,成为其高级技术合作伙伴和独家高端润滑油供应商.同时,壳牌V-Power将成为宝马M系汽车使用的推荐燃油. 此次合作涉及德国房车大师赛(DTM).帝舵USCC冠军锦标赛和纽博格林24小时耐力赛(德国)等赛事,地区涵盖奥地利.加拿大
03/28 02:34
内置锂电池续航更持久 目前的2.4GHz无线键鼠普遍采用了AA电池供电,而2.4GHz无线手柄则大多采用内置锂电池供电.因此,无线手柄拥有更长时间的电池续航能力,并且其传输距离也能够与2.4GHz无线键鼠相同,可以达到10米之远,每当笔者窝在沙发里看片的时候,便可使用北通这款无线手柄远距离遥控电脑啦. 手柄变身遥控器 把游戏手柄改造成为电脑遥控器,最重要的环节就是需要一款名为JoyToKey的软件进行支持.该软件可以把游戏手柄模拟成电脑键盘,也就是说平时我们通过电脑键盘来完成的操作,如今都可以通
05/13 17:33
德国电脑配件商 Gyration 设计远距离空中鼠标已经有多年历史,今天该厂商新发布了一款 支持更长距离操控的空中鼠标,名为 Air Mouse Go Plus,最长可支持 100 英尺,大约 30 米. 该鼠标可兼容 Windows 电脑和 Mac.据了解,该鼠标既可以充当桌面光学鼠标,也可以作 为动作感应鼠标,它主要是通过一枚 2.4GHz 无线收发器与电脑连接,鼠标内置有一个可拆卸可 充电电池. Air Mouse Go Plus 鼠标很灵活,拥有 3 个可自定义按钮,用户可以在按钮上设置
03/22 08:18
电视也开始跨入了智能时代,搭载了Android系统,用户可以在欣赏传统电视节目的同时,可以安装各种APP,实现对电视功能的扩展.但是传统的红外遥控器在越来越丰富的功能面前显得越来越力不从心.有部分厂商尝试采用语音.眼球以及手势等方法来操控电视,但是在实际的应用中,这些方式的体验并不被用户所认可.本期为大家介绍的FreesPACe是一个非常成熟的体感技术,可以让遥控器像个在空中的鼠标一样,实现点选.滑扫及各种手势操作. 三重组合捕捉动作 Freespace技术是由美国Hillcrestlabs公司
09/15 16:46
一直以来使用的是MacBook Pro,近日入手了一台惠普Folio13.在使用时发现,与MacBook Pro相比,这台超极本的触控板手势方向全部是&翻转&的,操作起来非常不顺手. 经分析,这台MacBookPro预装了Mac OS X Lion,加入了&自然手势&,触控板手势会随滚动条移动的对应方向而移动内容,即与鼠标滚轮滚动方向相反,但如今改用了惠普Folio13,其触控板滚动方向与鼠标滚轮滚动方向一致,操作极为不习惯. 原版驱动设置步骤 如何让普通本拥有Ma首次应用手势控制 新宝马7系6月10日发布
日前,有媒体报道称,全新一代宝马7系(G11/G12)有望于6月10日全球首发。相比上一代车型,全新7系在技术方面明显改进,同时应用了全新的“35up”平台后使用大量轻量化材料,较上代成功减重130kg。
版权声明:本文版权为网易汽车所有,转载请注明出处。网易汽车5月13日报道&日前,有媒体报道称,全新一代(G11/G12)有望于6月10日全球首发。相比上一代,全新7系在技术方面明显改进,同时应用了全新的“35up”平台后使用大量轻量化材料,较上代减重130kg。信息点:1.全新平台减重130kg 2.安全配置升级 3.动力或升级此前曝光的或为全新一代宝马7系旗舰车型谍照从最新曝出的高清侧身照来看,全新宝马7系的B柱处有所调整。另外,从其侧面的大量镀铬元素来看,或为全新一代宝马7系的车型。疑似全新宝马7系官图此前曝光的全新宝马7系谍照从曝光的一系列谍照来看,新一代宝马7系采用开眼角的前大灯,同时前后尾灯以及保险杠等细节也有所变动。此前曝光的全新宝马7系谍照配置方面,新一代宝马7系装备了全液晶仪表盘、第四代iDrive互联网驾驶功能。同时,新一代宝马7系还增加了手势控制系统。用户只要通过在中央控制台区域做出相应的固定手势动作,iDrive系统即可做出响应回复。另外,全新一代7系还配备了带有触控显示技术的智能钥匙,车主可以站在车外遥控车辆自动进出停车位,而停车过程几乎是自动完成的,车辆不但可以自动刹车,也可以实现10°左右的转向角度修正,而车主只要站在8米开外(车辆长度的1.5倍距离)的安全距离用钥匙控制车辆自己停好就可以了。同时,新车使用了升级的iDrive系统与TouchCommand后排控制系统,其中TouchCommand系统是配备宝马应用软件的三星平板,允许后排乘客控制大部分车内功能。全新7系还增加了手势控制系统,用户只需要通过在中控台前方的区域做出相对应的固定手势,iDrive系统就会做出相应的回应。这个功能也是首次应用在量产车型上。此外,新一代宝马7系在安全配置方面也增加了多项功能,比如增加了自适应功能的驾驶模式,以及增强型驾驶辅助系统、遥控泊车等功能。其中,增强型辅助系统通过车辆尾部的雷达传感器,安全系统可以针对车辆后方的区域提供尾部碰撞预防措施并对交叉车流予以警告。同时,带有主动侧面撞击防护的车道偏离警报系统与交通拥堵辅助系统也出现在新一代宝马7系配置中。平台方面,换代车型应用了被称为“碳纤维内核(Carbon Core)”的理念,基于宝马全新平台“35up”后驱平台制造,该平台使用了大量的铝合金、碳纤维(CFRP)等复合材料打造。仅车身部分,就比这一代车型减重了40kg。据了解,除了超轻量化材料的规模化运用外,全新一代宝马7系还系统性地优化现有系统组件,从而实现更加显著的减重效果。与这一代7系相比,全新一代7系的非簧载质量降低15%,车辆自重则降低130kg(现款车型整备质量1910kg-1985kg),以达到提高燃油效率的目的。B58B30发动机动力方面,全新一代宝马7系将搭载新一代B系列直列六缸发动机来替换N54系列发动机,这款全新的发动机代号为B58B30。2.0T四缸车型或称为新车的入门级车型,同时还将保留3.0T的六缸车型,而最高级别的车型依旧搭载W12发动机,排量有望由现款的6.0T调整为源于劳斯莱斯古斯特6.6T发动机。并且还会有插电式混合动力、柴油版车型供消费者选择。此外新车还将会推出高性能版车型M750i,搭载源于M5的4.4L
V8双涡轮增压发动机。传动系统方面,宝马还对8速Steptronic手自一体变速箱改进升级,内部动力传递效率更高,挡位位齿比进一步增大,换挡位策略实现与导航数据联网。此外,前后空气悬架系统也将成为换代宝马7系标准配置。
本文来源:网易汽车
作者:费希
关键词阅读:
不做嘴炮 只管约到
跟贴热词:
文明上网,登录发贴
网友评论仅供其表达个人看法,并不表明网易立场。
宝马7系竞争车型
全新爱丽舍三厢
马自达CX-4
请选择品牌
请选择车系
热门产品:   
:        
:         
热门影院:
用微信扫描二维码分享至好友和朋友圈基于单camera的手势识别 - Linux - 次元立方网 - 电脑知识与技术互动交流平台
基于单camera的手势识别
android平台测试程序见附件。
/s/1gd5nthL
密码: h46g
基于视觉的动作识别,一直以来的最大问题是精度问题。 - -!
刚刚做了一套手势识别的算法,在此做下简单总结
先说下我做的效果:
2m内手掌识别率在90%以上(强光干扰下效果烂成渣渣了。。so。。 扣掉10%)
处理速度,15fps
(arm 4核)
以上效果为平板测试结果
1& 目的: opencv的haar特征库用来训练各种手势其实是很强势,很好用的东西,唯一的缺点是: Haar版权问题。。,
Haar训练需要的样本数也是一个蛮头疼的问题,识别准确性完全取决于样本数量和质量,没有几十k的样本,效果只能呵呵了
还好,条条大路通罗马,
2&外围设备:
摄像头,这是基本的
深度传感器
,这是一直想要的,可惜到现在也没搞到
红外传感器
,同上。。。。。
3& 检测方式:
利用手势的特征点:
手掌的特征点还是挺多的,我使用的是手轮廓的5个内凹陷,再加上相对位置,再加上人体肤色的特征
基本一个完整的手就检测出来了
精度缺失 ,没办法识别3d空间位置,单camera。。。。
--------------------------------code 分割线--------------------------------------------------------
肤色过滤部分
#include &utils.h&
cv::Mat edgeFilter();
void areaFilter(cv::Mat srcMask);
void skinFilter();
cv::Scalar YUV_SKIN_BEGIN = cv::Scalar(0,133,77);
// 论文肤色(0,133,77)-&(256,173,127)
cv::Scalar YUV_SKIN_END
= cv::Scalar(256,173,127);
cv::Scalar COLOR_RED = cv::Scalar(0,0,255);
cv::Scalar COLOR_GREEN = cv::Scalar(0,255,0);
cv::Scalar COLOR_BLUE = cv::Scalar(255,0,0);
#ifdef USE_SHARP
cv::Mat sharpKernal = (cv::Mat_&float&(3, 3) && 0, -1, 0, -1, 5, -1, 0, -1, 0);
cv::Mat morphKernal = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(3,3),cv::Point(1,1) );
cv::Size pSize = cv::Size(320,240);
cv::Mat edgeFilter(){
#ifdef USE_EDGE
#ifdef DEBUG
long begT = getTime(true);
cv::Mat g = gray.clone();
if(withRsize)
resize(g,g,pSize);
equalizeHist(g,g);
Canny(g,g,100,300,3);
g = g & 1;
#ifdef USE_SHARP
long usec = getTime(true);
filter2D(gray, gray, gray.depth(), sharpKernal); //卷积
LOGD(&filter2D(%d*%d): %d us&,gray.cols,gray.rows,(int)(getTime(true)-usec));
#ifdef USE_ERODE
dilate(gray,gray,morphKernal);
if(withRsize)
resize(g,g,src.size());
#ifdef DEBUG
int w = withRsize? 320 : gray.
int h = withRsize? 240 : gray.
cvtColor(g,can,CV_GRAY2BGR);
//src.copyTo(can,g);
//addWeighted(src,1.0,can,1.0,1.0,src);
src = src +
LOGD(&edgeFilter(%d*%d): %d us&,w,h,(int)(getTime(true)-begT));
#endif //USE_EDGE
// 小面积过滤
void areaFilter(cv::Mat srcMask){
#ifdef USE_SF_AREA
#ifdef DEBUG
long usec = getTime(true);
cv::Mat temp = srcMask.clone(); // 二值化图像
std::vector&std::vector&cv::Point& &
std::vector&cv::Vec4i&
findContours(temp, points, vecs,
CV_RETR_EXTERNAL,
CV_CHAIN_APPROX_SIMPLE );
if(points.size()&=0 || vecs.size()&=0) {
skin.setTo(0);
std::vector&std::vector&cv::Point& & points_poly(points.size());
std::vector&cv::Rect& bound(points.size());
std::vector&int& usefulL
std::vector&float& areaL
float max=0;
for(int i=0;i&=0;i=vecs[i][0]){
bound[i] = boundingRect(points[i]);
//噪声过滤(微小面积过滤)
if( points[i].size()&6
|| bound[i].width & MIN_IMAGE_PIX || bound[i].height & MIN_IMAGE_PIX
srcMask(bound[i]).setTo(0);
}else{ // 多边形逼近
approxPolyDP(points[i], points_poly[i],10,true);
float area = fabs(contourArea(points_poly[i]));
// 有用Rect
usefulList.push_back(i);
areaList.push_back(area); // 面积
if(max&area) max =
// 最大面积
max *= 0.01;
int j=usefulList.size()-1;
for(int i=0;j&=0;j--){
i = usefulList.at(j);
float area = areaList.at(j);
if(area&=max) {
srcMask(bound[i]).setTo(0);
#ifdef USE_ERODE
std::vector&int&
std::vector&cv::Point& pos = points_poly[i];
convexHull(cv::Mat(pos), hull, true);
std::vector&cv::Vec4i& // 起始点,终止点,最凹点,凹点深度
convexityDefects(pos,cv::Mat(hull),defects);
int dsize = defects.size();
if(dsize&=0)
int miniDis = MAX(bound[i].width,bound[i].height)&&3;
for(int j=0;j&j++){
if(miniDis&(defects[j][3]&&8))
cv::Rect rect = cv::Rect(pos[defects[j][2]].x-(miniDis&&1)
,pos[defects[j][2]].y-(miniDis&&1)
,(miniDis)
,(miniDis));
cv::Mat roi = srcMask(rect);
cv::Mat kernel = getStructuringElement(cv::MORPH_RECT,cv::Size(3,(miniDis&&1)+1),cv::Point(1,(miniDis&&2)+1) );
erode(roi,roi,kernel);
medianBlur(roi,roi,3);
}catch(cv::Exception e){}
#ifdef DEBUG
LOGD(&areaFilter(%d*%d): %d us&,srcMask.cols,srcMask.rows,(int)(getTime(true)-usec));
cv::Mat skin_
void *edgeFilterT(void*){
skin_img = edgeFilter();
void skinFilter(){
#ifdef DEBUG
long usec = getTime(true);
LOGD(&skinFilter()&);
#ifdef USE_EDGE
err = pthread_create(&tid,NULL,&edgeFilterT,NULL);
if(err!=0){
skin_img = edgeFilter();
cv::Mat tmpC
cv::cvtColor(src,tmpColor,CV_BGR2YCrCb);
cv::Mat skinMask = cv::Mat::zeros(tmpColor.size(),CV_8UC1);
cv::inRange(tmpColor,YUV_SKIN_BEGIN,YUV_SKIN_END,skinMask);
#ifdef USE_EDGE
if(err==0){
err = pthread_join(tid,NULL);
skinMask -= skin_
cany = skin_
skinMask -=
#ifdef USE_SF_AREA
areaFilter(skinMask);
#ifdef DEBUG
LOGD(&skinFilter:BGR-&YUV:(%d,%d) : %d us&,src.cols,src.rows,(int)(getTime(true)-usec));
mask = skinM
// yuv uv分量肤色mask
手掌识别部分:
#include &utils.h&
// (0 - 3)
3:误判最多
#define PLAM_THRESHOLD 0
bool isPlamFound =
bool withPlam =
void actionPlam(RectHold found);
void actionFist(cv::Point center);
void findArea(); // 面积处理
bool findPlam(cv::Mat mask,cv::Rect roi);
int getDistance(cv::Point p1,cv::Point p2,bool usemax=false);
//void findPlam(std::vector&UsefulContours& uContours);
// 计算轮廓
int getDistance(cv::Point p1,cv::Point p2,bool usemax) {
int x = abs(p1.x-p2.x);
int y = abs(p1.y-p2.y);
return usemax ? MAX(x,y) : sqrt(x*x+y*y);
void actionPlam(RectHold found){
//#ifdef DEBUG
if(showRect)
rectangle(src,found.bound.tl(),found.bound.br(),COLOR_RED,3,8,0);
LOGD(&found plam (%d,%d) ,%d&,found.center.x,found.center.y,found.c);
cv::Rect pRect = found.
//lastPlamHold.lastRect = cv::Rect(pRect.tl(),pRect.br());
lastPlamHold.lastRect = found.
lastPlamHold.center = found.
lastPlamHold.area = found.
lastPlamHold.arc = found.
// lastPlamHold.centRect = cv::Rect(found.center.x-(pRect.width&&2)
,found.center.y-(pRect.height&&2) ,pRect.width&&1 ,pRect.height&&1);
lastPlamHold.centRect = found.cR
if(!lastPlamHold.used){
lastPlamHold.used =
lastPlamHold.unHoldCount=0;
#ifdef USE_OPT_FLOW
#ifndef OPT_NEED_INIT
withPlam =
// 关闭camshift
#ifdef USE_CAMSHIFT
#ifdef USE_FIST
trackRect =
initBackproj =
trackRect =
initBackproj =
#endif // USE_FIST
#endif // USE_CAMSHIFT
/////////////////
lastPlamHold.type = TYPE_PLAM;
callJava(lastPlamHold.type,lastPlamHold.center);
void actionFist(cv::Point center){
lastPlamHold.used =
lastPlamHold.unHoldCount=0;
lastPlamHold.center =
// 关闭camshift
#ifdef USE_CAMSHIFT
trackRect =
initBackproj =
#endif // USE_CAMSHIFT
/////////////////
lastPlamHold.type = TYPE_FIST;
callJava(lastPlamHold.type,lastPlamHold.center);
cv::Mat plam_
cv::Rect plam_
pthread_mutex_t locker = PTHREAD_MUTEX_INITIALIZER;
void *findPlamT(void*){
findPlam(plam_img,plam_rect);
截取不同区域计算手掌
long pTime = 0;
std::vector&RectHold& pH
bool findPlam(cv::Mat mask,cv::Rect roi){
#ifdef DEBUG
long beginT = getTime(true);
cv::Point sp = cv::Point(roi.x,roi.y);
std::vector&cv::Point&
std::vector&cv::Point&
contours_poly_
std::vector&RectHold& plamH
float max = -1;
float arc = -1;
int width = roi.width && 1;
int height = roi.height && 1;
bool wLarge = width &=
int mMax = MAX(roi.width,roi.height);
int mMin = MIN(roi.width,roi.height);
if(mMin&=8)
int sv = mMax/mM
if(sv&1 && mMax&30){
//if(false) {
// width : height not normal split it
cv::Rect roiRect1,roiRect2;
// 截取两端
int x,y,w,h;
if(wLarge){
// (0,0,1.5w,1.5h)
// for roiRect1
w = roi.height + height - (height&&2);
// for roiRect2
x = roi.x+roi.width-w;
y = roi.y;
h = roi.width + width - (width&&2);
x = roi.x;
y = roi.y+roi.height-h;
roiRect1 = cv::Rect(roi.x,roi.y,w,h) & cv::Rect(0,0,mask.cols,mask.rows);
roiRect2 = cv::Rect(x,y,w,h) & cv::Rect(0,0,mask.cols,mask.rows);
plam_img =
plam_rect = roiRect1;
#ifdef USE_THREAD
pthread_create(&tid,NULL,&findPlamT,NULL);
findPlam(mask,roiRect1);// recursive
findPlam(mask,roiRect2);// recursive
#ifdef USE_THREAD
pthread_join(tid,NULL);
cv::Mat tmp = mask(roi).clone();
std::vector&std::vector&cv::Point& &
std::vector&cv::Vec4i&
findContours(tmp,contours,vecs,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
if(contours.size()&=0 || vecs.size()&=0)
std::vector&std::vector&cv::Point& & contours_poly(contours.size());
std::vector&cv::Rect& bound(contours.size());
for(int i=0;i&=0;i=vecs[i][0]){
bound[i] = boundingRect(contours[i]);
if(contours[i].size()&6
&& bound[i].width&width
&& bound[i].height&height){
approxPolyDP(contours[i],contours_poly[i],5.0,true);
if(contours_poly[i].size()&=3)
float area = fabs(contourArea(contours_poly[i]));
if(area&max){
arc = arcLength(contours_poly[i],true);
bound_find = bound[i];
contours_find = contours[i];
contours_poly_find = contours_poly[i];
} // for end
if(contours_poly_find.size()&=3)
cv::Rect shRect = cv::Rect(bound_find.x+roi.x,bound_find.y+roi.y,bound_find.width,bound_find.height);
// now we find the max area,let's find out the plam
//Moments m = moments(contours_find,false);
// 绘制 凸包
cv::Rect cRect = cv::Rect(bound_find.x + (bound_find.width&&2)
,bound_find.y + (bound_find.height&&2)
,bound_find.width&&1
,bound_find.height&&1);
cv::Point center = cv::Point(cRect.x+(cRect.width&&1),cRect.y+(cRect.height&&1))+
if(lastPlamHold.used && lastPlamHold.centRect.contains(center)){
rectangle(src,cRect.tl()+sp,cRect.br()+sp,COLOR_RED,3,8,0);
isPlamFound =
//rectangle(src,cRect.tl()+sp,cRect.br()+sp,COLOR_RED,0.5,8,0);
std::vector&int&
std::vector&cv::Point& pos = contours_poly_
convexHull(cv::Mat(pos), hull, true);
std::vector&cv::Vec4i& // 起始点,终止点,最凹点,凹点深度
convexityDefects(pos,cv::Mat(hull),defects);
int dsize = defects.size();
if(dsize&=0)
// 凸凹陷点均值
int avg=0;
for(int j=0;j&j++)
avg += (defects[j][3] &&8);
int miniDis = avg&&1;
cv::Point fixP = cv::Point(0,0); // 偏移修正量
int actSize = 0;
std::vector&int& pH
for(int j=0;j&j++){
if((defects[j][3]&&8) &= avg){
pHold.push_back(j);
cv::Point depP = pos[defects[j][2]]; //凸凹陷点
// cRect = 1/2 Bound.Rect
// 向落入cRect的极值点方向偏移,偏移量 fixP(x,y)
if(cRect.contains(pos[defects[j][2]])){ // 蓝色 一次修正
#ifdef DEBUG
if(showRect){
circle(src,pos[defects[j][2]]+sp,4,COLOR_BLUE,0.5,CV_AA);
line(src,pos[defects[j][1]]+sp,pos[defects[j][0]]+sp,COLOR_BLUE,2,CV_AA);
fixP.x += depP.x;
fixP.y += depP.y;
actSize ++;
#ifdef DEBUG
if(showRect){
cv::Vec4i vec = defects[j];
line(src,pos[vec[0]]+sp,pos[vec[2]]+sp,COLOR_RED,1.5,CV_AA);
line(src,pos[vec[1]]+sp,pos[vec[2]]+sp,COLOR_RED,2,CV_AA);
// farthest_pt_index
circle(src,pos[vec[2]]+sp,4,COLOR_RED,1,CV_AA);
circle(src,pos[vec[1]]+sp,4,COLOR_BLUE,2,CV_AA);
circle(src,pos[vec[0]]+sp,4,COLOR_GREEN,1,CV_AA);
} // end showRect
}//end for defects.size();
if(actSize&=1) {
#ifdef USE_NEW_FIST
// ==========================maybe fist
int areaBit = (int)lastPlamHold.area/
//int pMax = MAX(abs(lastPlamHold.center.x-center.x),abs(lastPlamHold.center.y-center.y));
if(lastPlamHold.used&&lastPlamHold.centRect.contains(center)
&& lastPlamHold.lastRect.width & shRect.width
&& lastPlamHold.lastRect.height & shRect.width
//&& pMax&2
&& areaBit&=0 && areaBit&3
//&& pHold.size()&=2
rectangle(src,shRect.tl(),shRect.br(),COLOR_BLUE,3,8,0);
actionFist(center);
if(lastPlamHold.unHoldCount++&fps) lastPlamHold.used=
initBackproj =
sRect = cRect & cv::Rect(0,0,src.cols,src.rows);
// fixP 偏移修正(x,y)
fixP.x /= actS
fixP.y /= actS
fixP.x -= (cRect.x + (cRect.width&&1));
// fixP 中心偏移
fixP.y -= (cRect.y + (cRect.height&&1));
// 修正后的rect
int lx = MIN(cRect.width,cRect.height)&&3;
cv::Rect actRect = cv::Rect(cRect.x+fixP.x-lx,cRect.y+fixP.y-lx
,cRect.width+(lx&&1),cRect.height+(lx&&1));
#ifdef DEBUG
rectangle(src,actRect.tl()+sp,actRect.br()+sp,COLOR_RED,0.5,8,0);
std::vector&int& tmpH
for(int i=pHold.size()-1;i&=0;i--){
cv::Point p = pos[defects[pHold[i]][2]];
if(actRect.contains(p))
tmpHold.push_back(pHold[i]);
// 判断极值点是否过近
for(int i=tmpHold.size()-1;i&0;i--){
cv::Point p1 = pos[defects[tmpHold[i]][2]];
cv::Point p2 = pos[defects[tmpHold[i-1]][2]];
int x = MAX(p1.x,p2.x)-MIN(p1.x,p2.x);
int y = MAX(p1.y,p2.y)-MIN(p1.y,p2.y);
if(MAX(x,y)&=(lx)) {
int actP=0; // 生效点个数
// 判断极值点是否与左右相连
dsize = tmpHold.size();
for(int i=0;i&i++){
int pl = tmpHold[(i+1)%dsize];
int p = tmpHold[i];
int pr = tmpHold[(i+dsize-1)%dsize];
int pdl = getDistance(pos[defects[p][0]],pos[defects[pl][1]],true);
int pdr = getDistance(pos[defects[p][1]],pos[defects[pr][0]],true);
if(pdl&miniDis || pdr & miniDis){
if(actP&=(3-PLAM_THRESHOLD)){
//rectangle(src,roi.tl(),roi.br(),COLOR_RED,3,8,0);
hold.bound =
hold.cRect = actRect +
hold.center.x = hold.cRect.x + (hold.cRect.width&&1);
hold.center.y = hold.cRect.y + (hold.cRect.height&&1);
hold.c = 1;
hold.area =
hold.arc =
plamHold.push_back(hold);
}catch(cv::Exception e){}
if(plamHold.size()&=0) {
#ifdef DEBUG
LOGD(&findPlam(%d*%d) (no): %d us&,roi.width,roi.height,(int)(getTime(true)-beginT));
isPlamFound =
// viewpager ass this fist open
if(lastPlamHold.unHoldCount++&fps)
lastPlamHold.used=
#ifdef USE_FPS_PLAM
actionPlam(plamHold[0]);
isPlamFound =
初始化时间较长
long t = getTime();
if(pTime!=t){
LOGD(& time out....&);
std::vector&RectHold& tmpH
#ifdef USE_THREAD
pthread_mutex_lock(&locker);
for(int i=pHolds.size()-1;i&=0;i--){
if(pHolds[i].c&2)
tmpHold.push_back(pHolds[i]);
std::swap(pHolds,tmpHold);
#ifdef USE_THREAD
pthread_mutex_unlock(&locker);
if(pHolds.size()==0){
#ifdef USE_THREAD
pthread_mutex_lock(&locker);
std::swap(pHolds,plamHold);
#ifdef USE_THREAD
pthread_mutex_unlock(&locker);
for(int i=plamHold.size()-1;i&=0;i--){
bool unFind =
RectHold ph = plamHold[i];
#ifdef USE_THREAD
pthread_mutex_lock(&locker);
for(int j=pHolds.size()-1;j&=0;j--){
RectHold actHold = pHolds[j];
if(actHold.cRect.contains(ph.center)){
pHolds[j].c += ph.c;
LOGD(&__plam hold count: (%d)
fps:%d&,pHolds[j].c,fps);
if(pHolds[j].c &= (fps&&2)){
//#ifdef DEBUG
rectangle(src,actHold.bound,COLOR_RED,3,8,0);
isPlamFound =
actHold.c = (fps&&2)+2;
pHolds.clear();
pHolds.push_back(actHold);
actionPlam(actHold);
pthread_mutex_unlock(&locker);
if(unFind){
pHolds.push_back(ph);
#ifdef USE_THREAD
pthread_mutex_unlock(&locker);
#ifdef DEBUG
LOGD(&findPlam(%d*%d): %d us&,roi.width,roi.height,(int)(getTime(true)-beginT));
void findArea(){
#ifdef DEBUG
long beginT = getTime(true);
//std::vector&UsefulContours& usefulContoursL
cv::Mat temp = mask.clone(); // 二值化图像
std::vector&std::vector&cv::Point& &
std::vector&cv::Vec4i&
findContours(temp, points, vecs,
CV_RETR_EXTERNAL,
CV_CHAIN_APPROX_SIMPLE );
if(points.size()&=0 || vecs.size()&=0) {
skin.setTo(0);
std::vector&std::vector&cv::Point& & points_poly(points.size());
std::vector&cv::Rect& bound(points.size());
//std::vector&int& usefulL
//std::vector&float& areaL
for(int i=0;i&=0;i=vecs[i][0]){
bound[i] = boundingRect(points[i]);
if( points[i].size()&6) {
mask(bound[i]).setTo(0);
}else{ // 多边形逼近
#ifdef DEBUG
approxPolyDP(points[i], points_poly[i],10,true);
if(showRect) drawContours(src,points_poly,i,COLOR_GREEN);
float area = fabs(contourArea(points_poly[i]));
// 有用Rect
usefulList.push_back(i);
areaList.push_back(area); // 面积
if(withPlam)
findPlam(mask,bound[i]);
int j=usefulList.size()-1;
usefulContoursList.clear();
for(int i=0;j&=0;j--){
i = usefulList.at(j);
float area = areaList.at(j);
if(showRect) {
drawContours(src,points_poly,i,COLOR_GREEN);
float arc = arcLength(points_poly[i],true);
// this has some err
if(arc&=0)
cv::Moments m = moments(points[i],false);
if(m.m00&=0)
my.poly = points_poly[i];
// my.poly = points[i];
my.bound = bound[i];
my.ratio = area/
my.center = cv::Point2f(m.m10/m.m00,m.m01/m.m00);
usefulContoursList.push_back(my);
//findPlam(srcMask,bound[i]);
//////////噪声过滤完毕,开始处理图像
skin.setTo(0);
src.copyTo(skin,mask);
#ifdef DEBUG
addWeighted(src,0.5,skin,0.9,1.0,src);
LOGD(&findArea(%d*%d): %d us&,skin.cols,skin.rows,(int)(getTime(true)-beginT));
PLAM_INIT_ET
if(!isPlamFound){
if(lastPlamHold.unHoldCount++&30){
lastPlamHold.unHoldCount = 0;
lastPlamHold.used =
延伸阅读:
Linux内核版本号:linux2 6 39交叉编译工具:arm-l...
本教程为 李华明 编著的iOS-Cocos2d游戏开发系列教程:教程涵盖关于i......
专题主要学习DirectX的初级编程入门学习,对Directx11的入门及初学者有......
&面向对象的JavaScript&这一说法多少有些冗余,因为JavaScript 语言本......
Windows7系统专题 无论是升级操作系统、资料备份、加强资料的安全及管......

我要回帖

更多关于 宝马7系全景摄像头 的文章

 

随机推荐