2016-08-27 11:53:00 alppkk4545 阅读数 2

        公司里有哥们想学图像处理,认为这东西看起来挺简单,应该可以很快入门进阶。他人之心,吾忖度之,不能再忖度了,否则会变成以小人之心度君子之腹。所以,应哥们的要求,我给他介绍一个图像处理入门教程。看起来入门比较麻烦,其实,只要功夫深,铁杵磨成针,欲速则不达,慢慢来,日积月累,总有一天可以运用自如,到达信手拈来的地步。


1 通识课程基础

         高等数学的基础概念是入门基础,数学知识不言其多。

         可以参考的基础书籍有《微积分》《数学/泛函分析》《概率论与数理逻辑》 ,很多图像学的基本概念可以从这三本书上找到。


         偏计算机科学的《 离散数学 》,这是计算机科学的基础数学。

         偏控制理论的《非线性动力学》,复杂度/非线性 的提升导致不可控性 ,如果设计复杂算法和大型工程,非线性动力学值得参考。


2 专业基础

        知识作为语义系统有可能在各个学科得到相同的映射,图像处理作为一门应用科学,可以用不同的专业知识来进行阐述。

        对于计算机科学的门徒,推荐这本书

                     

       对于物理学 自动化 信号系统 出身的学生,推荐这本书

                       


3 没有人心甘情愿的为别人探索未知的路径,作为入门的学生,自己的想法只能自己实现。既然图像处理离不开计算机科学,那么计算及科学的基础知识也必须是需要掌握的


        计算 科学的最基础知识:《 计算机硬件原理 》《 计算机软件原理 》    ----------------系统性看懂就行

                                                  《 C/++/Python编程 》《算法与数据结构》   --------------------系统性的学习,精益求精最好

        如果上升到顶层设计,可一参考的书籍有《 软件工程学》《 设计模式 》


4 动手能力

        一门可以操纵指针/内存地址的语言是必须的,因此C语言或者C++语言是绕不过去的坑。当然,你可以只用Matlab,前提是你能保证有一个人乖乖地给你转换代码,而除了已经到达导师这个层次,还有你是别人的小师妹,而这几乎是不可能的事。

       

        

转载于:https://www.cnblogs.com/wishchin/p/9199993.html

2019-10-15 19:07:08 weixin_40198377 阅读数 95

利用Hog特征和SVM分类器进行行人检测

1.基本概念

HOG特征描述符: HOG是一个特征描述符,它基于梯度来计算直方图,能够为特征匹配和目标检测(或识别)提供重要信息。
支持向量机(SVM): SVM是一种算法,可用于对数据进行分类。该方法源于1995年Corinna Cortes和Vadimir Vapnik的论文,可从SVM论文地址链接下载。
行人检测: OpenCV提供了Hog和SVM的API,是已经训练好的分类器,不需要再进行训练。

2.代码示例

import cv2

# 判断两个矩形是否为包含关系,包含返回True,不包含返回False
def is_inside(o, i):
    ox, oy, ow, oh = o
    ix, iy, iw, ih = i
    return ox < ix and oy < iy and ox+ow > ix+iw and oy+oh > iy+ih

# 在图片中检测到行人的位置画矩形
def draw_person(src, person_xy):
    x, y, w, h = person_xy
    cv2.rectangle(src, (x, y), (x+w, y+h), (0, 255, 255), 2)

img = cv2.imread('E:/PycharmProjects/openCV/pictures/ch7_persons.jpg')
cv2.imshow('img', img)
cv2.waitKey(0)

# 调用
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
found, w = hog.detectMultiScale(img)

found_filtered = []

for ri, r in enumerate(found):  # 同时列出数据下标和数据
    for qi, q in enumerate(found):
        if ri != qi and is_inside(r, q):
            break
        else:
            found_filtered.append(r)  # 把检测出的行人位置放在found_filtered中
    for person in found_filtered:
        draw_person(img, person)

cv2.imshow('detect result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.代码分析

# 判断两个矩形是否为包含关系,包含返回True,不包含返回False
def is_inside(o, i):
    ox, oy, ow, oh = o
    ix, iy, iw, ih = i
    return ox < ix and oy < iy and ox+ow > ix+iw and oy+oh > iy+ih

is_inside(o,i)函数用于判断两个矩形是否为包含关系,

hog = cv2.HOGDescriptor() # 调用HOGDescriptor作为检测人的检测器
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) # 通过SVM方法实现
found, w = hog.detectMultiScale(img) # 不需要将图像转为灰度图像

HOG和SVM的API。

4.结果展示

在这里插入图片描述
在这里插入图片描述

2018-10-11 14:13:34 mengjiexu_cn 阅读数 4001

图像分类与检测是现今计算机视觉处理中最为常见的两项任务,本文尽量综述一下传统的图像分类与检测与现今的图像分类与检测技术。以下是要讲的几个方面:

图像分类与检测概述
传统的图像分类与检测方法
现今的图像分类与检测方法

1 图像分类与检测概述

当我们面对一张图片的时候,最基础的任务就是这张图片是什么,是风景图还是人物图、是描写建筑物的还是关于食物的,这就是分类。分类作为一个较为笼统的目标,还是较为好达成的。当知道了图像的类别的时候,进一步的就是检测了,例如我知道这个图像是关于人脸的,那么这个人脸在哪里,能不能把它框出来。检测作为一个较为精细的目标,达成的难度可以说是远大于分类的。

1.1 图像分类与检测的难点

不只是图像分类与检测,几乎所有的关于机器学习的难点,都是特征提取这一步,一旦找到好的特征,分类与检测就变的很容易了。所谓的特征提取就是指构建一种提取算法,提取出图像里目标对象的特征,例如人脸的边缘特征、皮肤的颜色特征等,这个特征需要尽可能的将目标物体与其他物体区分开来,例如需要区分的物体是黑猫和白猫,那么毫无疑问颜色特征是一个很好的特征。但是,生活中遇到的难题往往都是很难去提取特征的,例如在嘈杂的街道上检测行人与车辆,这种任务对于检测算法的正确率要求很高,因为一不小心漏检或错检一个人可能就会带来一场车祸。

1.2 图像分类与检测的评价指标

图像分类的指标比较常见,就是分类的正确率,例如猫狗分类,100张中99张分类正确,那么正确率就是99%的正确率。对于目标检测来说,评价指标就多了一些,主要是检错率、漏检率以及检测meaniou,检错率是指一张图片上有两只猫一只狗,而你的模型检测出了三只猫,那么那第三只猫就是检错的,检错率就是33%;漏检的意思是如果你将上面的图片只检测出一只猫和一只狗的话,那就是漏检了一只猫,漏检率33%;mean_iou指的是你检测出来的目标物体的框和真实的框之间的交并比,如下图:
2 传统的图像分类与检测方法

传统的图像分类与检测的步骤大致是两步:特征提取-》训练分类器

在特征提取阶段,设计者会尝试各种通用特征或者自己设计的特征对图像进行特征提取,我们以人脸检测为例,通用的特征就是HOG、SURF、LBP等特征,而对于人脸效果比较好的特征有鼎鼎大名的haar特征。在选定了这些备用特征之后,设计者会进行尝试特征与权衡利弊,因为对于计算机来说,特征的唯一性、通用性越好,所意味的计算量就越大,设计者必须在保证速度的情况下选择尽量好的特征。

当选择了计算量适中同时能达到要求的准确率的特征例如LBP和haar特征之后,使用传统的机器学习方法例如朴素贝叶斯、adaboost、随机森林等建模方法,训练出一个分类模型,使用这个分类模型来进行图像分类或检测。模型的选择通常要比特征选择简单的多,只需要把备选的模型都试一遍,挑效果最好的模型进行调参,调到极致之后,一个人脸检测模型就做出来的。

走这么一套传统图像检测方法的流程,需要很长的时间,并且每一步都需要做好,最终的模型才会有较好的效果,一旦中间的一步出现错误就会牵一发而动全身。所以使用传统方法做图像处理是需要很大代价的。
3 现今的图像分类和检测方法

自从2015年深度学习占领各大图像处理比赛榜首之后,现在的图像处理大部分使用的方法都是深度学习,也就是神经网络。神经网络通过很多的神经元构建成一层一层的网络,通过激活层来使得模型有很强的非线性拟合的能力。设计者只需要将图像输入,然后告诉模型需要的结果是什么,模型便会自动的学习特征提取与结果映射。

通过深度学习,剩下设计者在传统图像处理时最为费时费力的特征提取的那一部分。设计者只需要设计网络结果,使得网络自动提取的特征越好,效果就会也好,正确率越高。

神经网络本质上是矩阵相乘与非线性的组合,通过很多很多的滤波核,来过滤对结果最为有用的特征而抑制对结果没有用的特征,来进行学习与分类。

现在在工程中最为常用的还是vgg、resnet、inception这几种结构,设计者通常会先直接套用原版的模型对数据进行训练一次,然后选择效果较为好的模型进行微调与模型缩减。因为工程上使用的模型必须在精度高的同时速度要快。常用的模型缩减的方法是减少卷积和个数与减少resnet的模块数。

现在常用的检测模型,还是FRCNN、Mask-RCNN、YOLO、SSD等网络模型,一方面精度确实是高,另一方面速度现在进过优化也可以做到实时了。像上面的人脸检测的功能,只需要准备好人脸图片及对应的框标注文件,便可直接跑模型,得到一个还不错的检测模型。
4 总结

深度学习对于图像处理非常有用,但同时也有一些弊端,例如需要大量数据、调参很依靠经验,需要的计算能力很高等,适合处理很复杂的现实生活场景。传统的图像处理对于特定场景下简单的任务例如文本文档的检测、矫正等,还是非常有用且高效的。

第一次写文章,这是从工程角度写的综述,不足之处恳请批评指正。以后会不定期写写图像处理的一些小项目,欢迎交流。

2018-01-22 15:33:37 tianyuhang8800 阅读数 4312

数字图像处理是计算机科学专业的一门基础学科,而其中人脸识别及分割又是其中最为经典不可缺失的一部分。本文采用MATLAB-VISION包中强大的图像识别功能,对目标图像进行人脸识别。VISION中的级联分类器具有识别人脸,嘴巴,鼻子,左右眼等功能。并且准确度高,能在较为复杂的环境下识别出目标。

程序:

点击打开链接

 

一.人脸识别及分割系统的设计

1.1系统总述

 

   目前,人脸识别的方法有很多,研究的方法也不同,所以有不同的分类方法。根据我们所读入图像中人脸的角度不同,可分为正脸,侧脸的人脸识别。根据合个器官的肤色和形状不同,我们可有基于几何特征和基于肤色的人脸识别。根据读入图像的色彩不同,我们可有彩色和灰度图像的人脸识别。这里我们采用MATLAB-VISION中的trainCascadeObjectDetector分类器对图像进行识别,识别图像为PHOTO1并且将识别出的部分用红色的矩形框出来,便于编程者直观的调试程序。接下来,将图像用函数print();写入本地设为PHOTO2。再次读取刚才写入的图像,与原图对比,此时的图像在所识别的区域加上了一个红色的矩形框。接下来提取红色分量,形成一个只有矩形是红色背景全部为黑色的照片,同样保存。设为PHOTO3,读取PHOTO3,将红色矩形框全部填充再次保存为PHOTO4.

最后我们读取PHOTO1和PHOTO4,将这两幅图像进行点乘。便得到我们的目标图像。

二.各部分模块设计

2.1级联分类器的介绍

   函数名称:TrainCasadeObjectDetector

   函数功能:训练级联分类器

函数原型:

trainCasadeObjectDetector(outputXLMFilenname,positiveInstance,negativeImage;)

2.2识别目标

算法思想大体如下:

   先调用MATLAB-VISION中CascadeObjectDetector级联分类器,用函数imread();读取图像,将图像转换为灰度图像,计算机识别出的目标并不能直观的展现给用户,这里我们采用将识别出的区域用红色的矩形框起来,以便于直观展示给用户。

   部分代码参考如下:

for i =1:size(face_dtect,1) 

rectangle('Position',face_dtect(i,:),'LineWidth',4,'LineStyle','-','EdgeColor','r'); 

end

rectangle();可通过形参设置显示框的线条宽度,种类,和颜色。这里我们设置线条的宽度为4,显示颜色为红色,并且用直线显示。

提取色彩分量:

 

先介绍一下HSV颜色模型:

HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。[i]

