版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
人工智能基础与应用(微课版)工业和信息化精品系列教材——人工智能技术第8章计算机视觉处理重点AKEY知识计算机视觉开发介绍手写数字识别人脸识别手写数字识别计算机视觉开发介绍人脸识别8.1计算机视觉开发介绍计算机视觉是一个跨学科的领域,涉及的部分学科如图8-1所示。图8-1计算机视觉涉及的部分学科8.1计算机视觉开发介绍计算机视觉是深度学习最先取得突破性成就的领域。2012年,在ILSVRC大赛上,基于卷积神经网络的AlexNet模型获得了当年图像分类的冠军。历年ILSVRC比赛冠军模型错误率如图8-2所示。图8-2历年ILSVRC比赛冠军模型错误率8.1计算机视觉开发介绍在图像分类问题中,图像上只有单一类别,将很多带有标记的数据集进行训练之后,可以对新的、未知的、具有单一类别的图像进行预测,类似于教小孩子看图识物,这种方法是数据驱动的方法,也是图像分类最常用的方法。1.图像分类进行目标检测的图像中并不一定只有单一类别的物体。在处理这类问题时,需要在数据上针对各个对象画出边界框和标签,训练完成后可以对新的图像进行预测,目标检测如图8-4所示,方框可以圈出猫的位置。2.目标检测8.1计算机视觉开发介绍语义分割与目标检测不同,语义分割需要对每个像素进行语义上的理解,由于需要对每个像素属于图像上的哪个部分做出分类,所以每个像素都拥有标签,语义分割如图8-5所示。3.语义分割计算机视觉比较突出的应用领域如下。医学图像检验:从图像数据中提取信息以诊断患者患病类别;工业领域:在该领域,计算机视觉有时被称为机器视觉,如产品质量把控,机器视觉也大量运用于农业上,以去除不良幼苗或除虫;安防、娱乐领域:传统机器学习的方法运用于人脸识别时并不能很好地满足精度要求,并且同一个人在不同光照、姿态下的特征会有差异,在深度学习运用于计算机视觉后,算法能够提升识别准确率;光学字符识别:将计算机无法理解的图像形式转换成计算机可以理解的文本格式;自动驾驶:可以在马路上无人驾驶汽车,还可以进行自动泊车等操作。手写数字识别计算机视觉开发介绍人脸识别8.2.1项目介绍本项目采用卷积神经网络,为了保证整个项目的完整性,在训练过程中不仅要显示损失或者准确率,而且在训练完成后需要保存得到的模型,然后调用摄像头来实时预测新的图像,新图像可以是数据集中的,也可以是自己手写的。通过实现整个过程,将OpenCV、神经网络以及TensorFlow结合起来学习,项目流程图如图8-6所示。图8-6项目流程图8.2.1项目介绍本节训练过程依然使用该网络,并且在最后训练出模型,模型文件以变量的形式存储参数,该变量需要在代码中初始化。在训练过程中,将更新的参数存储到变量中,使用tf.train.Saver()对象将所有的变量添加到Graph中。保存模型的函数为:save_path=saver.save(sess,model_path)如果每隔一定的迭代步数就保存一次模型,就把迭代步数作为参数传进去:save_path=saver.save(sess,model_path,global_step=step,write_meta_graph=False)在模型保存之后,调用该模型可以完成新数据的分类预测,模型在保存后会生成4个文件,TensorFlow模型如图所示。8.2.2图像获取以及预处理【例8-1】在mnist_predict目录下新建文件,命名为read_pic.py,使用OpenCV读取新图像,并进行预处理,在PyCharm中编写如下代码。1.从图像文件中读取并处理importosimportcv2os.environ['TF_CPP_MIN_LOG_LEVEL']='2'#将输入的彩色图像转换为二值化图defcolor_input(endimg):img_gray=cv2.cvtColor(endimg,cv2.COLOR_BGR2GRAY)#灰度化转换ret,img_threshold=cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY_INV)returnimg_thresholddefread_pic(path):img=cv2.imread(path,cv2.IMREAD_COLOR)
#读取图像并显示cv2.imshow('img',img)cv2.waitKey(0)img_threshold=color_input(img)cv2.imshow('img_threshold',img_threshold)cv2.waitKey(0)if__name__=='__main__':read_pic("pic.png")运行以上代码,在read_pic()函数中可读取与read_pic.py同级目录下的pic.png图像文件并且显示出来。pic.png图像文件如图8-8所示,这是手写的一些数字,关掉显示框之后,调用color_input()函数,并将读取的图像传递进去。在color_input()函数中,完成RGB彩色图像向二值化图像的转换,并将转换后的二值化图像显示出来,转换后的二值化图像如图8-9所示。图8-8pic.png图像文件图8-9转换后的二值化图像8.2.2图像获取以及预处理【例8-2】在mnist_predict目录下新建文件,命名为camera.py,使用摄像头拍摄图像,处理为二值化图并显示,在PyCharm中编写以下代码。2.从摄像头获取图像importcv2defstart():cap=cv2.VideoCapture(0)#使用摄像头while(True):ret,frame=cap.read()#读取一帧的图像img_gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#灰度化ret,img_threshold=cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY_INV)cv2.imshow('img_threshold',img_threshold)key=cv2.waitKey(30)&0xffifkey==27:sys.exit(0)cap.release()#释放摄像头
cv2.destroyAllWindows()if__name__=='__main__':start()start()函数可调用摄像头,捕捉并显示视频帧。8.2.3图像识别【例8-3】在mnist_predict目录下新建文件,命名为predict_pic.py,识别图像。1.从图像文件中读取并识别importosimportcv2importnumpyasnpimporttensorflowastfos.environ['TF_CPP_MIN_LOG_LEVEL']='2'#将输入的彩色图像转换为二值化图defcolor_input(endimg):img_gray=cv2.cvtColor(endimg,cv2.COLOR_BGR2GRAY)#灰度化
ret,img_threshold=cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY_INV)returnimg_threshold#读取图像并显示defread_pic(path):img=cv2.imread(path,cv2.IMREAD_COLOR)cv2.imshow('img',img)cv2.waitKey(0)img_threshold=color_input(img)cv2.imshow('img_threshold',img_threshold)cv2.waitKey(0)returnimg_thresholdif__name__=='__main__':withtf.Session()assess:saver=tf.train.import_meta_graph('model_data/model.meta')saver.restore(sess,'model_data/model')#模型恢复graph=tf.get_default_graph()input_x=sess.graph.get_tensor_by_name("Mul:0")#获取变量y_conv2=sess.graph.get_tensor_by_name("final_result:0")#读取图像img_threshold=read_pic("nine.png")8.2.3图像识别#将图像进行缩放
im=cv2.resize(img_threshold,(28,28),interpolation=cv2.INTER_CUBIC)x_img=np.reshape(im,[-1,784])#识别
output=sess.run(y_conv2,feed_dict={input_x:x_img})result=np.argmax(output)print("识别结果为:{}".format(result))8.2.3图像识别【例8-4】在目录下新建文件,命名为predict_camera.py,完成识别。首先导入需要的类,包括OpenCV、NumPy和TensorFlow。2.从摄像头实时识别importosimportcv2importsysimporttimeimportnumpyasnpimporttensorflowastfos.environ['TF_CPP_MIN_LOG_LEVEL']='2'接下来需要封装一个函数,作用是将输入的RGB图像转换为二值化图像,并将转换后的二值化图像返回。#将输入的彩色图像转换为二值化图defcolor_input(endimg):img_gray=cv2.cvtColor(endimg,cv2.COLOR_BGR2GRAY)ret,img_threshold=cv2.threshold(img_gray,127,255, cv2.THRESH_BINARY_INV)returnimg_threshold8.2.3图像识别然后恢复模型。实例化一个saver,并使用saver.restore()函数恢复模型,将得到的变量返回。#恢复模型并实例化saverdefrestore_model():sess=tf.Session()saver=tf.train.import_meta_graph('model_data/model.meta')#使用saver.restore()函数模型恢复
saver.restore(sess,'model_data/model')#获取变量
input_x=sess.graph.get_tensor_by_name("Mul:0")y_conv2=sess.graph.get_tensor_by_name("final_result:0")returnsess,input_x,y_conv2接下来构建预测函数,将变量和二值化图像传入,将图像进行缩放,调用sess.run()函数实现预测,并将结果返回。#图像预测defmnist_predict(sess,input_x,y_conv2,img_thre):#将图像进行缩放
im=cv2.resize(img_thre,(28,28),interpolation=cv2.INTER_CUBIC)x_img=np.reshape(im,[-1,784])#识别
output=sess.run(y_conv2,feed_dict={input_x:x_img})result=np.argmax(output)returnresult最后在主函数中调用摄像头,调用模型恢复函数,使用cv2.putText()函数在显示的界面上显示识别结果、帧Q数等提示。8.2.3图像识别if__name__=='__main__':#使用默认字体
font=cv2.FONT_HERSHEY_SIMPLEX#使用摄像头
cap=cv2.VideoCapture(0)#初始化用于计算fps的变量
fps="FPS:??"start_time=time.time()counter=0#调用模型恢复函数
sess,input_x,y_conv2=restore_model()#循环显示识别结果图像
while(True):#读取一帧的图像
ret,frame=cap.read()cv2.rectangle(frame,(180,100),(460,380),(0,255,0),2)frame=cv2.putText(frame,'Please',(0,40),font,1.2,(0,255,255),2)frame=cv2.putText(frame,'Putthenumberinthebox:',(0,80),font,1.2,(0,255,255),2)endimg=frame[100:380,180:460]endimg_threshold=color_input(endimg)result=mnist_predict(sess,input_x,y_conv2,endimg_threshold)counter+=1if(time.time()-start_time)>1:print("FPS:",counter/(time.time()-start_time))counter=0start_time=time.time()cv2.putText(frame,"%d"%result,(460,380),font,3,(0,0,255),2)cv2.putText(frame,fps,(50,120),font,0.8,(0,0,255),2)cv2.imshow('NumberRecognition',frame)key=cv2.waitKey(30)&0xffifkey==27:sys.exit(0)sess.close()#释放摄像头cap.release()cv2.destroyAllWindows()8.2.4结果显示使用代码画一个方形框,可以使结果更加直观。将摄像头对准手写的数字,将数字放在框里,调用识别函数完成识别,并将帧数FPS显示在方形框左上角,将结果显示在方形框右下角,识别结果如图8-12所示。手写数字识别计算机视觉开发介绍人脸识别8.3.1项目介绍本项目使用读取图像以及调用摄像头两种方式完成图像中人脸检测、人脸关键点检测、人脸对比、人脸搜索与人脸识别。本项目基于face_recognition项目开发。face_recognition项目的人脸识别是基于C++开源库dlib中的深度学习模型实现的,用LFW(LabeledFacesintheWildHome)人脸数据集进行测试时,准确率可达到99.38%。在项目开始之前需要安装face_recognition第三方库:Python版本需要在Python3.3及以上或者Python2.7上安装;在Mac、Linux或者Windows上安装时,首先需要安装dlib,然后在交互界面输入“pip3installface_recognition”命令安装项目源码,或者直接在GitHub网站下载项目源码。8.3.2人脸的数据集介绍人脸数据集很多,本书介绍LFW(LabeledFacesintheWildHome)数据集。由美国马萨诸塞州立大学阿默斯特分校计算机视觉实验室整理完成的,主要用来研究非受限情况下的人脸识别问题。在LFW数据集中,由于多姿态、光照、表情、年龄、遮挡等因素的影响,即使是同一人的照片差别也很大。该数据集包含5746个人的13233张照片,其中1680个人拥有多张照片,每张照片的大小为250像素×250像素。下载LFW数据集,解压后的目录如图所示。LFW数据集文件夹按名字命名,人脸照片在每个名字的文件夹下,人脸照片命名方式为“名字_xx.jpg”,如Aaron_Eckhart_0001.jpg。8.3.3人脸识别流程01OPTION02OPTION03OPTION04OPTION人脸图像采集及检测人脸识别首先需要采集人脸图像,可以通过读取图像或者通过摄像头直接采集来完成。人脸图像预处理预处理可以尽量避免环境条件限制和随机干扰,提高特征提取准确率。人脸图像特征提取人脸图像特征提取也称为人脸表征,它是对人脸进行特征建模的过程,可以将图像信息数字化,根据人脸器官的形状描述以及它们之间的距离特性来获得有助于人脸分类的特征数据。匹配与识别匹配是将所提取的人脸图像的特征数据与数据库中存储的特征模板进行搜索匹配8.3.4人脸识别方案1.怎么找到人脸人脸识别的第一步是找到人脸,即人脸检测,在一张照片或一个视频帧中,首先要知道是否存在人脸以及人脸的位置。找到人脸之后需要提取整体图像特征,提取特征的方法有方向梯度直方图(HistogramofOrientedGradient,HOG)、局部二值(LocalBinaryPattern,LBP)以及Haar-like。8.3.4人脸识别方案2.简单的面部识别分类根据之前的步骤将脸部从图像中分离,如果直接将两张照片进行对比,当两者中人脸的角度、位置不同时,接下来的网络或者算法在做分类时准确率降低,所以通常需要先对脸部图像进行预处理。预处理方法是瓦希德•卡泽米(VahidKazemi)和约瑟芬•沙利文(JosephineSullivan)提出的面部特征点估计,该方法的主要思路是找到面部中普遍存在的68个特征点,包括下巴、每只眼睛的外部轮廓、每条眉毛的内部轮廓等,然后基于这些特征点的位置对图像进行仿射变换等操作,让人脸尽量居中。脸部居中之后可以进行识别,最简单的方法是将要识别的人脸与数据库被标注的人脸进行比较,看是否相似。最后一步就是人脸识别,有了前面的铺垫,这一步就很简单了。得到需要识别的人脸并将其编码之后,使用分类算法就可以完成识别,如KNN。需要注意的是,这里的KNN并不是对比两张照片的像素距离,而是对比编码后的128个参数值的距离。8.3.5人脸识别应用1.人脸检测【例8-5】在face_predict下新建face-find.py文件,读取照片并将检测后的人脸标注出来。importcv2importface_recognition#加载被比较的图像frame=face_recognition.load_image_file("Face_database/hyz/hyz.png")#使用CPU获得人脸边界框的数列face_locations=face_recognition.face_locations(frame)#使用CNN并利用GPU/CUDA加速获得人脸边界框的数列#相对更准确#face_locations=face_recognition.face_locations(frame,number_of_times_to_upsample=0,model="cnn")print("该张图像中有{}张人脸。".format(len(face_locations)))#圈出人脸边界框for(top,right,bottom,left)inface_locations:cv2.rectangle(frame,(left,top),(right,bottom),(0,255,0),2)#显示得到人脸后的图像frame=frame[:,:,::-1]cv2.imshow("image",frame)cv2.waitKey(0)8.3.5人脸识别应用2.人脸关键点检测【例8-6】在face_predict下新建face-feature.py文件,读取照片并标记特征点。#加载被比较的图像frame=face_recognition.load_image_file("Face_database/hyz/hyz.png")#查找图像中的所有面部特征face_landmarks_list=face_recognition.face_landmarks(frame,face_locations=None,model='large')#查找图像中的鼻子、左眼、右眼面部特征#face_landmarks_list=face_recognition.face_landmarks(frame,face_locations=None,model='small')print("该张图像中有{}张人脸。".format(len(face_landmarks_list)))forface_landmarksinface_landmarks_list:#打印此图像中每个面部特征的位置
#查找图像中所有面部特征的列表
facial_features=['chin','left_eyebrow','right_eyebrow','nose_bridge','nose_tip','left_eye','right_eye','top_lip','bottom_lip'
]#查找图像中鼻子、左眼、右眼面部特征的列表#facial_features=[#'nose_tip',#'left_eye',#'right_eye',#]#在图像中描绘出人脸特征forfacial_featureinfacial_features:#数据类型必须是int32pts=np.array(face_landmarks[facial_feature],32)pts=pts.reshape((-1,1,2))#图像,点集,是否闭合,颜色,线条粗细cv2.polylines(frame,[pts],False,(0,0,0),2)#显示得到人脸后的图像frame=frame[:,:,::-1]cv2.imshow("image",frame)cv2.waitKey(0)8.3.5人脸识别应用3.人脸对比【例8-7】在face_predict下新建face-compare.py,完成人脸对比。#人脸比较:将两张人脸图像进行对比#将两者之间的相似值进行打印#阈值为0.6,阈值越小,条件越苛刻importcv2importface_recognition#加载被比较的图像source_image=face_recognition.load_image_file("Face_database/hyz/hyz.png")#加载测试图像compare_image=face_recognition.load_image_file("Face_database/hyz/hyz_near.png")#获取人脸位置并做单人脸容错处理source_locations=face_recognition.face_locations(source_image)iflen(source_locations)!=1:print("注意:图像一只能有一张人脸哦!")exit(0)#获取人脸位置并做单人脸容错处理compare_locations=face_recognition.face_locations(compare_image)iflen(compare_locations)!=1:print("注意:图像二只能有一张人脸哦!")exit(0)#绘制图像一的人脸for(top,right,bottom,left)insource_locations:print(top,right,bottom,left)cv2.rectangle(source_image,(left,top),(right,bottom),(0,255,0),2)#绘制图像二的人脸for(top,right,bottom,left)incompare_locations:print(top,right,bottom,left)cv2.rectangle(compare_image,(left,top),(right,bottom),(0,255,0),2)#获取图像一的面部编码source_face_encoding=face_recognition.face_encodings(source_image)[0]source_encodings=[source_face_encoding,]#获取图像二的面部编码compare_face_encoding=
face_recognition.face_encodings(compare_image)[0]#显示两张得到人脸后的图像source_image=source_image[:,:,::-1]cv2.imshow("image",source_image)cv2.waitKey(0)compare_image=compare_image[:,:,::-1]8.3.5人脸识别应用cv2.imshow("image",compare_image)cv2.waitKey(0)#查看面部一与面部二的比较结果,阈值为0.6,阈值越小越苛刻face_distances=face_pare_faces(source_encodings,compare_face_encoding,0.6)#输出结果print("正常阈值为0.6时,测试图像是否与已知图像{}匹配!".format("是"ifface_distanceselse"不是"))4.人脸搜索【例8-8】在face_predict下新建face-seek.py,完成人脸搜索。#查找人脸:查找图像中的人脸并标记出来importosimportface_recognitionfile_name=[]known_faces=[]#加载文件中的人脸库图像image_dir="Face_database/hyz/"8.3.5人脸识别应用forparent,dirnames,filenamesinos.walk(image_dir):forfilenameinfilenames:#print(filename)#加载图像
frame=face_recognition.load_image_file(image_dir+filename)face_bounding_boxes=face_recognition.face_locations(frame)iflen(face_bounding_boxes)!=1:#如果训练图像中没有人(或人太多),请跳过图像
print("{}这张图像不适合训练:{}。".format(image_dir+filename,"因为它上面没找到人脸"iflen(face_bounding_boxes)<1else"因为它不止一张人脸"))else:#encodingframe_face_encoding=face_recognition.face_encodings(frame)[0]#加到列表里
known_faces.append(frame_face_encoding)file_name.append(filename)#加载未知图像frame=face_recognition.load_image_file("unknown/unknown1.png")#encodingframe_face_encoding=face_recognition.face_encodings(frame)[0]#比较获得结果results=face_pare_faces(known_faces,frame_face_encoding)print(results)8.3.5人脸识别应用5.人脸识别【例8-9】在face_predict下新建face-knn-train.py,使用KNN实现人脸库的训练。#训练K近邻分类器importmathfromsklearnimportneighborsimportosimportos.pathimportpickleimportface_recognitionfromface_recognition.face_recognition_cliimportimage_files_in_folderdeftrain(train_dir,model_save_path=None,n_neighbors=None,knn_algo='ball_tree',verbose=False):"""
训练K近邻分类器进行人脸识别
paramtrain_dir:包含每个已知人员的子目录及人员名称的目录
parammodel_save_path:(可选)将模型保存在磁盘上的路径
paramn_neighbors:(可选)在分类中称重的邻居数。如果未指定,则自动选择
paramknn_algo:(可选)支持knn.default的底层数据结构是ball_treeparamverbose:训练时是否根据图像数量取n_neighbors的值
return:返回在给定数据上训练的KNN分类器
"""X=[]y=[]8.3.5人脸识别应用#循环遍历训练集中的每个人forclass_dirinos.listdir(train_dir):#如果train_dir/class_dir不是一个目录,就继续ifnotos.path.isdir(os.path.join(train_dir,class_dir)):continue#循环浏览当前人员的每个训练图像forimg_pathinimage_files_in_folder(os.path.join(train_dir,class_dir)):image=face_recognition.load_image_file(img_path)face_bounding_boxes=face_recognition.face_locations(image)iflen(face_bounding_boxes)!=1:#如果训练图像中没有人(或人太多),请跳过图像
ifverbose:print("{}这张图像不适合训练:{}。".format(img_path,"因为它上面没找到人脸"iflen(face_bounding_boxes)<1else"因为它不止一张人脸"))else:#将当前图像的面部编码添加到训练集
X.append(face_recognition.face_encodings(image,known_face_locations=face_bounding_boxes)[0])y.append(class_dir)#确定KNN分类器中用于加权的近邻
ifn_neighborsisNone:n_neighbors=int(round(math.sqrt(len(X))))#面部编码长度开平方后四舍五入取整数
ifverbose:print("自动选择n_neighbors:",n_neighbors)#创建并训练KNN分类器
knn_clf=neighbors.KNeighborsClassifier(n_neighbors=n_neighbors,algorithm=knn_algo,weights='distance')knn_clf.fit(X,y)8.3.5人脸识别应用#保存训练后的KNN分类器
ifmodel_save_pathisnotNone:withopen(model_save_path,'wb')asf:pickle.dump(knn_clf,f)returnknn_clfif__name__=="__main__":#训练的KNN分类,并将其保存到磁盘
print("训练KNN分类器...")classifier=train("Face_database",model_save_path="trained_knn_model.clf",n_neighbors=1)print("训练完成!")5.人脸识别在face_predict下新建face-knn-predict.py文件,实现人脸识别。#摄像头测试K近邻分类器importosimportcv2importos.pathimportpickleimportface_recognitionALLOWED_EXTENSIONS={'png','jpg','jpeg'}defpredict(X_img,knn_clf=None,model_path=None,distance_threshold=0.6):8.3.5人脸识别应用"""
使用训练后的KNN分类器识别给定图像中的面部
paramX_img:要识别的图像
paramknn_clf:(可选)一个KNN分类器对象。如果未指定,则必须指定model_save_pathparammodel_path:(可选)pickleKNN分类器的路径。如果未指定,则model_save_path必须为knn_clfparamdistance_threshold:(可选)面部分类的距离阈值。它越大,机会就越大,就会将一个不知名的人误分类为已知人员图像中已识别面部的名称和面部位置列表:[(名称,边界框),...]。对于未被识别人员的面孔,将返回“未知”的名称
"""ifknn_clfisNoneandmodel_pathisNone:raiseException("必须提供KNN分类器knn_clf或model_path")
#加载训练后的KNN模型(如果传入了一个)
ifknn_clfisNone:withopen(model_path,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论