当前位置: 首页 > 后端技术 > Python

【Python自动戴圣诞帽】02戴圣诞帽抗疫彩蛋

时间:2023-03-26 11:43:09 Python

今年因为疫情,太久没更新文章。作为一个湖北人,我知道在不给大家添麻烦的同时,我要提升自己。奈何没有把电脑带回家,家里的电脑也是老式机器,折腾了几天终于可以用了。尽快带来【Python自动戴圣诞帽】系列第二篇。另外,文末还有防疫彩蛋,别忘了翻过来看看。注:本文部分图片来自百度百科。如有侵权,请联系删除。OpenCV人脸关键点检测前面说到家用电脑的原因是无法安装face_recognition库,所以暂时用OpenCV中的LBF算法代替。方法其实是一样的。他们都检测面部的关键点,然后定位圣诞老人帽子的位置。上一篇文章详细讲解了face_recognition方法获取人脸关键点,这里不再赘述,看代码和注释就能明白。代码中的haarcascade_frontalface_alt2.xml和lbfmodel.yaml可以自行搜索,也可以在公众号后台回复OpenCVFace获取下载地址。#loadimage:image=cv2.imread(image_path,0)#findfaces:cascade=cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')faces=cascade.detectMultiScale(image,1.3,5)#创建地标检测器并加载lbf模型:facemark=cv2.face.createFacemarkLBF()facemark.loadModel('lbfmodel.yaml')#ok表示是否检测到关键点,landmarks表示所有关键坐标都ok,landmarks=facemark.fit(image,faces)不同于face_recognition遗憾的是,这种方式生成的关键点不是按器官分组的字典,而是列表文件。下面是列表中每个点所属器官的关系表:landmarks---[0,16]----Chinlandmarks---[17,21]---Lefteyebrowlandmarks---[22,26]---右眉标记---[27,30]---鼻梁标记---[30,35]---下鼻标---[36,41]---左眼标记---[42,47]---RightEyelandmarks---[48,59]---Outerliplandmarks---[60,67]---内唇使用OpenCV显示关键点:points_face=copy.deepcopy(image)foreachinlandmarks[0][0]:points_face=cv2.circle(points_face,tuple(each),3,(0,0,255),-1)#显示结果图像cv2.imshow('points_face',points_face)cv2.waitKey(0)效果如下:与face_recognition方法相比,基本没有区别:戴圣诞帽前,准备一顶合适的圣诞帽。首先,你需要找到一张合适的圣诞帽图片,图片必须是.png格式,带有透明信息。我找到的圣诞帽是这样的,还蛮漂亮的:按照常理,头部部分只有下图中蓝框所在的地方,所以我们需要提前确定好这部分的尺寸。用windows自带的图纸简单测量后,帽子帽檐的宽度为175px,帽子帽檐距图片底部的距离为25px。确定圣诞帽的位置有了圣诞帽,知道了脸上关键点的位置,如何确定圣诞帽应该放哪呢?这时候就需要用到小学美术学过的“三庭五眼”知识了:从图中可以看出,鼻子下缘到下巴尖的距离等于眉毛中心到发际线的距离,脸的宽度与发际线的宽度相同。两颊彼此等距。平时戴帽子的时候,帽檐一般会在发际线处,圣诞帽的位置可以据此推断出来(不管帽子的各种花式戴法)。仔细观察上面脸部关键点的图片示例,你会发现鼻梁上方的关键点距离眉心的位置很近。根据这些信息,可以确定圣诞帽在Y轴方向的位置。在检测人脸的关键点时,会得到两边脸颊的具体坐标,根据脸颊的第一个点和最后一个点的坐标,可以计算出人脸的实际宽度。根据比例,可以计算出圣诞帽在X轴方向的位置。实施细节如下。代码实现首先需要对圣诞帽进行预处理:#圣诞帽相关参数hat_img=Image.open("./hat.png")hat_brim_length=175.0hat_height_buffer=25.0hat_img=hat_img.convert('RGBA')最后一行of代码是将图片转换成RGB和透明形式,以便后面可以直接作为蒙板使用,这也是为什么需要.png格式图片的原因。人脸关键点的获取方法前面已经介绍过,不再赘述。根据前面的分析,只需要目标人脸的脸颊关键点和鼻梁关键点就可以达到目的,所以取出这些数据:chin=landmarks[0][0][:17]nose_bridge=landmarks[0][0][27:31]根据脸颊关键点,眉心到发际线的距离计算实际脸宽:defget_distance(point1,point2):returnint(math.sqrt((point1[0]-point2[0])**2+(point1[1]-point2[1])**2))face_width=get_distance(chin[0],chin[-1])hair_brim=get_distance(nose_bridge[-1],chin[int(len(chin)/2)])这里实际的脸宽是通过计算两个脸颊的端点之间的距离来确定的。简单的说,两点的横轴左边直接相减也可以得到近似结果。根据脸宽调整圣诞帽的大小:resize_ratio=face_width/hat_brim_lengthhat_width=int(hat_img.width*resize_ratio)hat_height=int(hat_img.height*resize_ratio)hat_buffer=int(hat_height_buffer*resize_ratio)圣诞帽应该在发际线的位置,所以整个圣诞帽图片的底部坐标应该是鼻梁顶部的垂直坐标减去“依婷”的位置:hat_bottom=int(nose_bridge[0][1])-hair_brim同理,下面是圣诞帽图片的上下左右坐标:hat_top=hat_bottom-hat_heightthat_left=int(chin[0][0])hat_right=hat_left+hat_width下一步是将缩放后的圣诞帽通过之前的mask粘贴到原图上并显示出来:mg)human_img.show()效果如下:注:该方法没有检测到女主图片中的人脸,所以结果不显示。观察下来,整体效果还不错,就是被范闲盯着看,感觉很不舒服。细节有点粗糙,对面部状态有一定要求。脸最好在正面位置。有兴趣的同学可以针对脸稍微倾斜的情况做一些优化。彩蛋这次疫情对大家的生活影响很大,以后的生活一定要注意健康饮食。希望疫情早日结束,武汉加油,湖北加油,中国加油!大家出门一定要戴口罩,保护自己和他人。特意给大家准备了一个面具:先帮范闲戴上:最后祝大家新的一年少病少灾,心想事成。结束语本系列到此结束。如果你想了解更多通讯方面的知识,可以在公众号主页联系我。这个系列的代码在这里:https://github.com/TitusWongCN/WeChatSubscriptionArticles/tree/master/WearChristmasHat大家有什么想知道的,或者想做点什么的可以在文末留言文章,说不定你以后会做~不管你在后记写什么,都希望能和更多的人交流。如果您有任何问题或需求,欢迎随时交流。我所有的项目源码都会放在下面的github仓库,有需要的可以参考,有问题请指正,谢谢!https://github.com/TitusWongCN/【Python自动戴圣诞帽】往期推荐:第一期:【Python自动戴圣诞帽】01熟悉face_recognition库下面是我的公众号,有兴趣的可以,您可以扫描它: