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.org。http://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\\json和jsoncpp-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++ 调用中的使用的主要内容,如果未能解决你的问题,请参考以下文章
C++ 中的 compute_face_descriptor() 替代方案
使用请求正文从Microsoft Computer Vision调用Face API是“application / json”