范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

给OpenCV初学者的礼物OpenCV人脸检测入门教程

  前言
  OpenCV是一种经常被用到的计算机视觉库。然而,它的文档是只用英文发布的。这对习惯中文阅读的国内计算机爱好者来说并不是太友好,特别是对那些还没受过高等教育但对计算机科学抱有美好向往的普通大众。
  诚然,英文阅读对于业内的大牛们来说并不会带来什么障碍。但是我们栗子社区是要走群众路线的。大牛们虽然技术水平高,但是能力越大责任越大,他们并不能天天来社区陪大家吹水。客观地看,我们的社区的生存根基,其实并不是那少数几个大牛,而是那更广大的初级爱好者,他们才是社区的活力源泉,给论坛源源不断的创造内容和点击。
  OpenCV各版本间的使用方法并不是完全统一的,最新的是OpenCV4.0.1,已经与2.x版本的用法有较大的区别。翻译工作与官方数据手册的发布不可避免的会有滞后性,虽然本文作者已经尽可能选取目前最新版本的文档了,但是这些内容也不可避免的会有一天变成过时的糟粕。所以提醒初学者们,尽信书不如无书。
  很荣幸能成为大家学习OpenCV的领路人。作者祝大家都能在学习的过程中找人生到真正的意义。
  本文的参考文档见https://docs.opencv.org/4.0.1/d1/dfb/intro.html
  图像的基本操作
  对于人类来说,图像可以解构为画面结构、色彩和非常丰富的意象。你可以把它解构为各种色块或线条,然后用故事性的语言把这幅图像存在脑海里。
  反过来,对于计算机来说,这个过程就要机械得多了,计算机只认识组成一副图像的那一个个像素。为了存储这一个个像素,需要像素的坐标和色彩信息。OpenCV以一种叫Mat的结构存储图像,你可以把它理解为一种数据结构,结构上是下图这样的一个表格,表格的行列分布代表像素的行列。
  在上图的各个像素中,颜色又用三原色来表示,即BGR(蓝绿红)。这些BGR数据依次排列如下图。其中,三原色里的每个颜色元素的值域是0-255(即8位),因此每个像素具有8x3位(即24位真彩色)。
  我们来建立一个Mat数据M,存储一个最简单的2x2像素的图像,且每个像素为蓝色(0,0,255),可以这样写。要注意的是,目前最新的OpenCV 4.0.1已经不支持C了,代码文件需要按C++写。
  Mat M(2,2, CV_8UC3, Scalar(0,0,255));//新建2x2像素图像
  imshow("image", M);//显示M的图像
  当然,大多数时候,我们是不会这样傻傻地新建一个图像的。我们可以直接从一个jpg文件里面读取图像,我将把读取图片文件的方法教给大家。
  举个例子,把一个叫Lena的照片放进一个叫M的Mat结构,可以像下面这么写。另外,我们还演示了怎么把一个彩色图像以灰度图的方式读取。
  Mat M = imread("lena.jpg");//图像来自图片文件
  imshow("image", M);//显示M的图像
  Mat img = imread("lena.jpg", IMREAD_GRAYSCALE);//以灰度形式读取图片文件
  imshow("grayimage", img);//显示img的图像(它是灰度图)
  反过来,一个Mat数据,也可以写入文件,这样就把图片给存起来了。举个例子,读取Lena的照片文件,然后存到一个叫out的文件里。
  imwrite("image.jpg", M);//显示M的图像
  Mat img = imread("lena.jpg", IMREAD_GRAYSCALE);//以灰度形式读取图片文件
  imwrite("grayimage.jpg", img);//显示img的图像(它是灰度图)
  一个人脸检测的例子
  这个例子,需要引用3个OpenCV的头文件:
  #include "opencv2/objdetect.hpp"
  #include "opencv2/highgui.hpp"
  #include "opencv2/imgproc.hpp"
  当然,也可以一步到位,把所有的OpenCv库都引了
  #include "opencv2/opencv.hpp"
  应用iostream库,并使用命名空间来减少代码里面文字的输入量
  #include
  using namespace std;
  using namespace cv;
  定义两个分类器,分别用来检测脸和眼睛
  CascadeClassifier face_cascade;
  CascadeClassifier eyes_cascade;
  加载已经训练好的分类器,其中face_cascade_name和eyes_cascade_name是xml格式的分类器文件名。(OpenCV的Github里有已经训练好的模型,可以免费下载)
  face_cascade.load( face_cascade_name );
  eyes_cascade.load( eyes_cascade_name );
  定义一个检测人脸并显示检测结果的函数,函数的输入变量是Mat图像。
  void detectAndDisplay( Mat frame )
  输入的Mat变量frame是彩色的,色彩信息对检测没什么用。所以我们把它转成灰度图,并标准化。
  Mat frame_gray;
  cvtColor( frame, frame_gray, COLOR_BGR2GRAY );//转灰度
  equalizeHist( frame_gray, frame_gray );//标准化
  一张图里有可能会检测到多个人脸,我们可以把检测结果用一个叫faces的向量来存储。用分类器进行多尺度检测的函数叫detectMultiScale,这个函数有两个变量,第一个是输入的图像frame_gray,第二个是输出的结果faces。
  std::vector faces;//准备要存入人脸检测结果的向量
  face_cascade.detectMultiScale( frame_gray, faces );//检测
  由于faces是把检测结果存成了一个向量,所以我们可以用size()函数得到这个向量的长度。下面这个代码循环遍历了每个结果,计算了每张脸的位置。
  for ( size_t i = 0; i < faces.size(); i++ )
  {
  Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );//获得每张脸部中心的xy像素坐标
  ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4 );//给每个脸画个圈圈框起来
  }
  上面这个循环里,还可以把检测到个每个脸的区域单独提取出来,再检测一下眼睛。然后嵌入一个用圈圈框出眼睛的循环。这一步,依然使用detectMultiScale函数进行检测。
  Mat faceROI = frame_gray( faces[i] );//提取脸部区域
  std::vector eyes;//准备要存入眼睛检测结果的向量
  eyes_cascade.detectMultiScale( faceROI, eyes );//检测眼睛
  for ( size_t j = 0; j < eyes.size(); j++ )
  {
  Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );//获得每个眼睛的中心
  int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
  circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4 );//把每个眼睛用圈圈框起来
  }
  接下来,我们把上面的内容整合一下,这个人脸检测并显示检测结果的函数
  detectAndDisplay可以写成这样
  void detectAndDisplay( Mat frame )
  {
  Mat frame_gray;
  cvtColor( frame, frame_gray, COLOR_BGR2GRAY );
  equalizeHist( frame_gray, frame_gray );
  //-- Detect faces
  std::vector faces;
  face_cascade.detectMultiScale( frame_gray, faces );
  for ( size_t i = 0; i < faces.size(); i++ )
  {
  Point center( faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2 );
  ellipse( frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4 );
  Mat faceROI = frame_gray( faces[i] );
  //-- In each face, detect eyes
  std::vector eyes;
  eyes_cascade.detectMultiScale( faceROI, eyes );
  for ( size_t j = 0; j < eyes.size(); j++ )
  {
  Point eye_center( faces[i].x + eyes[j].x + eyes[j].width/2, faces[i].y + eyes[j].y + eyes[j].height/2 );
  int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 );
  circle( frame, eye_center, radius, Scalar( 255, 0, 0 ), 4 );
  }
  }
  //-- Show what you got
  imshow( "Capture - Face detection", frame );
  }
  实际中,循环读摄像头并用这个detectAndDisplay函数进行检测的代码可以这么写。
  Mat frame;//存放摄像头捕获图像的frame变量,它是个Mat数据
  while ( capture.read(frame) )//循环把摄像头图像放入frame变量
  {
  detectAndDisplay( frame );//检测人脸并显示结果
  }
  最后,我们来写一下主函数,把上面那个摄像头读取和人脸检测功能加上。
  int main( int argc, const char** argv )
  {
  CommandLineParser parser(argc, argv,
  "{help h||}"
  "{face_cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|Path to face cascade.}"
  "{eyes_cascade|../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|Path to eyes cascade.}"
  "{camera|0|Camera device number.}");
  parser.about( " This program demonstrates using the cv::CascadeClassifier class to detect objects (Face + eyes) in a video stream. "
  "You can use Haar or LBP features.  " );
  parser.printMessage();
  String face_cascade_name = parser.get("face_cascade");
  String eyes_cascade_name = parser.get("eyes_cascade");
  //-- 1. Load the cascades
  if( !face_cascade.load( face_cascade_name ) )
  {
  cout << "--(!)Error loading face cascade ";
  return -1;
  };
  if( !eyes_cascade.load( eyes_cascade_name ) )
  {
  cout << "--(!)Error loading eyes cascade ";
  return -1;
  };
  int camera_device = parser.get("camera");
  VideoCapture capture;
  //-- 2. Read the video stream
  capture.open( camera_device );
  if ( ! capture.isOpened() )
  {
  cout << "--(!)Error opening video capture ";
  return -1;
  }
  Mat frame;
  while ( capture.read(frame) )
  {
  if( frame.empty() )
  {
  cout << "--(!) No captured frame -- Break! ";
  break;
  }
  //-- 3. Apply the classifier to the frame
  detectAndDisplay( frame );
  if( waitKey(10) == 27 )
  {
  break; // escape
  }
  }
  return 0;
  }
  人脸检测完整的代码可去下方下载
  https://github.com/opencv/opencv/blob/master/samples/cpp/tutorial_code/objectDetection/objectDetection.cpp
  已经训练好的分类器可去下方下载
  https://github.com/opencv/opencv/tree/master/data/haarcascades

