年会签到,拍自己的大头照,有的人可能会拍成横向的,需要旋转,用人脸检测并修正它(图片)。
训练数据集下最基本的人脸haarcascade_frontalface_default.xml
1) 斜脸检测失败
用了一张逃避可耻但有用剧照,不知是gakki脸斜还是不清晰的缘故,face_cascade.detectMultiScale
无结果。
网上找了一张人脸图发现可以有结果[[436 142 604 604]]
2) 旋转图片,被裁剪
测试图片旋转90°,180°,270°时,发现有个问题。下面为旋转180°,90°的效果:90°(以及270°)的图片大小没变,导致横向过长,纵向太窄,图片被裁减。
粗暴的尝试,直接用:
转换宽高后,输出90°为:
出现了奇怪的边框。
再来看一个45°的输出,也同样被裁剪
直到我找到了 Rotate images (correctly) with OpenCV and Python 这篇文章,写的太好了,用的动图也恰到好处。
作者检测原型药片旋转没关系,用椭圆的药片就有被裁剪的问题,我上面的那些就是被裁剪了。
使用作者给的函数实验:
-45°旋转
-90°旋转
完成。
4) 自动旋转图片
作者旋转的很好看,所以也模仿了一把,将自己展示图片的函数改为:「 获取图片宽高,然后动态改变宽高显示图片,ms参数为停留的毫秒数(宽高除以3是因为图片太大了,展示不好看)」
用自己之前不正确的旋转函数rotate_img_old
测试,有裁剪
用正确的测试:裴斐科特
3) 再试gakki图
range(0,360,45)
以45°为步长检测,发现-315°(即45°)有结果:
检测到两处人脸:修改配置 每次缩减比例:scaleFactor=1.2
,检测多次: minNeighbors=10
之后检测,只有一处。
最后,想截取有效的最大头像,
90°旋转裁剪
在这次真实的年会场合实际使用的时候,不能转45°去裁剪显示,斜着头拍照的可不想转成正经的证件照,
所以只用转90°然后裁剪其中最大正方形,取高和宽中小的一个。较简单,蓝色为实际裁剪区域。
斜的图则不可这样,会裁剪黑色的区域,(避免脸在图中过小,取了**检测到的脸宽*2.5长度**)
代码段
斜矩形裁剪探索
那么gakki那张斜的如何裁剪呢,斜矩形之外有黑色背景。举例:应该取到绿色矩形的扩大版,但又没有取到黑色背景。比如这样的蓝色区域
转换为数学方法为:todo, 画在本子上的,最后再补
编写数学函数:
来测试一波,最后的圆形标注只是为了辅助验证。
其实是有问题的,看效果,最小的蓝色圆形标注位置不对,超出原图片了,而且观察其他三个圆也不在图片边上。
这块处理不同角度下取的矩形ABCD边不同,数学角度看是没有错的,但是Opencv坐标圆心在左上角,所以得将数学图形画为:todo
上面赋值代码只需改为
蓝色圈已经是我们要求的矩形头像外接圆了,其他三个圆输出也是贴紧各自的边框,完美。
在蓝圈中画黑色正方形:
是想要的效果,最后裁剪即可。
多角度修复
测试初始角度为横向或者侧向时,需修复角度:
测试三张不同角度照片,和一张不需旋转的图:
结果为:
过程: