第一次使用python,所以语法有些凌乱.
菜鸟随便做的一个小东西.
开发环境:win10+anaconda3.0+python3.6+opencv2+pyqt5
下载链接:
https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/
安装好anaconda后,找到并打开 anaconda prompt
输入 conda install -c https://conda.binstar.org/menpo opencv
官网链接:
https://cloud.baidu.com/product/face
注册好百度云帐号,下载对应开发语言的api文件就行了.
我用的是python,所以下载了对应的api,按照官网教程配置好了接口后,在代码中这样写就能调用了:
其中的APP_ID和API_KEY和SECRET_KET都是在百度云上获得的,具体的按照百度云教程就可以了。
from aip import AipFace
# 我的百度云接口帐号密码
APP_ID = '你的APP_ID'
API_KEY = '你的API_KEY'
SECRET_KEY = '你的SECRET_KEY'
client = AipFace(APP_ID,API_KEY,SECRET_KEY)
imagepath = r'./1.jpg'
# 因为本地图片要用base64编码
f = open(imagepath, 'rb') # 二进制方式打开图文件
imageB64 = base64.encodebytes(f.read()) # 读取文件内容,转换为base64编码
image = str(imageB64, 'utf-8')
#image=base64.encodebytes(f.read())
f.close()
#result是字典类型
result = client.detect(image,'BASE64', None)
得到的result里有很多的东西,也可以按照教程里面定义options来选择想要得到的参数:
# 定义参数变量
options = {
'max_face_num': 1,
'face_fields': "age,beauty,expression,faceshape",
}
# 调用人脸属性识别接口
result = aipFace.detect(get_file_content('face.jpg'), options)
参数有很多,我只用到了旋转角度和72个面部特征点。
源码:
rows,cols = image_st.shape[:2]
M = cv2.getRotationMatrix2D((cols/2,rows/2),int(rotation),1)
#输出的图片,矩阵点,像素数量
new_image = cv2.warpAffine(image_st ,M,(cols,rows))
(下图为百度云接口文档里的例图)
(1)根据特征点编号绘制出覆盖五官的三角形区域。(完全人肉覆盖……)
# 用三角形网格覆盖图片,抠出眉毛、眼、鼻、嘴
TriangleList = [
Triangle(13,14,20),Triangle(14,15,20), Triangle(15,19,20),Triangle(15,16,19),Triangle(16,18,19),Triangle(16,17,18), #eye1
Triangle(29,14,13),Triangle(29,28,14),Triangle(28,15,14),Triangle(28,27,15),Triangle(27,16,15),
Triangle(27,26,16),Triangle(29,28,14),Triangle(26,17,16),Triangle(26,47,17),
Triangle(17,47,48),Triangle(17,48,18),
Triangle(30,31,37),Triangle(31,32,37),Triangle(32,36,37),Triangle(32,33,36),Triangle(33,35,36),Triangle(33,34,35), #eye2
Triangle(44,34,33),Triangle(45,44,33),Triangle(45,33,32),Triangle(46,45,32),Triangle(46,32,31),
Triangle(39,46,31),Triangle(39,31,30),Triangle(56,30,55),
Triangle(26,56,47),Triangle(26,39,56),Triangle(25,39,26),Triangle(40,39,26),
Triangle(50,51,49),Triangle(48,49,51),Triangle(48,49,52), Triangle(49,51,52),Triangle(52,53,54),
Triangle(48,52,54),Triangle(48,54,55), Triangle(47,48,55),Triangle(47,55,56), # nose
Triangle(58,59,65),Triangle(59,60,65),Triangle(60,64,65),Triangle(60,61,64),Triangle(61,63,64),Triangle(61,62,63),# mouth
Triangle(22,23,29),Triangle(23,24,29),Triangle(24,28,29),Triangle(24,25,28),Triangle(25,27,28),Triangle(25,26,28),# eye-brow1
Triangle(39,40,46),Triangle(40,41,46),Triangle(41,45,46),Triangle(41,42,45),Triangle(42,45,44),Triangle(42,43,44) # eye-brow2
]
(2)每个像素都检测是否在三角形区域中,在里面的值为1(白色),在外面的值为2(黑色)。
# 不在给定三角形内部的像素统统变成白色底色
for triIndex in range(len(TriangleList)):
tri = TriangleList[triIndex]
for y in range(int(min(tri.v1.y, tri.v2.y, tri.v3.y)), int(max(tri.v1.y, tri.v2.y, tri.v3.y)+1)):
#for y in range(imageHeight):
for x in range(int(min(tri.v1.x, tri.v2.x, tri.v3.x)), int(max(tri.v1.x, tri.v2.x, tri.v3.x)+1)):
# for x in range(imageWidth):
# 对于三角形附近的像素,都看看在不在三角形内部。不在就clear as white
if is_in_triangle(Point(x, y), TriangleList[triIndex]):
grayMask[int(y), int(x)] = 255
(3)为防止边缘过于生硬,对mask的值进行处理。
# 对mask执行膨胀操作
inflatedGrayMask = clippedGrayMask
halfKernelWidth = int(9)
for i in range(0, clippedHeight):
for j in range(0, clippedWidth):
# 对于非0的mask位置,按inflateKernel按个印章下去
newVal = 0
for m in range(-min(i, halfKernelWidth), min(clippedHeight-i, halfKernelWidth), 3):
for n in range(-min(j, halfKernelWidth), min(clippedWidth-j, halfKernelWidth), 3):
newVal += int(clippedGrayMask[i+m, j+n]) # int(clippedGrayMask[i+m, j+n] + inflateKernel[m+2][n+2])
newVal /= (halfKernelWidth * halfKernelWidth)
newVal = newVal * 9 / 4
inflatedGrayMask[i, j] = newVal
(4)生成一个覆盖五官的mask。
(5)调节色阶
# 手动调整色阶(线性映射亮度)
for i in range(clippedHeight):
for j in range(clippedWidth):
lowerBound = 100
upperBound = 180
ratio = float(clippedGrayImage[i, j] - lowerBound)/float(upperBound - lowerBound)
ratio = 1.0 if ratio > 1.0 else (ratio if ratio >= 0.0 else 0.0)
if inflatedGrayMask[i, j] == 0:
clippedGrayImage[i, j] = 255
else:
clippedGrayImage[i, j] = ratio * inflatedGrayMask[i, j] + (255 - inflatedGrayMask[i, j])
可以抠出一个这样的脸:
为了使效果更好(其实为了操作更简单),熊猫头是自己画的,画了6张。
采用了很笨的像素点相加的办法“贴”了上去,代码就不贴了。
五、使用pyqt5做GUI界面:
网上的教程真的很少,所以做出来的界面丑得一批……
就搞几个button然后加个背景图填充一下就行了……
https://download.csdn.net/download/coconut_j/10886567