这里我们以鼻子为例。首先读取图像,将GRB图像转换为HSV图像。将HSV图像中的红色分量提取出来设为S,再通过graythresh函数找到图片的一个合适的阈值,通过im2bw将灰度图像转化为二值图像。

 

部分代码参考如下:

shibie=imread('shibiebizi.png');

hsv=rgb2hsv(shibie);

s=hsv(:,:,2);

bw=im2bw(s,graythresh(s));

se=strel('disk',5);

bw2=imclose(bw,se);

bw3=bwareaopen(bw2,200);

figure(6);

imshow(bw3);

print(gcf,'-dpng','tiqubizi.png');   %保存为png格式的图片到当前路径

 

2.3填充区域

这里是将前面提取出的红色分量矩形进行填充,再进行后续步骤,先介绍一下填充的函数

Bwlabel();

    L = bwlabel(BW,n)

    返回一个和BW大小相同的L矩阵,包含了标记了BW中每个连通区域的类别,这里采用更为精确的8连通算法。

[L,num] = bwlabel(BW,n)这里num返回的就是BW中连通区域的个数。

 

部分代码参考如下:

tianchong =imread('tiqubizi.png')

J=tianchong(:,:,1);

K=J>30;%阈值分割,30通过工作空间观察得到

[L,num] = bwlabel(K,8);%8连通块标记

F=L>1;%除去周边区域

F(339,269)=1;%在工作空间中找到使最大目标不连通的点,赋值,使之连通

BW2 = imfill(F,'holes');%填充区域

imwrite(BW2,'tianchongbizi.png','png')%用imwrite写没有白边

2.4分割目标

         将填充好的图像和原图点乘,二值图像中0代表黑色,1代表白色。所以处理后的图像只显示白色矩形中的原图。如果原图是灰度图像我们直接点乘,如果是RGB真彩色图像,我们要把图像中的R,G,B分量单独提取出来分别与原图点乘。

部分代码参考如下:

yuantu=imread('zheng.png');

figure(7);

imshow(yuantu)

print(gcf,'-dpng','whitephoto.png')  %保存为png格式的图片到当前路径

yuantu_baibian=imread('whitephoto.png');

 

yan_tianchong= imread('tianchongbizi.png');

I= yuantu_baibian;

R= I(:,:,1);

G= I(:,:,2);

B= I(:,:,3);

m_BG=yan_tianchong;

m_BG=im2bw(m_BG,0.2);%阈值根据实际条件自行设置

%figure(5);imshow(m_BG,[]);

m_BG= uint8(m_BG);

R=R.*m_BG;

G=G.*m_BG;

B=B.*m_BG;

I(:,:,1)=R;

I(:,:,2)=G;

I(:,:,3)=B;

figure(9);imshow(I,[]);

imwrite(I,'Nose.png','png')%用imwrite写没有白边

2.5保存图像

可以用 save(),imwrite(),或者printf();把图像保存在本地。

 


[i]HSV_百度百科

 

2019-03-04 20:03:27 LuohenYJ 阅读数 3682

目录

1基于CNN的性别分类建模原理

1.1 人脸识别

1.2 性别预测

1.3 年龄预测

1.4 结果

2 代码

参考


本教程中,我们将讨论应用于面部的深层学习的有趣应用。我们将估计年龄,并从单个图像中找出该人的性别。模型由GilLevi和TalHassner训练(https://talhassner.github.io/home/publication/2015_CVPR)。本文介绍了如何在OpenCV中使用该模型的步骤说明。Opencv版本3.4.3以上。代码教程代码可以分为四个部分:

1基于CNN的性别分类建模原理

作者使用非常简单的卷积神经网络结构,类似于Caffenet和Alexnet。网络使用3个卷积层、2个全连接层和一个最终的输出层。下面给出了这些层的细节。COV1:第一卷积层具有96个内核大小7的节点。COV2:第二个卷积层Conv层具有256个具有内核大小5的节点。CONV3:第三个CONV层具有384个内核大小为3的节点。两个完全连接的层各自具有512个节点。

训练数据来源:https://talhassner.github.io/home/projects/Adience/Adience-data.html

检测程序主要有四块:检测人脸检测、性别检测、年龄显示和输出。

1.1 人脸识别

我们将使用人脸检测器(tensorflow模型)进行人脸检测。该模型很简单,即使在CPU上也是相当快的。详细见论文:

https://arxiv.org/pdf/1502.00046.pdf

1.2 性别预测

将性别预测设定为一个分类问题。性别预测网络(caffe模型)中的输出层类型为两类,2个节点表示“男性”和“女性”两类。以这两个输出的最大值作为最终的性别。

1.3 年龄预测

理想情况下,年龄预测应该作为一个回归问题来处理。然而通过回归准确估计年龄是很有挑战性的。即使是人类也无法通过观察一个人来准确预测年龄。但是我们能够知道他们是20多岁还是30多岁。由于这个原因,把这个问题描述为一个分类问题是明智的,因为我们试图估计这个人所处的年龄组。例如,0-2范围内的年龄是一个类,4-6是另一个类,依此类推。因此数据集分为以下8个年龄组[(0-2)、(4-6)、(8-12)、(15-20)、(25-32)、(38-43)、(48-53)、(60-100)]。因此,年龄预测网络在最后一层有8个节点,表示所述年龄范围。

应该记住,从一幅图像中预测年龄并不是一个很容易解决的问题,因为感知到的年龄取决于许多因素,而同龄的人在世界各地可能看起来很不一样。而且,人们非常努力地隐藏他们的真实年龄!

我们加载年龄网络(caffe模型)并使用前向通道获得输出。由于网络结构类似于性别网络,所以我们可以从所有输出中提取出最大值来得到预测的年龄组

1.4 结果

尽管性别预测网络表现良好,但年龄预测网络仍未达到我们的预期。所以添加人脸对齐算法或者数据样本很多时候,可以通过回归的模型来检测。但是性别人脸检测还是很准确的。

2 代码

在VS2017下运行了C++代码,其中OpenCV版本至少要3.4.5以上。不然模型读取会有问题。三个模型文件太大,见下载链接:

https://download.csdn.net/download/luohenyj/10993309

​​​​​​​https://github.com/luohenyueji/OpenCV-Practical-Exercise

如果没有积分(系统自动设定资源分数)看看参考链接。我搬运过来的,大修改没有。

其中tensorflow和caffe模型都可以用opencv中的readnet函数读取,流程很简单。看看代码就会。

代码提供了C++和Python版本,但是python版本没有运行,原因opencv版本太低,不想升级。代码都有详细的注释。

C++版本:

#include <tuple>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <iterator>
using namespace cv;
using namespace cv::dnn;
using namespace std;

/**
 * @brief Get the Face Box object 人脸定位
 *
 * @param net 人脸检测网络
 * @param frame 检测图像
 * @param conf_threshold 阈值
 * @return tuple<Mat, vector<vector<int>>> 元组容器,可返回多个值
 */
tuple<Mat, vector<vector<int>>> getFaceBox(Net net, Mat &frame, double conf_threshold)
{
	//图像复制
	Mat frameOpenCVDNN = frame.clone();
	int frameHeight = frameOpenCVDNN.rows;
	int frameWidth = frameOpenCVDNN.cols;
	//缩放尺寸
	double inScaleFactor = 1.0;
	//检测图大小
	Size size = Size(300, 300);
	// std::vector<int> meanVal = {104, 117, 123};
	Scalar meanVal = Scalar(104, 117, 123);

	cv::Mat inputBlob;
	inputBlob = cv::dnn::blobFromImage(frameOpenCVDNN, inScaleFactor, size, meanVal, true, false);
	net.setInput(inputBlob, "data");
	//四维矩阵输出
	cv::Mat detection = net.forward("detection_out");
	//提取结果信息
	cv::Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());

	vector<vector<int>> bboxes;

	for (int i = 0; i < detectionMat.rows; i++)
	{
		//预测概率
		float confidence = detectionMat.at<float>(i, 2);

		if (confidence > conf_threshold)
		{
			//左上角点,坐标被归一化
			int x1 = static_cast<int>(detectionMat.at<float>(i, 3) * frameWidth);
			int y1 = static_cast<int>(detectionMat.at<float>(i, 4) * frameHeight);
			//右下角角点,坐标被归一化
			int x2 = static_cast<int>(detectionMat.at<float>(i, 5) * frameWidth);
			int y2 = static_cast<int>(detectionMat.at<float>(i, 6) * frameHeight);
			vector<int> box = { x1, y1, x2, y2 };
			//人脸坐标
			bboxes.push_back(box);
			//图像框选
			cv::rectangle(frameOpenCVDNN, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(0, 255, 0), 2, 4);
		}
	}

	return make_tuple(frameOpenCVDNN, bboxes);
}

