C++处理JSON数据和在face++ 调用中的使用

Posted deep_learninger

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++处理JSON数据和在face++ 调用中的使用相关的知识,希望对你有一定的参考价值。

使用C++处理JSON数据交换格式
一、摘要
    JSON的全称为:javascript Object Notation,顾名思义,JSON是用于标记Javascript对象的,JSON官方的解释为:JSON是一种轻量级的数据传输格式。本文并不详细介绍JSON本身的细节,旨在讨论如何使用C++语言来处理JSON。关于JSON更具体的信息,可参见JSON官网:http://www.json.orghttp://json.org/json-zh.html
二、本文选择处理JSON的C++库
   本文选择一个第三方库jsoncpp来解析JSON。jsoncpp是比较出名的C++ JSON解析库。在JSON官网也是首推的。下载地址为:http://sourceforge.net/projects/jsoncpp。本文使用的jsoncpp版本为:0.5.0。
三、jsoncpp在Windows下的编译
 
方法一:使用Jsoncpp生成的lib文件
      解压上面下载的Jsoncpp文件,在jsoncpp-src-0.5.0/makefiles/vs71目录里找到jsoncpp.sln,用VS2008版本编译,默认生成静态链接库。 在工程中引用,只需要包含include/json下的头文件及生成的.lib文件即可。       如何包含lib文件:在.cpp文件中#pragma comment(lib."json_vc71_libmt.lib"),
           在工程属性中Linker下Input中Additional Dependencies写入lib文件名字(Release下为json_vc71_libmt.lib,Debug为json_vc71_libmtd.lib


注意:Jsoncpp的lib工程编译选项要和VS工程中的编译选项保持一致。如lib文件工程编译选项为MT(或MTd),VS工程中也要选择MT(或MTd),否则会出现编译错误问题,debug和release下生成的lib文件名字不同,注意不要看错了,当成一个文件来使用(我就犯了这个错误)。
 
方法二:使用Jsoncpp包中的.cpp.h文件
      解压上面下载的Jsoncpp文件,把jsoncpp-src-0.5.0文件拷贝到工程目录下,jsoncpp-src-0.5.0\\jsoncpp-src-0.5.0\\include\\jsonjsoncpp-src-0.5.0\\jsoncpp-src-0.5.0\\src\\lib_json目录里的文件包含到VS工程中,在VS工程的属性C/C++下General中Additional Include Directories包含头文件目录.\\jsoncpp-src-0.5.0\\include。在使用的cpp文件中包含json头文件即可,如:#include "json/json.h"。将json_reader.cpp、json_value.cpp和json_writer.cpp三个文件的Precompiled Header属性设置为Not Using Precompiled Headers否则编译会出现错误。

jsoncpp 使用详解

jsoncpp 主要包含三种类型的 class:Value、Reader、Writer。jsoncpp 中所有对象、类名都在 namespace Json 中,包含 json.h 即可。

Json::Value 只能处理 ANSI 类型的字符串,如果 C++ 程序是用 Unicode 编码的,最好加一个 Adapt 类来适配。


本实验采用方法二, 这样方便调试,同时也方便学习该开源库的代码。 本代码不为商用, 所以以学习为主。

四\\ 需要解析的数据,face++ 调动返回json数据,数据个数如下:
{
    "face": [
        {
            "attribute": {
                "age": {
                    "range": 5, 
                    "value": 23
                }, 
                "gender": {
                    "confidence": 99.9999, 
                    "value": "Female"
                }, 
                "glass": {
                    "confidence": 99.945, 
                    "value": "None"
                }, 
                "pose": {
                    "pitch_angle": {
                        "value": 17
                    }, 
                    "roll_angle": {
                        "value": 0.735735
                    }, 
                    "yaw_angle": {
                        "value": -2
                    }
                }, 
                "race": {
                    "confidence": 99.6121, 
                    "value": "Asian"
                }, 
                "smiling": {
                    "value": 4.86501
                }
            }, 
            "face_id": "17233b4b1b51ac91e391e5afe130eb78", 
            "position": {
                "center": {
                    "x": 49.4, 
                    "y": 37.6
                }, 
                "eye_left": {
                    "x": 43.3692, 
                    "y": 30.8192
                }, 
                "eye_right": {
                    "x": 56.5606, 
                    "y": 30.9886
                }, 
                "height": 26.8, 
                "mouth_left": {
                    "x": 46.1326, 
                    "y": 44.9468
                }, 
                "mouth_right": {
                    "x": 54.2592, 
                    "y": 44.6282
                }, 
                "nose": {
                    "x": 49.9404, 
                    "y": 38.8484
                }, 
                "width": 26.8
            }, 
            "tag": ""
        }
    ], 
    "img_height": 500, 
    "img_id": "22fd9efc64c87e00224c33dd8718eec7", 
    "img_width": 500, 
    "session_id": "38047ad0f0b34c7e8c6efb6ba39ed355", 
    "url": "http://www.faceplusplus.com.cn/wp-content/themes/faceplusplus/assets/img/demo/1.jpg?v=4"
}

五、遇到问题,曾经尝试多次,找了很多博客都是不能解决问题,
仔细观察后,发现有[ ], 这个不能忽视。http://blog.163.com/pei_hua100/blog/static/80569759201333114010800/ 通过这个博客启发。发现[] 为里面的数据。所以更改代码如下。
<span style="color:#333333;">Json::Value detect;
	Json::Value face;
	if (!DetectResult1.parse(DetectResult, detect))
	{
		return -1;
	}

	int face_size = detect["face"].size();
	// 遍历face 个数
	for (int i = 0; i < face_size; i++) </span><span style="color:#ff0000;"> 这里很关键,学会使用该方法。</span><span style="color:#333333;">
	{
		Json::Value attribute;
		attribute = detect["face"][i]["attribute"];
		int attribute_size = attribute.size();
		int age = attribute["age"]["value"].asInt();
		string gender = attribute["gender"]["value"].asString();
		int smiling = attribute["smiling"]["value"].asInt();
		string race = attribute["race"]["value"].asString();
	}
	for (int i = 0; i < face_size; i++)
	{
		Json::Value position;
		position = detect["face"][i]["position"];
		int centerX = position["center"]["x"].asInt();
		int centerY = position["center"]["y"].asInt();
		int eye_leftx = position["eye_left"]["x"].asInt();
		int eye_lefty = position["eye_left"]["y"].asInt();
		int eye_rightx = position["eye_right"]["x"].asInt();
		int eye_righty = position["eye_right"]["y"].asInt();
		int height = position["height"].asInt();
		cout << "centerX" << centerX << "centerY" << centerY << endl;

		int mouth_leftx = position["mouth_left"]["x"].asInt();
		int mouth_lefty = position["mouth_left"]["y"].asInt();
		int mouth_rightx = position["mouth_right"]["x"].asInt();
		int mouth_righty = position["mouth_right"]["y"].asInt();
		int nosex = position["nose"]["x"].asInt();
		int nosey = position["nose"]["y"].asInt();
		int width = position["width"].asInt();
	}
	int img_height = detect["img_height"].asInt();
	cout << "img_height" << img_height << endl;
	int img_width = face["img_width"].asInt();
</span>

通过这个方式,发现curl 返回的代码 里面有\\n 换行符, 想办法去掉他。
本实验的实现方式如下:
// 去掉返回值中的 \\n 换行符
	string::iterator it;
	for (it = HTTPRESULT.begin(); it != HTTPRESULT.end(); ++it)
	{
		if (*it == '\\n')
		{
		//	*it = '\\\\r\\\\n';
			HTTPRESULT.erase(it);
		}
	}

本次实验所有代码如下:
// face++.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <string>  
#include <iostream>  
using namespace std;
#include "HttpClient.h"  
#include "curl/curl.h"  
#include "curl/easy.h"  
std::string strResult;
#include <opencv2\\core\\core.hpp>
#include <opencv2\\highgui\\highgui.hpp>

#include "json/json.h"
using namespace cv;

// #pragma comment(lib, "libcurl.lib")  

std::string HTTPRESULT;

const char* detectResult;
void Write_data(void* buffer, size_t size, size_t nmemb, void* user_p){
	cout << "(const char*)buffer" << (const char*)buffer << endl;
	HTTPRESULT += (const char*)buffer;
	detectResult = (const char*)buffer;

}


int _tmain(int argc, _TCHAR* argv[])
{


	CURL *curl = curl_easy_init();
	CURLcode res = curl_global_init(CURL_GLOBAL_WIN32);
	struct curl_httppost *formpost = NULL;
	struct curl_httppost *lastptr = NULL;
	//        struct curl_slist *headerlist=NULL;  
	//        static const char buf[] = "Expect:";  

	curl_formadd(&formpost,
		&lastptr,
		CURLFORM_COPYNAME, "api_key",
		CURLFORM_COPYCONTENTS, "d45344602f6ffd77baeab05b99fb7730",
		CURLFORM_END);
	curl_formadd(&formpost,
		&lastptr,
		CURLFORM_COPYNAME, "api_secret",
		CURLFORM_COPYCONTENTS, "jKb9XJ_GQ5cKs0QOk6Cj1HordHFBWrgL",
		CURLFORM_END);


	char* file_data = NULL;
	long file_size = 0;
	string imageName = "d:\\\\mqx.jpg";
	FILE* fp = fopen("d:\\\\mqx.jpg", "rb");
	if (fp)
	{
		fseek(fp, 0, SEEK_END);
		file_size = ftell(fp);
		fseek(fp, 0, SEEK_SET);
		file_data = new char[file_size + 1];
		fread(file_data, 1, file_size, fp);
		cout << file_data << endl;
		fclose(fp);
	}


	curl_formadd(&formpost, &lastptr,
		CURLFORM_COPYNAME, "img",
		CURLFORM_BUFFER, "test.jpg",
		CURLFORM_BUFFERPTR, file_data,
		CURLFORM_BUFFERLENGTH, file_size,
		CURLFORM_CONTENTTYPE, "image/jpeg",
		CURLFORM_END);


	if (curl) {
		// what URL that receives this POST 
		curl_easy_setopt(curl, CURLOPT_URL, "http://apicn.faceplusplus.com/v2/detection/detect");
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);

		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &HTTPRESULT);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Write_data);
		cout << "CURLOPT_WRITEFUNCTION" << CURLOPT_WRITEFUNCTION << endl;

		char error[1024];
		curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);

		res = curl_easy_perform(curl);
		if (res != CURLE_OK) cout << endl << error << endl;
	}
	curl_easy_cleanup(curl);
	curl_formfree(formpost);
	cout << endl << HTTPRESULT<< endl;
