果蔬识别能识别近千种水果和蔬菜的名称,适用于识别只含有一种果蔬的图片,可自定义返回识别结果数,适用于果蔬介绍相关的美食类APP中。
应用场景
果蔬介绍:根据拍摄照片,识别图片中果蔬名称,可结合识别结果进一步为用户提供营养价值、搭配禁忌,果蔬推荐等相关信息,广泛应用于美食类APP中。
接口描述 该请求用于识别果蔬类食材,即对于输入的一张图片(可正常解码,且长宽比适宜),输出图片中的果蔬食材结果。
请求说明
HTTP 方法: POST
请求 URL: https://aip.baidubce.com/rest/2.0/image-classify/v1/classify/ingredient
URL参数: access_token
Header 参数: Content-Type
= application/x-www-form-urlencoded
Body 参数:见下表
参数
是否必选
类型
默认值
说明
image
是
string
-
图像数据,base64
编码,要求 base64
编码后大小不超过 4M,最短边至少 15px
,最长边最大 4096px
, 支持 jpg/png/bmp
格式 。注意:图片需要 base64
编码、去掉编码头后再进行 urlencode
top_num
否
unit32
-
返回预测得分 top 结果数,如果为空或小于等于 0 默认为 5;如果大于 20 默认 20
返回说明 返回参数如下表:
字段
是否必选
类型
说明
log_id
是
uint64
唯一的 log id,用于问题定位
result
是
object()
识别结果
result_num
否
unit32
识别结果数
+name
否
string
图像中的食材名称
+score
否
double
得分,0-1
返回示例如下:
{ "log_id" : 1091287364 , "result_num" : 20 , "result" : [ { "name" : "非果蔬食材" , "score" : 0.99999988079071 } , { "name" : "油菜" , "score" : 1.1175458780599e-8 } , { "name" : "蛇果" , "score" : 7.2776291659693e-9 } , { "name" : "国光苹果" , "score" : 5.6971951600815e-9 } , { "name" : "海枣" , "score" : 4.2508210285064e-9 } , { "name" : "琼瑶浆葡萄" , "score" : 4.1451895249622e-9 } , { "name" : "京锐号辣椒" , "score" : 3.9915102334476e-9 } , { "name" : "冬瓜" , "score" : 3.3611948779821e-9 } , { "name" : "长江豆" , "score" : 2.9944848822794e-9 } , { "name" : "黑加仑" , "score" : 2.7750137743254e-9 } , { "name" : "面包果" , "score" : 2.3357531464541e-9 } , { "name" : "椰子" , "score" : 1.9741890344704e-9 } , { "name" : "美人瓜" , "score" : 1.9319581490151e-9 } , { "name" : "莲藕" , "score" : 1.759222323372e-9 } , { "name" : "黑奥林" , "score" : 1.7266311713726e-9 } , { "name" : "芥菜" , "score" : 1.6180708994895e-9 } , { "name" : "样芹菜" , "score" : 1.5472728653876e-9 } , { "name" : "篙巴" , "score" : 1.4084827748562e-9 } , { "name" : "花生" , "score" : 1.3972580870103e-9 } , { "name" : "魁绿猕猴桃" , "score" : 1.3920842256709e-9 } ] }
C++ 代码实现调用 这里假设已经将环境配置好了,环境配置的文章可以参考 Windows 下使用 Vcpkg 配置百度 AI 图像识别 C++开发环境(VS2017) 。
为了方便,首先根据返回参数定义了一个结构体,该结构体包括了返回参数中的参数,如下:
struct IngredientInfo { std::string name; double score; void print () { std::cout << std::setw (30 ) << std::setfill ('-' ) << '\n' ; std::cout << "name: " << name << '\n' ; std::cout << "score: " << score << '\n' ; } };
在 IngredientInfo
结构体中,定义了一个 print
方法以打印获取的结果。
然后定义了一个类来调用接口并获取结果
class Ingredient { public : Ingredient (); ~Ingredient (); Json::Value request (std::string imgBase64, std::map<std::string, std::string>& options) ; void getAllResult (std::vector<IngredientInfo>& results) ; void getResult (IngredientInfo& result) ; private : Json::Value obj_; std::string url_; uint32_t top_num_; std::string filename_; };
类中的私有成员 obj_
表示返回结果对应的 json 对象。url_
表示请求的 url,top_num_
表示识别结果数,filename_
表示用于存储 access token
的文件的文件名。
request
函数输入请求图像的 base64 编码以及请求参数,返回一个 json 对象,json 对象中包含请求的结果。
getAllResult
获取请求的结果,总共有 top_num 条结果。
getResult
获取 score 最高的一条结果。
完整代码如下
util.h
和 util.cpp
代码参见 (简单调用篇 01) 通用物体和场景识别高级版 - C++ 简单调用
Ingredient.h
代码如下:
#pragma once #include "util.h" struct IngredientInfo { std::string name; double score; void print () { std::cout << std::setw (30 ) << std::setfill ('-' ) << '\n' ; std::cout << "name: " << name << '\n' ; std::cout << "score: " << score << '\n' ; } }; class Ingredient { public : Ingredient (); ~Ingredient (); Json::Value request (std::string imgBase64, std::map<std::string, std::string>& options) ; void getAllResult (std::vector<IngredientInfo>& results) ; void getResult (IngredientInfo& result) ; private : Json::Value obj_; std::string url_; uint32_t top_num_; std::string filename_; }; void ingredientTest () ;
Ingredient.cpp
代码如下:
#include "Ingredient.h" Ingredient::Ingredient () { filename_ = "tokenKey" ; url_ = "https://aip.baidubce.com/rest/2.0/image-classify/v1/classify/ingredient" ; } Ingredient::~Ingredient () { } Json::Value Ingredient::request (std::string imgBase64, std::map<std::string, std::string>& options) { if (options.find ("top_num" ) == options.end ()) { top_num_ = 5 ; } else { int top_num = stoi (options["top_num" ]); top_num_ = top_num <= 0 ? 5 : (top_num >= 20 ? 20 : top_num); } std::string response; Json::Value obj; std::string token; std::string body; mergeHttpPostBody (body, imgBase64, options); std::string url = url_; getHttpPostUrl (url, filename_, token); int status_code = httpPostRequest (url, body, response); if (status_code != CURLcode::CURLE_OK) { obj["curl_error_code" ] = status_code; obj_ = obj; return obj; } generateJson (response, obj); if (obj["error_code" ].asInt () == 110 || obj["error_code" ].asInt () == 111 ) { token = getTokenKey (); writeFile (filename_, token); return request (imgBase64, options); } obj_ = obj; checkErrorWithExit (obj); return obj; } void Ingredient::getAllResult (std::vector<IngredientInfo>& results) { int len = obj_["result" ].size (); results.reserve (len); IngredientInfo tmp; for (int i = 0 ; i < len; ++i) { tmp.name = UTF8ToGB (obj_["result" ][i]["name" ].asString ().c_str ()); tmp.score = obj_["result" ][i]["score" ].asDouble (); results.push_back (tmp); } } void Ingredient::getResult (IngredientInfo & result) { result.name = UTF8ToGB (obj_["result" ][0 ]["name" ].asString ().c_str ()); result.score = obj_["result" ][0 ]["score" ].asDouble (); } void ingredientTest () { std::cout << "size: " << sizeof (IngredientInfo) << "\n" ; std::string imgFile = "./images/vegetable.png" ; std::string imgBase64; imgToBase64 (imgFile, imgBase64); std::map<std::string, std::string> options; options["top_num" ] = "10" ; Json::Value obj; Ingredient ingredientObj; obj = ingredientObj.request (imgBase64, options); IngredientInfo result; ingredientObj.getResult (result); result.print (); std::vector<IngredientInfo> results; ingredientObj.getAllResult (results); for (auto & vec : results) { vec.print (); } }
main.cpp
代码如下:
#include "util.h" #include "Ingredient.h" #include <stdlib.h> int main () { ingredientTest (); system ("pause" ); return EXIT_SUCCESS; }
运行结果 测试图像