int main(void)
{
	//人脸模型
	string faceProto = "model/opencv_face_detector.pbtxt";
	string faceModel = "model/opencv_face_detector_uint8.pb";

	//年龄模型
	string ageProto = "model/age_deploy.prototxt";
	string ageModel = "model/age_net.caffemodel";

	//性别模型
	string genderProto = "model/gender_deploy.prototxt";
	string genderModel = "model/gender_net.caffemodel";

	//均值
	Scalar MODEL_MEAN_VALUES = Scalar(78.4263377603, 87.7689143744, 114.895847746);

	//年龄段标签
	vector<string> ageList = { "(0-2)", "(4-6)", "(8-12)", "(15-20)", "(25-32)",
		"(38-43)", "(48-53)", "(60-100)" };

	//性别标签
	vector<string> genderList = { "Male", "Female" };

	//导入网络
	Net ageNet = cv::dnn::readNet(ageProto, ageModel);
	Net genderNet = cv::dnn::readNet(genderProto, genderModel);
	Net faceNet = cv::dnn::readNetFromTensorflow(faceModel, faceProto);

	//打开摄像头
	VideoCapture cap;
	cap.open(0);
	if (cap.isOpened())
	{
		cout << "camera is opened!" << endl;
	}
	else
	{
		return 0;
	}

	int padding = 20;
	while (waitKey(1) < 0)
	{
		// read frame 读图
		Mat frame;
		cap.read(frame);
		if (frame.empty())
		{
			waitKey();
			break;
		}
		frame = imread("./images/couple1.jpg");
		//人脸坐标
		vector<vector<int>> bboxes;
		//人脸检测结果图
		Mat frameFace;
		//人脸定位
		//tie()函数解包frameFace和bboxes
		tie(frameFace, bboxes) = getFaceBox(faceNet, frame, 0.7);
		//人脸判断
		if (bboxes.size() == 0)
		{
			cout << "No face detected, checking next frame." << endl;
			continue;
		}
		//逐个提取人脸检测
		for (auto it = begin(bboxes); it != end(bboxes); ++it)
		{
			//框选人脸
			Rect rec(it->at(0) - padding, it->at(1) - padding, it->at(2) - it->at(0) + 2 * padding, it->at(3) - it->at(1) + 2 * padding);
			//避免人脸框选超过图像边缘
			rec.width = ((rec.x + rec.width) > frame.cols) ? (frame.cols - rec.x - 1) : rec.width;
			rec.height = ((rec.y + rec.height) > frame.rows) ? (frame.rows - rec.y - 1) : rec.height;

			// take the ROI of box on the frame,原图中提取人脸
			Mat face = frame(rec);

			//性别检测
			Mat blob;
			blob = blobFromImage(face, 1, Size(227, 227), MODEL_MEAN_VALUES, false);
			genderNet.setInput(blob);
			// string gender_preds; 获取前向传播softmax结果
			vector<float> genderPreds = genderNet.forward();
			// find max element index max_element用于找寻最大值
			// distance function does the argmax() work in C++ distance返回最大值和第一个值下标的距离
			int max_index_gender = std::distance(genderPreds.begin(), max_element(genderPreds.begin(), genderPreds.end()));
			//获得检测结果
			string gender = genderList[max_index_gender];
			cout << "Gender: " << gender << endl;

			//年龄识别
			ageNet.setInput(blob);
			vector<float> agePreds = ageNet.forward();
			// finding maximum indicd in the age_preds vector 找到年龄预测最大下表
			int max_indice_age = std::distance(agePreds.begin(), max_element(agePreds.begin(), agePreds.end()));
			string age = ageList[max_indice_age];
			cout << "Age: " << age << endl;

			// label 输出标签
			string label = gender + ", " + age;
			//在人脸定位图上显示结果
			cv::putText(frameFace, label, Point(it->at(0), it->at(1) - 15), cv::FONT_HERSHEY_SIMPLEX, 0.9, Scalar(0, 255, 255), 2, cv::LINE_AA);
		}
		//保存结果
		imshow("Frame", frameFace);
		imwrite("out.jpg", frameFace);
	}
}

python版本:

# Import required modules
import cv2 as cv
import time
import argparse

def getFaceBox(net, frame, conf_threshold=0.7):
    frameOpencvDnn = frame.copy()
    frameHeight = frameOpencvDnn.shape[0]
    frameWidth = frameOpencvDnn.shape[1]
    blob = cv.dnn.blobFromImage(frameOpencvDnn, 1.0, (300, 300), [104, 117, 123], True, False)

    net.setInput(blob)
    detections = net.forward()
    bboxes = []
    for i in range(detections.shape[2]):
        confidence = detections[0, 0, i, 2]
        if confidence > conf_threshold:
            x1 = int(detections[0, 0, i, 3] * frameWidth)
            y1 = int(detections[0, 0, i, 4] * frameHeight)
            x2 = int(detections[0, 0, i, 5] * frameWidth)
            y2 = int(detections[0, 0, i, 6] * frameHeight)
            bboxes.append([x1, y1, x2, y2])
            cv.rectangle(frameOpencvDnn, (x1, y1), (x2, y2), (0, 255, 0), int(round(frameHeight/150)), 8)
    return frameOpencvDnn, bboxes


parser = argparse.ArgumentParser(description='Use this script to run age and gender recognition using OpenCV.')
parser.add_argument('--input', help='Path to input image or video file. Skip this argument to capture frames from a camera.')

args = parser.parse_args()

faceProto = "age_gender/model/opencv_face_detector.pbtxt"
faceModel = "age_gender/model/opencv_face_detector_uint8.pb"

ageProto = "age_gender/model/age_deploy.prototxt"
ageModel = "age_gender/model/age_net.caffemodel"

genderProto = "age_gender/model/gender_deploy.prototxt"
genderModel = "age_gender/model/gender_net.caffemodel"

MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
ageList = ['(0-2)', '(4-6)', '(8-12)', '(15-20)', '(25-32)', '(38-43)', '(48-53)', '(60-100)']
genderList = ['Male', 'Female']

# Load network
ageNet = cv.dnn.readNet(ageModel, ageProto)
genderNet = cv.dnn.readNet(genderModel, genderProto)
faceNet = cv.dnn.readNet(faceModel, faceProto)

# Open a video file or an image file or a camera stream
cap = cv.VideoCapture(args.input if args.input else 0)
padding = 20
while cv.waitKey(1) < 0:
    # Read frame
    t = time.time()
    hasFrame, frame = cap.read()
    if not hasFrame:
        cv.waitKey()
        break

    frameFace, bboxes = getFaceBox(faceNet, frame)
    if not bboxes:
        print("No face Detected, Checking next frame")
        continue

    for bbox in bboxes:
        # print(bbox)
        face = frame[max(0,bbox[1]-padding):min(bbox[3]+padding,frame.shape[0]-1),max(0,bbox[0]-padding):min(bbox[2]+padding, frame.shape[1]-1)]

        blob = cv.dnn.blobFromImage(face, 1.0, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
        genderNet.setInput(blob)
        genderPreds = genderNet.forward()
        gender = genderList[genderPreds[0].argmax()]
        # print("Gender Output : {}".format(genderPreds))
        print("Gender : {}, conf = {:.3f}".format(gender, genderPreds[0].max()))

        ageNet.setInput(blob)
        agePreds = ageNet.forward()
        age = ageList[agePreds[0].argmax()]
        print("Age Output : {}".format(agePreds))
        print("Age : {}, conf = {:.3f}".format(age, agePreds[0].max()))

        label = "{},{}".format(gender, age)
        cv.putText(frameFace, label, (bbox[0], bbox[1]-10), cv.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2, cv.LINE_AA)
        cv.imshow("Age Gender Demo", frameFace)
        # cv.imwrite("age-gender-out-{}".format(args.input),frameFace)
    print("time : {:.3f}".format(time.time() - t))

参考

https://www.learnopencv.com/age-gender-classification-using-opencv-deep-learning-c-python/

没有更多推荐了,返回首页