由于本地有一大批数据需要处理,虽然百度开放了在线人脸识别接口,但实际测试,10个QPS+50M上行带宽,仅仅三十多万张图就花了40小时左右, 后面还有大量的视频,抽帧检测更是难搞,因此申请离线识别SDK走起。。。。

狗血的是,百度的人脸识别SDK分为两种,离线采集(仅支持移动端)和离线识别,还有单设备90天和5台设备的限制,(吐槽归吐槽,后面还是得掏钱买的,还TM一百个授权码起购。。。)

到下载页面一看,傻眼了,没有python版本的,只有Java和C++.

我的java就是入了门,直接搞kotlin+Android(当然也是非常烂); C++就更不用说了,就会写个hello world
于是我萌生了一个大胆的想法——python调用Java!!!

正文

一、环境配置

  1. python3.7 依赖库: pyjnius
  2. jdk18 亲测此版本可用

不要问我为什么用这么新的jdk,因为我找不到当时的安装路径了,懒得找了,直接现场下。
python 仅仅需要 pip install pyjnius 即可食用。

二、jnius使用

理论上,应该下载C++版本的,直接编译成dll与python供python调用是最完美的方案,无奈我看不懂。
因此调用流程就是:python 调用 java , java在调用dll,然后再通过java传递给python。
jnius用法很简单,但有点小坑,因此我直接简单封装了个jvm 包,方便以后使用。

如果要修改jvm的封装,请注意: 导入顺序千万不能错,先配置环境变量,再调用jnius_config, 最后再导入autoclass,因为autoclass导入后,虚拟机已经启动了,再配置jnius_config就不生效了(当然也有解决方案,但不做赘述,能跑就行)

# jvm.__init__.py

import os
import jnius_config
env = []
jar2classPaths = []


def run():
    os.environ['path'] = ';'.join(env)
    jnius_config.add_classpath(*jar2classPaths)
# jvm.com.py
# 可以在这个文件中定义一些常用的Java类的映射与类型标注,方便IDE进行代码提示。
from jnius import autoclass


class __System:

    @staticmethod
    def getProperty(key: str) -> str: ...

    @staticmethod
    def loadLibrary(name: str) -> str: ...

    @staticmethod
    def load(path: str) -> str: ...

    class out:
        def println(self, *args): ...


System: __System = autoclass("java.lang.System")
# main.py
# 运行测试
import jvm
# --- jvm初始化 ---
jvm.env.extend([
    r"C:\Program Files\Java\jdk-18\bin\server", # jvm地址
    # 各种dll路径,我将相关的dll全部复制到这个目录了,也可以直接填百度SDK的主目录
    r"E:\projects\Python\tempitem\mada_emotion\lib"])  
jvm.jar2classPaths.extend([
    r"E:\projects\kotlin\BaiduFaceSDK\bin", # java编译后的目录
    # jar包, 如果有其他依赖,继续往这儿加,本质上都是.class文件
    r"E:\projects\Python\tempitem\mada_emotion\lib\opencv-320"]) 
jvm.run()
# --- jvm初始化完成 ---

# 尝试初始化百度SDK的Face类
api = autoclass("com.jni.face.Face")()
print(api.sdkInit("xxxxx")) # 初始化成功返回0

至此,就可以勉强使用了

三、BaiduFaceSDK 封装

可是,作为有强迫症的我,没有代码提示简直没法下手敲,因此,肝了一小时,拿去用吧各位,不用谢。共三个文件,封装成了baiduFaceSDK,后面打包整理传github再更新。

# baiduFaceSDK.__init__.py
from jnius import autoclass
from result import *

class Api:
    def __new__(cls, **kwargs):
        return autoclass("com.jni.face.Face")()

    def __init__(self): ...

    def readImage(self, f: Union[bytes, bytearray]) -> Mat: ...

    def sdkInit(self, modelPath) -> int: ...

    def sdkDestroy(self): ...

    def isAuth(self) -> bool: ...

    def getDeviceId(self) -> str: ...

    def sdkVersion(self) -> str: ...

    def detect(self, addr: int, _type: int) -> detectResult: ...

    def track(self, addr: int, _type: int) -> trackResult: ...

    def clearTrackHistory(self) -> int:

    def faceAttr(self, addr: int) -> faceAttrResult: ...

    def faceEyeClose(self, addr: int) -> faceEyeCloseResult: ...

    def faceGaze(self, addr: int) -> faceGazeResult: ...

    def faceHeadPose(self, addr: int) -> faceHeadPoseResult: ...

    def faceIllumination(self, addr: int) -> List[int]: ...

    def faceBlur(self, addr: int) -> List[float]: ...

    def faceMouthClose(self, addr: int) -> List[float]: ...

    def faceMouthMask(self, addr: int) -> List[float]: ...

    def faceOcclusion(self, addr: int) -> faceOcclusionResult: ...

    def darkEnhance(self, in_addr: int, out_addr: int) -> int: ...

    def faceCrop(self, in_addr: int, out_addr: int) -> int: ...

    def faceBest(self, addr: int) -> List[float]: ...

    def faceLandmark(self, addr: int) -> faceLandmarkResult: ...

    def faceActionLive(self, addr: int, actionType: int, actionResult: List[int]) -> faceActionLiveResult: ...

    def clearActionLiveHistory(self) -> int: ...

    def faceFeature(self, addr: int, _type: int) -> faceFeatureResult: ...

    def livenessFeature(self, addr: int, _type: int) -> livenessFeatureResult: ...

    def match(self, addr1: int, addr2: int, _type: int) -> int: ...

    def compareFeature(self, f1: Feature, f2: Feature, _type: int) -> float: ...

    def rgbLiveness(self, addr: int) -> rgbLivenessResult: ...

    def userAddByMat(self, addr: int, userId: str, groupId: str, userInfo: str) -> str: ...

    def userAdd(self, fea: Feature, userId: str, groupId: str, userInfo: str) -> str: ...

    def userUpdate(self, addr: int, userId: str, groupId: str, userInfo: str) -> str: ...

    def userDelete(self, userId: str, groupId: str) -> str: ...

    def groupAdd(self, groupId: str) -> str: ...

    def groupDelete(self, groupId: str) -> str: ...

    def getUserInfo(self, userId: str, groupId: str) -> str: ...

    def getUserImage(self, out_addr: int, userId: str, groupId: str) -> int: ...

    def getUserList(self, groupId: str, start: int, length: int) -> str: ...

    def getGroupList(self, start: int, length: int) -> str: ...

    def dbFaceCount(self, groupId: str) -> int: ...

    def identifyByMat(self, addr: int, groupIdList: str, userId: str, _type: int)-> str: ...

    def identify(self, fea: Feature, groupIdList: str, userId: str, _type: int) -> str: ...

    def identifyWithAllByMat(self, addr: int, _type: int) -> str: ...

    def identifyWithAll(self, fea: Feature, _type: int) -> str: ...

    def loadDbFace(self) -> bool: ...