//	cout << endl << "测试结果如下" << endl;
//	cout << endl << "年龄:" << HTTPRESULT.find("value") << endl;
//	cout << endl << "年龄:" << HTTPRESULT.substr(HTTPRESULT.find("age", 0)) << endl;
//	cout << endl << "年龄:" << HTTPRESULT.substr(HTTPRESULT.find("gender",0)) << endl;
//	cout << endl << "年龄:" << HTTPRESULT.substr(HTTPRESULT.find("race", 0)) << endl;
//	cout << endl << "年龄:" << HTTPRESULT.substr(HTTPRESULT.find("smiling", 0)) << endl;
	// 得到年龄性别等。
	int agePos = HTTPRESULT.find("age", 0);
	string age = HTTPRESULT.substr(agePos + 70, 2);
	int genderPos = HTTPRESULT.find("gender", 0);
	string gender = HTTPRESULT.substr(genderPos + 84, 6);
	int racePos = HTTPRESULT.find("race", 0);
	string race = HTTPRESULT.substr(racePos + 83, 5);
	int smilingPos = HTTPRESULT.find("smiling", 0);
	string smiling = HTTPRESULT.substr(smilingPos + 41, 5);
	// end 结束
	
	/*
	//读入图像
	Mat img = imread(imageName, CV_LOAD_IMAGE_COLOR);
	//如果读入图像失败
	if (img.empty())
	{
		cout << "Could not open or find the image!" << endl;
		return -1;
	}
	//创建窗口
	namedWindow("face", CV_WINDOW_AUTOSIZE);
	//显示图像
	imshow("face", img);
	//等待按键,按键盘任意键返回
	waitKey(-1);
//	while (HTTPRESULT != " ")
//	{
//		agePos[numage] = HTTPRESULT.find("value");
//		HTTPRESULT
//	}
//	int agePos = HTTPRESULT.find("value");
	if (file_data != NULL)
		delete[] file_data;

		*/


	//HTTPRESULT = HTTPRESULT.replace(/ \\\\n / g, "\\\\n");