巨幕时代到来,客厅秒变电影院随着人们对生活品质的追求,对各类智能应用要求也越来越高,各种人工智能技术都开始应用到家庭场景里,为用户打造更加便捷健康的生活。而在家庭娱乐场景里,智能电视也开始了新一轮的角逐,面板1450元起售?红米6A同款四核芯片,TCL新机正式发布作为传统家电厂商,TCL早早布局智能手机市场,可惜多重原因影响未能站稳脚跟,四五年前基本淡出人们的视野。最新消息显示,TCL旗下一款入门手机发布,搭载联发科多年前的四核低端芯片,而诺基亚N100渲染图蔡司双主摄骁龙8芯片,顶级配置能否重回巅峰诺基亚没能跟上智能手机的脚步,从王者跌到了青铜,产品销量一落千丈,回想当年诺基亚嘲笑苹果触屏操作是一种愚蠢的行为,现在想想都觉得太可笑了。如今诺基亚终于领悟了识时务者为俊杰这个道理毛子的芯片制造能力几乎是0,为啥不怕制裁?有底牌仗着半导体技术领先,老美又开始作妖了。近期,有消息传出,其将对毛熊实行类华为禁令,禁止使用含有美专利的高科技技术及包含技术的相关产品出口。想要借此实行制裁。咱们都知道,全球半导体产iPhone14渲染图曝光,iPhone12沦为百元机,果粉后悔买早了每一代苹果都会吸引外界的目光,比如下一代iPhone14系列就吸引了众多消费者的目光。外媒曝光了下一代iPhone14ProMax的外观设计,采用了打孔的摄像头屏幕。当然,这只是暴我年轻时玩过的四款单反相机,在那个年代已足够风光了那些年,那些岁月,因为喜欢摄影,玩过的相机真的无数了。我第一次接触照相机是1981年,和同学出去玩,他带了一台海鸥4A,他主照,我看得眼馋手痒,他也给我按了几次快门。那感觉,今天似闲谈中德合资相机长江巴尔达小到极致,做口袋机太理想了春节前找东西,无意中翻出一台小相机长江巴尔达。把玩了一阵儿,发现它不是我最初买的的那台,好像是后来二手市场淘来收藏的,于是不死心,继续找,终于找到我最初的那台CE35,而后淘的这台如果微信支付宝需要交会员费,你还会继续使用吗?微信作为我们生活中必不可缺少的一款聊天软件,基本上大部分人已经离不开微信了。所以就有很多网友好奇,如果微信和支付宝也像那些视频网站一样,比如爱奇艺,腾讯视频等各大APP都开始按月收2021年世界前沿科技发展态势总结及2022年趋势展望信息篇国际技术经济研究所全体同仁祝各位读者朋友新年快乐幸福安康。感谢大家长久以来的关注和支持,也期待未来我们能一直有你相伴。我们将在春节期间连续九天献上专题文章年度科技发展态势总结与展望Java9特性响应式流(ReactiveStream)什么是流形象的比喻来说就是如同水一样绵绵不绝的数据形式。而抽象点来说,是有一个生产者(source)产生,由一个或者多个消费者(sink)消费的数据元素(item)序列。那从这个抽冰箱哪个牌子好?分享6个选购要点,买对冰箱再也不是难题冰箱是我们家居生活中很重要的一款家电,一台合适的冰箱可以大大提升我们的家庭幸福感,那么冰箱到底是哪个牌子更好呢?下面给大家分享6个选购要点,让你轻轻松松买对适合自己的冰箱。1冰箱哪
东数西算国家工程全面启动!亨通数字化转型再迎新使命启程奏响新乐章今年2月,历时近两年筹划的东数西算工程正式全面启动,成为继南水北调西电东送西气东输之后,我国第4个跨区域资源调配超级工程,在今年的全国两会上,东数西算也成为当仁不让的大厂回报缩水福利收缩薪资下滑股票没了深燃(shenrancaijing)原创作者唐亚华编辑黎明你的年终绩效为C,年终奖为0。听到HR宣布完结果,王嘉意识到,20多万元的年终奖泡汤了。知道了,我不接受,我会进行申诉。他润建股份(002929。SZ)取得1。02亿元能源网络管维业务合同格隆汇3月22日丨润建股份(002929。SZ)公布,公司近期在能源网络管维业务领域取得清河县10。39兆瓦分布式光伏项目河北华电石家庄赞皇200MW光伏复合项目南皮县屋顶分布式光iPhonexr升级IOS15。4爆雷iPhonexr升级15。4后能否再战两年?2019年10月购入的国行版本,基本每次更新系统都会升级,升级到IOS15以上的系统后,可玩性增强了,功能增加了一部分,但是电池续航降的iOS15。4正式版续航尿崩官方回应来了并附上省电妙招苹果iOS15。4正式版,自推出以来,因为支持戴口罩解锁功能,不少果粉纷纷第一时间升级。近日,越来越多的国内外网友反应,升级到iOS15。4正式版后,续航下降严重。有网友反应自己的国产电视哪个牌子好,海信电视U7G质量怎么样今天给大家介绍这款海信2021年最新款的ULED超画质电视,接下来我们一起体验一下。什么是ULED超画质电视呢?这里要带大家小小科普一下,普通液晶电视最大的问题就是没有背光分区或分世界芯片行业瓶颈将至!台积电首创3D封装芯片,或为国产芯转机?英特尔创始人戈登摩尔提出过一个摩尔定律集成电路上晶体管数量每18个月将增加一倍,同时性能也将提升一倍!这句话给芯片行业定下了一个方向,那就是依靠制程的突破来实现性能的提升,同时也带显卡高溢价时代结束?经销商高阶型号报价雪崩有产品一天内创史上最大跌幅科创板日报(上海,编辑宋子乔)讯,据报道,近日经销商的高端显卡报价暴跌。华硕的高阶显卡RTX3080TUFGAMINGOC价格在澳洲市场一天内大跌35,创史上最大跌幅,其他规格显卡阿里巴巴平台是否值得做?我感觉是这样的首先所有的平台都是大卖家大客户的天下。没有办法,是利益的驱使。人家方案大,成交大,确实有实力。目前全球主要国家的网购比例越来越高,不存在明显的信息差,这就导致原来的批充分认识科技伦理问题的紧迫性和复杂性长江日报评论员秦孟婷近日,中共中央办公厅国务院办公厅印发了关于加强科技伦理治理的意见,旨在进一步完善科技伦理体系,提升科技伦理治理能力,有效防控科技伦理风险,不断推动科技向善造福人浅谈科技成果转化生态体系的构建吴乐斌科技成果转化是一项高度复杂的系统工程,界面多跨度大,跨行跨界跨时跨域,是社会经济发展中的世界性难点热点痛点问题。在中国国情条件下探索如何提升科技成果转化的效率与效益,具有重要