# baiduFaceSDK.result.py
# 定义接口的返回值,并做类型标注,即使是列表遍历之后Pycharm也会提示关键字,舒服!!!
from structs import *


class Mat:
    def release(self): ...

    def getNativeObjAddr(self) -> float: ...


class detectResult(list):
    def __getitem__(self, i) -> FaceBox: ...
    def __iter__(self) -> List[FaceBox]: ...


class trackResult(list):
    def __getitem__(self, i) -> TrackFaceInfo: ...
    def __iter__(self) -> List[TrackFaceInfo]: ...


class faceAttrResult(list):
    def __getitem__(self, i) -> Attribute: ...
    def __iter__(self) -> List[Attribute]: ...


class faceEyeCloseResult(list):
    def __getitem__(self, i) -> EyeClose: ...
    def __iter__(self) -> List[EyeClose]: ...


class faceGazeResult(list):
    def __getitem__(self, item) -> GazeInfo: ...
    def __iter__(self) -> List[GazeInfo]: ...


class faceHeadPoseResult(list):
    def __getitem__(self, item) -> HeadPose: ...
    def __iter__(self) -> List[HeadPose]: ...


class faceOcclusionResult(list):
    def __getitem__(self, item) -> Occlusion: ...
    def __iter__(self) -> List[Occlusion]: ...


class faceLandmarkResult(list):
    def __getitem__(self, item) -> Landmarks: ...
    def __iter__(self) -> List[Landmarks]: ...


class faceActionLiveResult(list):
    def __getitem__(self, item) -> FaceBox: ...
    def __iter__(self) -> List[FaceBox]: ...


class faceFeatureResult(list):
    def __getitem__(self, item) -> FeatureInfo: ...
    def __iter__(self) -> List[FeatureInfo]: ...


class livenessFeatureResult(list):
    def __getitem__(self, item) -> LiveFeatureInfo: ...
    def __iter__(self) -> List[LiveFeatureInfo]: ...


class rgbLivenessResult(list):
    def __getitem__(self, item) -> LivenessInfo: ...
    def __iter__(self) -> List[LivenessInfo]: ...



# baiduFaceSDK.structs.py
# 定义的结构体

from typing import List


class Attribute:
    age: int
    race: int  # 0:黄种人 1:白种人 2:黑种人 3:印第安人
    emotion: int  # 0:皱眉 1:笑 2:平静
    glasses: int  # 0:无眼镜 1:有眼镜 2:墨镜
    gender: int  # 0:女性 1:男性


class CropFaceConf:
    isFlat: int  # 是否镜像
    cropSize: int  # 抠图大小
    enlargeRatio: int  # 抠图倍数


class EyeClose:  # 双眼闭合置信度
    leftEyeCloseConf: float
    rightEyeCloseConf: float


class FaceBox:
    index: int
    centerx: float
    centery: float
    width: float
    height: float
    angle: float
    score: float


class Feature:
    size: int
    data: bytes


class FeatureInfo:
    feature: Feature
    face: FaceBox


class GazeInfo:  # 注意力信息
    leftEyeDirection: int  # 左眼凝视方向 0:向上看 1:向下看 2:向右看 3:向左看 4:向前看 5:闭眼
    leftEyeConf: float  # 置信度
    rightEyeDirection: int  # 右眼凝视方向 0:向上看 1:向下看 2:向右看 3:向左看 4:向前看 5:闭眼
    rightEyeConf: float  # 置信度


class HeadPose:
    yaw: float  # 水平转动
    roll: float  # 左右倾斜
    pitch: float  # 抬头低头


class Landmarks:
    index: int  # 关键点索引
    size: int
    data: List[float]  # 关键点数据,144个点,72个x,y坐标
    score: float  # 关键点分值


class LiveFeatureInfo:
    feature: Feature  # 特征值
    box: FaceBox  # 人脸框
    score: float  # 活体分值


class TrackFaceInfo:
    faceId: int
    box: FaceBox
    land: Landmarks


class LivenessInfo:
    trackinfo: TrackFaceInfo
    livescore: float


class Occlusion:
    leftEye: float
    rightEye: float
    nose: float
    mouth: float
    leftCheek: float
    rightCheek: float
    chin: float


class RgbDepthInfo:
    trackinfo: TrackFaceInfo
    rgbscore: float
    depthscore: float
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