// 去掉返回值中的 \\n 换行符
	string::iterator it;
	for (it = HTTPRESULT.begin(); it != HTTPRESULT.end(); ++it)
	{
		if (*it == '\\n')
		{
		//	*it = '\\\\r\\\\n';
			HTTPRESULT.erase(it);
		}
	}

	const char * DetectResult = HTTPRESULT.c_str();

	Json::Reader DetectResult1;
	Json::Value detect;
	Json::Value face;
	if (!DetectResult1.parse(DetectResult, detect))
	{
		return -1;
	}

	int face_size = detect["face"].size();
	// 遍历face 个数
	for (int i = 0; i < face_size; i++)
	{
		Json::Value attribute;
		attribute = detect["face"][i]["attribute"];
		int attribute_size = attribute.size();
		int age = attribute["age"]["value"].asInt();
		string gender = attribute["gender"]["value"].asString();
		int smiling = attribute["smiling"]["value"].asInt();
		string race = attribute["race"]["value"].asString();
	}
	for (int i = 0; i < face_size; i++)
	{
		Json::Value position;
		position = detect["face"][i]["position"];
		int centerX = position["center"]["x"].asInt();
		int centerY = position["center"]["y"].asInt();
		int eye_leftx = position["eye_left"]["x"].asInt();
		int eye_lefty = position["eye_left"]["y"].asInt();
		int eye_rightx = position["eye_right"]["x"].asInt();
		int eye_righty = position["eye_right"]["y"].asInt();
		int height = position["height"].asInt();
		cout << "centerX" << centerX << "centerY" << centerY << endl;

		int mouth_leftx = position["mouth_left"]["x"].asInt();
		int mouth_lefty = position["mouth_left"]["y"].asInt();
		int mouth_rightx = position["mouth_right"]["x"].asInt();
		int mouth_righty = position["mouth_right"]["y"].asInt();
		int nosex = position["nose"]["x"].asInt();
		int nosey = position["nose"]["y"].asInt();
		int width = position["width"].asInt();
	}
	int img_height = detect["img_height"].asInt();
	cout << "img_height" << img_height << endl;
	int img_width = face["img_width"].asInt();


	system("pause");
	return 0;
}




下面是从网上找的代码示例:
1. 从字符串解析json
     const  char * str = "{\\"uploadid\\": \\"UP000000\\",\\"code\\": 100,\\"msg\\": \\"\\",\\"files\\": \\"\\"}";       Json::Reader reader;       Json::Value root;        if  (reader.parse(str, root))   //  reader将Json字符串解析到root,root将包含Json里所有子元素       {           std:: string  upload_id = root["uploadid"].asString();   //  访问节点,upload_id = "UP000000"            int  code = root["code"].asInt();     //  访问节点,code = 100      }  

以上是关于C++处理JSON数据和在face++ 调用中的使用的主要内容,如果未能解决你的问题,请参考以下文章

人脸识别 python调用face++ 功能测试

C++ 中的 compute_face_descriptor() 替代方案

使用请求正文从Microsoft Computer Vision调用Face API是“application / json”

OpenCV c++ 找不到 <opencv2/face.hpp>

使用 C++ 处理 JSON 数据交换格式

Javascript中的范围链和在全局范围内调用嵌套函数