windows下百度离线人脸识别本地部署与使用(nodejs做客户端,c++做服务端,socket做通信)

时间:2020-11-27 16:19:33

1.离线人脸识别本地部署

  详情请阅读百度人脸识别官网

2.nodejs做socket通信的客户端

  为什么不直接通过调用c++编译的exe获得人脸识别结果?

  原因:exe运行时会加载很多模型而消耗很多时间,导致不能实时得到人脸识别结果;而用socket通信则只需执行一次加载模型的过程,后面的请求只需直接进行人脸识别检测而只用100多毫秒得到结果。

  1)nodejs将canvas得到的视频帧的base64字符串转换成图片

    

var image = query.image;
var base64Data = image.replace(/^data:image\/\w+;base64,/, "");
var dataBuffer = new Buffer(base64Data, 'base64');
fs.writeFile("image.png", dataBuffer, function(err) {
if(err){
console.log("保存成功!");
}else{
console.log("保存成功!");
}
});

  2)创建socket(同步模式,即得到人脸识别结果再执行下面的代码)

  

      var result = '';

         var net = require('net');
var port = 8588;
var host = '127.0.0.1';
      //等待检测结果出来
result = await new Promise(
function (resolve, reject) {
          //创建socket客户端
var client= new net.Socket();
client.setEncoding('binary');
//连接到服务端
client.connect(port,host,function(){
             //向服务端发送数据
client.write('D:\\wamp\\wamp64\\www\\eggs\\image.png'); 
});
client.on('data',function(data){
console.log('from server:'+ data); 
console.log(data);
result = data;
//得到服务端返回来的数据
resolve({"cod"e: 1, "data": result, "msg": 'success' })
});
client.on('error',function(error){
//错误出现之后关闭连接 
console.log('error:'+error);
reject({"code": 0, "data": "", "msg": error });
// client.destory();
});
client.on('close',function(){
//正常关闭连接
resolve({"code": 1, "data": "", "msg": 'socket closed' });
console.log('Connection closed');
}); }
)     return result; //result = {"code":1 , "data":xxx, "msg": xxx};

3.c++ 做socket服务端

  

   int main(){  
     //std::cout << "in main" << std::endl;
//api实例指针
BaiduFaceApi *api = new BaiduFaceApi();
//初始化sdk
// 若采用证件照模式,请把id_card设为true,否则为false,证件照模式和非证件照模式提取的人脸特征值不同,
// 不能混用
bool id_card = false;
bool is_authed = true;
int suc = api->sdk_init(id_card);
if (suc != )
{
std::cout << " err{authed is failed} "<< std::endl;
getchar();
is_authed = false;
//return 0;
} std::time_t time_begin = get_timestamp();
/*std::cout << "start tracking" << std::endl;
for (int i = 0; i < argc; i++)
{
std::cout << "argv is" << i << argv[i] << "end print " << std::endl;
}*/ WSACleanup(); //初始化WSA
WORD sockVersion = MAKEWORD(, );
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != )
{
return ;
} //创建套接字
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
printf("socket error !");
return ;
} //绑定IP和端口
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons();
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (::bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("bind error !");
} //开始监听
if (listen(slisten, ) == SOCKET_ERROR)
{
printf("listen error !");
return ;
} //循环接收数据
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
char revData[* ];
     //不断监听接口获取客户端参数
while (true)
{
printf("等待连接...\n");
sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
if (sClient == INVALID_SOCKET)
{
printf("accept error !");
continue;
}
printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr)); //接收数据
long long int ret = recv(sClient, revData, *, );
const char * sendData = "";
//如果没接收到数据
if (ret > )
{
//如果百度人脸识别验证证书不通过
if (!is_authed)
{
sendData = "error:authed is failed";
}
else
{
revData[ret] = 0x00;
printf(revData);
            //检测图片
string res = test_face_attr(api, revData);
if (res == "")
{
sendData = "error:no people";
}
else
{
bool is_utf8 = is_str_utf8(res.c_str());
std::cout << "\nis_utf8-" << is_utf8 << "\n" << std::endl;
std::cout << res << endl; printf(res.c_str());
//发送数据
char arr[]; int len = res.copy(arr, );
arr[len] = '\0';
sendData = arr;
}
} }
else
{
//发送数据
sendData = "{error:'no data recv'}\n";
} send(sClient, sendData, strlen(sendData), );
std::time_t time_end = get_timestamp();
//std::cout << "tracking_result is:" << res << std::endl;
std::cout << "time cost is :" << time_end - time_begin << "ms" << std::endl;
closesocket(sClient);
}
   }