人脸识别——使用阿里云人脸检测API 获取人脸关键点

概述:

      最近做了人脸皮肤疾病检测项目。功能包括色素分解、皮肤敏感、毛孔检测、斑点检测、肌底抗衰、粉刺等皮肤疾病检测。包括“局部皮肤检测”和“全脸皮肤检测”。在做全脸皮肤疾病检测的时候做了提取人脸皮肤的功能。试过基于RGB颜色空间、HSV颜色空间、YCrCb颜色空间的Cr分量+OSTU等多种方法,效果不是那么完美。

     后来也试了调阿里云的人脸检测接口。要先获取调用API的url及所需要的ak_id和ak_secret。这里使用的是libcurl和cJSON,通过https请求来获取人脸关键点。libcurl 需要自己编译,我有编译好的已上传给大家,需要的朋友可以到我的下载资源里去下载。cJSON也比较方便。下载后可以直接将cJSON.h和cJSON.c拷贝到项目中去,添加头文件即可。

    这里将调用阿里云的功能封装成一个函数。相关参数如下: 

    参数1:要调用的阿里云url:https://dtplus-cn-shanghai.data.aliyuncs.com/face/detect

    参数2:传入的图片

    参数3:图片长度

    参数4,5:申请的ak_id和ak_secret

    参数6:返回的关键点信息,放入vector中

// 调用阿里云,返回图片关键点
int HttpPostAliYun(const string& url, const unsigned char* image, int imageLen, const string&ak_id, const string& ak_secret, vector<double> &landmardk_info)
{
	string strStl;
	// 返回信息
	RespData respData = { 0,0 };
	int size = 102400;   // 这里需要确认  长度要固定吗?

	if (respData.buff == 0)
		respData.buff = new char[size];
	respData.len = 0;
	memset(respData.buff, 0, size);

	// 创建一个Object结构体
	cJSON * root = cJSON_CreateObject();
	// 将图片加密,得到base64字符串
	string base64str = CUtils::Base64Encode(image, imageLen);
	cout << "base64Str:" << base64str << endl;
	string body("{\"type\":1,\"content\":");
	body += "\"" + base64str + "\"}";

	string method = "POST";
	string accept = "application/json";
	string content_type = "application/json";
	string path = "/face/attribute";
	string date = CUtils::GetGMTDatetime();
	string bodyMd5str = CUtils::Md5Base64(body);

	string stringToSign = method + "\n" + accept + "\n" + bodyMd5str + "\n" + content_type + "\n" + date + "\n" + path;
	// 签名
	string signature = CUtils::HMACSha1Base64(stringToSign, ak_secret);
	string authHeader = "Dataplus " + ak_id + ":" + signature;

	cout << "body:" << body.c_str() << endl;
	cout << "url       :" << url.c_str() << endl;
	cout << "date      :" << date.c_str() << endl;
	cout << "bodyMd5str:" << bodyMd5str.c_str() << endl;
	cout << "signature :" << signature.c_str() << endl;

	CURL* curl = NULL;
	CURLcode res = CURLE_OK;

	struct curl_slist* headers = NULL;
	char tmp_str[256] = { 0 };

	snprintf(tmp_str, sizeof(tmp_str), "Content-Type: %s", "application/json");
	headers = curl_slist_append(headers, tmp_str);
	snprintf(tmp_str, sizeof(tmp_str), "Accept: %s", "application/json");
	headers = curl_slist_append(headers, tmp_str);
	snprintf(tmp_str, sizeof(tmp_str), "Date: %s", date.c_str());
	headers = curl_slist_append(headers, tmp_str);
	snprintf(tmp_str, sizeof(tmp_str), "Authorization: %s", authHeader.c_str());
	headers = curl_slist_append(headers, tmp_str);
	// 1.curl初始化
	curl = curl_easy_init();
	if (curl)
	{
		//CUtils::writeLog("curl初始化成功");
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &respData);

		// 2.以阻塞方式执行文件请求
		CURLcode retcode = curl_easy_perform(curl);
		// 请求返回成功
		if (CURLE_OK == retcode)
		{
			// 3.执行文件成功,解析返回的json
			cout << " respData:" << respData.buff << endl;

			cJSON *strStl = cJSON_Parse(respData.buff);
			CUtils::writeLog("respData:" + (std::string)respData.buff);
			if (!strStl)
			{
				cout << "parse json failed." << endl;
				CUtils::writeLog("parse json failed.");
				return -1;
			}
			// 解析json成功(这里使用的是cJSON)
			// 创建一个对象 获取Json里面的错误代码(errno)
			cJSON *error = cJSON_GetObjectItem(strStl, "errno");                // 错误代码
			cJSON *facenum = cJSON_GetObjectItem(strStl, "face_num");           // 人脸个数
			cJSON *landmark_num = cJSON_GetObjectItem(strStl, "landmark_num");  // 特征点个数

			// 打印错误代码
			char* strErr = cJSON_Print(error);
			//std::string strErr = error->valuestring;
			string str_landmark_num = cJSON_Print(landmark_num);

			cout << "特征点个数:" << str_landmark_num << endl;
			//CUtils::writeLog("特征点个数:" + (std::string)str_landmark_num);    

			// 判断返回的错误代码error
			// 错误代码是0,表示成功
			if (error->valueint == 0)
			{
				// 判断人脸数目
				if (facenum->valueint == 0)
				{
					// 没有找到人脸
					return -1;
				}
				else {
					// 找到了人脸
					// 如果人脸个数是1
					if (facenum->valueint == 1)
					{
						// 获取返回数据中的“landmark”字段
						cJSON *landmarks = cJSON_GetObjectItem(strStl, "landmark");
						// 将特征点写入文本文件
						char* strLandmarks = cJSON_Print(landmarks);
						//CUtils::writeLog("人脸特征点:" + (std::string)strLandmarks);

						// 获取特征点的个数   就是cJSON对象landmarks的长度
						int len = cJSON_GetArraySize(landmarks);

						cout << "特征点个数的长度:" << len << endl;
						//CUtils::writeLog("特征点个数的长度:" + CUtils::int_to_string(len)); 
						// 长度
						for (int i = 0; i < len; i++)
						{
							// 将返回的一个个数据放入vector容器中
							cJSON *subItem = cJSON_GetArrayItem(landmarks, i);    // 获取第i个数据
							double value_landmark_item = subItem->valuedouble;   // 转换成double数据
							landmardk_info.push_back(value_landmark_item);
						}
					}
					else {
						// 多个人脸
						return -1;
					}
				}
			}
			//解析json失败
			else {
				//CUtils::writeLog("parse json failed. the errno is:" + (std::string)strErr);
				return -1;
			}
		}
		else
		{
			// 执行文件请求返回失败
			// 获取错误代码
			string error = curl_easy_strerror(retcode);
			// 可以更新错误代码
			curl_easy_cleanup(curl);
			return -1;
		}
	}
	else {
		CUtils::writeLog("curl初始化失败...");
		return -1;
	}
	return 0;
}

效果图:

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值