品牌 logo 识别能识别超过 2 万类商品 logo,支持用户创建属于自己的品牌 logo 图库,可准确识别图片中品牌 logo 的名称,适用于需要快速获取品牌信息的业务场景中
应用场景
品牌信息获取:根据拍摄照片,识别图片中商品 logo 名称,加快品牌信息获取速度,给消费者轻松高效的信息获取体验,促进消费者向投资者转化,适用于需要快速获取品牌信息的业务场景中
接口描述 该请求用于检测和识别图片中的台标、品牌商标等 logo 信息。即对于输入的一张图片(可正常解码,且长宽比适宜),输出图片中 logo 的名称、位置和置信度。
使用时,可直接调用 logo 识别-检索接口,支持识别超过 2 万类 logo 名称;当效果欠佳时,可以建立子库(在控制台创建应用并申请建库)并通过调用 logo 入口接口完成自定义 logo 入库,再调用 logo 识别-检索接口,选择在自定义 logo 库内检索,提高识别效果。
请求说明
HTTP 方法: POST
请求 URL: https://aip.baidubce.com/rest/2.0/image-classify/v2/logo
URL参数: access_token
Header 参数: Content-Type
= application/x-www-form-urlencoded
Body 参数:见下表
参数
是否必选
类型
可选值范围
说明
image
是
string
-
图像数据,base64
编码,要求 base64
编码后大小不超过 4M,最短边至少 15px
,最长边最大 4096px
, 支持 jpg/png/bmp
格式 。注意:图片需要 base64
编码、去掉编码头后再进行 urlencode
custom_lib
否
integer
-
是否只检索用户子库,true 则只检索用户子库, false (默认)为检索底库 + 用户子库
返回说明 返回参数如下表:
字段
是否必选
类型
说明
log_id
是
uint64
唯一的 log id,用于问题定位
result_num
是
uint32
识别结果数,标识返回结果数目
result
否
array()
返回结果数组,每一项为一个识别出的 logo
+location
是
object
位置信息(左起像素位置、上起像素位置、像素宽、像素高)
++left
是
number
坐起像素位置
++top
是
number
上起像素位置
++width
是
number
像素宽
++height
是
number
像素高
+name
是
string
识别的品牌名称
+probability
是
number
分类结果置信度(0
—1.0
)
+type
是
number
type=0
为 1 千种高优商标识别结果; type=1
为 2 万类 logo 库的结果;其它 type 为自定义 logo 库结果
返回示例如下:
{ "log_id" : 843411868 , "result_num" : 1 , "result" : [ { "type" : 0 , "name" : "科颜氏" , "probability" : 0.99998807907104 , "location" : { "width" : 296 , "top" : 20 , "height" : 128 , "left" : 23 } } ] }
了解更多关于 logo 识别-入库 和 logo 识别-删除
C++ 代码实现调用 这里假设已经将环境配置好了,环境配置的文章可以参考 Windows 下使用 Vcpkg 配置百度 AI 图像识别 C++开发环境(VS2017) 。
为了方便,首先根据返回参数定义了两个结构体,结构体包括了返回参数中的参数,如下:
struct Location { int left; int top; int width; int height; void print () { std::cout << "\n\t left: " << left << " top: " << top << " width: " << width << " height: " << height << '\n' ; } void draw (cv::Mat &img) { cv::Rect rect (left, top, width, height) ; cv::rectangle (img, rect, cv::Scalar (255 , 0 , 255 ), 3 ); } }; struct LogoInfo { int type; std::string name; float probability; Location location; void print () { std::cout << std::setw (30 ) << std::setfill ('-' ) << '\n' ; std::cout << "type: " << type << "\n" ; std::cout << "name: " << name << "\n" ; std::cout << "probability: " << std::fixed << std::setprecision (4 ) << probability << "\n" ; std::cout << "location: " ; location.print (); } void draw (cv::Mat &img) { location.draw (img); } };
在 Location
结构体中,定义了一个 print
方法以打印 logo 位置信息。draw
方法用于在图像中画出 logo 的边框。
在 LogoInfo
结构体中,定义了一个 print
方法以打印 logo 结果信息。draw
方法用于在图像中画出 logo 的边框。
然后定义了一个类来调用接口并获取结果
class Logo { public : Logo (); ~Logo (); Json::Value request (std::string imgBase64, std::map<std::string, std::string>& options) ; uint32_t getResultNum () ; void getAllResult (std::vector<LogoInfo>& results) ; void getResult (LogoInfo& result) ; private : Json::Value obj_; std::string url_; uint32_t result_num_; std::string filename_; };
类中的私有成员 obj_
表示返回结果对应的 json 对象。url_
表示请求的 url,result_num_
表示返回的结果数,filename_
表示用于存储 access token
的文件的文件名。
request
函数输入请求图像的 base64 编码以及请求参数,返回一个 json 对象,json 对象中包含请求的结果。
getAllResult
获取请求的结果,总共有 top_num 条结果。
getResult
获取置信度最高的一条结果。
完整代码如下
util.h
和 util.cpp
代码参见 (简单调用篇 01) 通用物体和场景识别高级版 - C++ 简单调用
Logo.h
代码如下:
#pragma once #include "util.h" struct Location { int left; int top; int width; int height; void print () { std::cout << "\n\t left: " << left << " top: " << top << " width: " << width << " height: " << height << '\n' ; } void draw (cv::Mat &img) { cv::Rect rect (left, top, width, height) ; cv::rectangle (img, rect, cv::Scalar (255 , 0 , 255 ), 3 ); } }; struct LogoInfo { int type; std::string name; float probability; Location location; void print () { std::cout << std::setw (30 ) << std::setfill ('-' ) << '\n' ; std::cout << "type: " << type << "\n" ; std::cout << "name: " << name << "\n" ; std::cout << "probability: " << std::fixed << std::setprecision (4 ) << probability << "\n" ; std::cout << "location: " ; location.print (); } void draw (cv::Mat &img) { location.draw (img); } }; class Logo { public : Logo (); ~Logo (); Json::Value request (std::string imgBase64, std::map<std::string, std::string>& options) ; uint32_t getResultNum () ; void getAllResult (std::vector<LogoInfo>& results) ; void getResult (LogoInfo& result) ; private : Json::Value obj_; std::string url_; uint32_t result_num_; std::string filename_; }; void logoTest () ;
Logo.cpp
代码如下:
#include "Logo.h" Logo::Logo () { filename_ = "tokenKey" ; url_ = "https://aip.baidubce.com/rest/2.0/image-classify/v2/logo" ; } Logo::~Logo () { } Json::Value Logo::request (std::string imgBase64, std::map<std::string, std::string>& options) { 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; } uint32_t Logo::getResultNum () { return obj_["result_num" ].asInt (); } void Logo::getAllResult (std::vector<LogoInfo>& results) { result_num_ = getResultNum (); results.reserve (result_num_); LogoInfo tmp; for (uint32_t i = 0 ; i < result_num_; ++i) { tmp.type = obj_["result" ][i]["type" ].asInt (); tmp.name = UTF8ToGB (obj_["result" ][i]["name" ].asString ().c_str ()); tmp.probability = obj_["result" ][i]["probability" ].asFloat (); tmp.location.left = obj_["result" ][i]["location" ]["left" ].asInt (); tmp.location.top = obj_["result" ][i]["location" ]["top" ].asInt (); tmp.location.width = obj_["result" ][i]["location" ]["width" ].asInt (); tmp.location.height = obj_["result" ][i]["location" ]["height" ].asInt (); results.push_back (tmp); } } void Logo::getResult (LogoInfo & result) { result.type = obj_["result" ][0 ]["type" ].asInt (); result.name = UTF8ToGB (obj_["result" ][0 ]["name" ].asString ().c_str ()); result.probability = obj_["result" ][0 ]["probability" ].asFloat (); result.location.left = obj_["result" ][0 ]["location" ]["left" ].asInt (); result.location.top = obj_["result" ][0 ]["location" ]["top" ].asInt (); result.location.width = obj_["result" ][0 ]["location" ]["width" ].asInt (); result.location.height = obj_["result" ][0 ]["location" ]["height" ].asInt (); } void logoTest () { std::cout << "size: " << sizeof (LogoInfo) << "\n" ; std::string imgFile = "./images/logo_test.jpg" ; std::string imgBase64; imgToBase64 (imgFile, imgBase64); std::map<std::string, std::string> options; Json::Value obj; Logo logoObj; obj = logoObj.request (imgBase64, options); LogoInfo result; logoObj.getResult (result); result.print (); cv::Mat img = cv::imread (imgFile); result.draw (img); cv::namedWindow ("Logo Test" , cv::WINDOW_NORMAL); cv::imshow ("Logo Test" , img); std::vector<LogoInfo> results; logoObj.getAllResult (results); cv::Mat img1 = cv::imread (imgFile); cv::namedWindow ("Logo Tests" , cv::WINDOW_NORMAL); for (auto & vec : results) { vec.print (); vec.draw (img1); } cv::imshow ("Logo Tests" , img1); cv::waitKey (); }
main.cpp
代码如下:
#include "util.h" #include "Logo.h" #include <stdlib.h> int main () { logoTest (); system ("pause" ); return EXIT_SUCCESS; }
运行结果 测试图像