百度云人脸识别接口+python+opencv做的表情包合成器

第一次使用python,所以语法有些凌乱.

菜鸟随便做的一个小东西.

 

开发环境:win10+anaconda3.0+python3.6+opencv2+pyqt5

一、anaconda安装

下载链接:

https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/

二、安装opencv2

安装好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个面部特征点。

四、使用opencv处理图片

1.首先前面已经通过百度云接口得到了旋转角度,旋转图片:

百度云人脸识别接口+python+opencv做的表情包合成器_第1张图片

源码:

    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))

2.根据获得的72个面部特征点生成一个mask:

(下图为百度云接口文档里的例图)

百度云人脸识别接口+python+opencv做的表情包合成器_第2张图片

(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])

可以抠出一个这样的脸:

百度云人脸识别接口+python+opencv做的表情包合成器_第3张图片

 

3.与表情包图片合成

为了使效果更好(其实为了操作更简单),熊猫头是自己画的,画了6张。

百度云人脸识别接口+python+opencv做的表情包合成器_第4张图片

采用了很笨的像素点相加的办法“贴”了上去,代码就不贴了。

4.最后结果

百度云人脸识别接口+python+opencv做的表情包合成器_第5张图片

 

五、使用pyqt5做GUI界面:

网上的教程真的很少,所以做出来的界面丑得一批……

就搞几个button然后加个背景图填充一下就行了……

百度云人脸识别接口+python+opencv做的表情包合成器_第6张图片

六、完整代码

https://download.csdn.net/download/coconut_j/10886567

你可能感兴趣的:(百度云人脸识别接口+python+opencv做的表情包合成器)