欢迎来到站长教程网!

PHPCMS

当前位置: 主页 > 开户教程 > PHPCMS

(简单调用篇 03) 动物识别 - C++ 简单调用

时间:2025-02-15 10:49:26|栏目:PHPCMS|点击:

动物识别能够识别近八千种动物,接口返回动物名称,并获取百科信息,适用于拍照识图类APP中。

  • 拍照识别:根据拍摄照片,识别图片中动物的名称,可配合其它识图能力对识别的结果进一步细化,提高用户体验,广泛应用于拍照识图类APP中

用于识别一张图片,即对于输入的一张图片(可正常解码,且长宽比较合适),输出动物识别结果。

  • HTTP 方法:
  • 请求 URL:
  • URL参数:
  • Header 参数: =
  • Body 参数:见下表
参数 是否必选 类型 默认值 说明
image string - 图像数据, 编码,要求 编码后大小不超过 4M,最短边至少 ,最长边最大 , 支持 格式 。注意:图片需要 编码、去掉编码头后再进行
top_num integer 6 返回预测得分 top 结果数,默认为 6
baike_num integer 0 返回百科信息的结果数,默认不返回

返回参数如下表:

字段 类型 是否必选 说明
id,用于问题定位
识别结果数组
+ 动物名称,示例:蒙古马
+ 置信度,示例:0.5321
+ 对应识别结果的百科词条名称
++ 对应识别结果百度百科页面链接
++ 对应识别结果百科图片链接
++ 对应识别结果百科内容描述

返回示例如下:

{
"log_id": 7392482912853822863,
"result": [{
"score": "0.993811",
"name": "叉角羚",
"baike_info": {
"baike_url": "http://baike.baidu.com/item/%E5%8F%89%E8%A7%92%E7%BE%9A/801703",
"description": "叉角羚(学名:Antilocapra americana):在角的中部角鞘有向前伸的分枝,故名。体型中等,体长1-1.5米,尾长7.5-10厘米,肩高81-104厘米,成体重36-60千克,雌体比雄体小;背面为红褐色,颈部有黑色鬃毛,腹部和臀部为白色,颊面部和颈部两侧有黑色块斑;毛被下面为绒毛,上覆以粗糙、质脆的长毛,由于某些皮肤肌的作用,能使其毛被呈不同角度,以利于保暖或散热。植食。叉角羚奔跑速度非常快,最高时速达100千米。一次跳跃可达3.5-6米。善游泳。夏季组成小群活动,冬季则集结成上百只的大群。为寻找食物和水源,一年中常进行几次迁移。性机警,视觉敏锐,能看到数千米外的物体。遇险时,臀部的白色毛能立起,向同伴告警。分布于北美洲。"
}
},
{
"score": "0.000289439",
"name": "印度羚"
},
{
"score": "0.000186248",
"name": "藏羚羊"
},
{
"score": "0.000147176",
"name": "跳羚"
},
{
"score": "0.000134434",
"name": "驯鹿"
},
{
"score": "9.86555e-05",
"name": "高鼻羚羊"
}]
}

这里假设已经将环境配置好了,环境配置的文章可以参考 Windows 下使用 Vcpkg 配置百度 AI 图像识别 C++开发环境(VS2017)

为了方便,首先根据返回参数定义了一个结构体,该结构体包括了返回参数中的参数,如下:

struct AnimalInfo {
std::string name;
std::string score;
std::string baikeurl;
std::string imageurl;
std::string baikedesc;

void print() {
std::cout << std::setw(30) << std::setfill('-') << ' ';
std::cout << "name: " << name << " ";
std::cout << "score: " << std::fixed << std::setprecision(4) << std::stof(score) << " ";
if (baikeurl !="null")
std::cout << "baikeurl: " << baikeurl << " ";
if (imageurl !="null")
std::cout << "imageurl: " << imageurl << " ";
if (baikedesc !="null")
std::cout << "baikedesc: " << baikedesc << " ";
}
};

在 结构体中,定义了一个 方法以打印获取的结果。

然后定义了一个类来调用接口并获取结果

class Animal
{
public:
Animal();
~Animal();

Json::Value request(std::string imgBase64, std::map<std::string, std::string>& options);

// get all return results
void getAllResult(std::vector<AnimalInfo>& results);

// only get first result
void getResult(AnimalInfo& result);


private:
Json::Value obj_;
std::string url_;
int top_num_;
// file to save token key
std::string filename_;
};

类中的私有成员 表示返回结果对应的 json 对象。 表示请求的 url, 表示请求参数中对应的 topnum,`filenameaccess token` 的文件的文件名。

函数输入请求图像的 base64 编码以及请求参数,返回一个 json 对象,json 对象中包含请求的结果。

获取请求的结果,总共有 top_num 条结果。

获取 score 最高的一条结果。


完整代码如下

和 代码参见 (简单调用篇 01) 通用物体和场景识别高级版 - C++ 简单调用

代码如下:

#pragma once
#include <string>
#include <map>
#include <curl/curl.h>
#include <json/json.h>
#include <iostream>
#include <vector>
#include <cstdlib>
#include "util.h"

struct AnimalInfo {
std::string name;
std::string score;
std::string baikeurl;
std::string imageurl;
std::string baikedesc;

void print() {
std::cout << std::setw(30) << std::setfill('-') << ' ';
std::cout << "name: " << name << " ";
std::cout << "score: " << std::fixed << std::setprecision(4) << std::stof(score) << " ";
if (baikeurl !="null")
std::cout << "baikeurl: " << baikeurl << " ";
if (imageurl !="null")
std::cout << "imageurl: " << imageurl << " ";
if (baikedesc !="null")
std::cout << "baikedesc: " << baikedesc << " ";
}
};

class Animal
{
public:
Animal();
~Animal();

Json::Value request(std::string imgBase64, std::map<std::string, std::string>& options);

// get all return results
void getAllResult(std::vector<AnimalInfo>& results);

// only get first result
void getResult(AnimalInfo& result);


private:
Json::Value obj_;
std::string url_;
int top_num_;
// file to save token key
std::string filename_;
};

void animalTest();

代码如下:

#include "animal.h"

Animal::Animal()
{
url_="https://aip.baidubce.com/rest/2.0/image-classify/v1/animal";
top_num_=6; // default value
}


Animal::~Animal()
{
}

Json::Value Animal::request(std::string imgBase64, std::map<std::string, std::string>& options)
{
if (!options["top_num"].empty()) {
top_num_=std::stoi(options["top_num"]);
}

std::string response;
Json::Value obj;
std::string token;

// 1. get HTTP post body
std::string body;
mergeHttpPostBody(body, imgBase64, options);

// 2. get HTTP url with access token
std::string url=url_;
getHttpPostUrl(url, filename_, token);

// 3. post request, response store the result
int status_code=httpPostRequest(url, body, response);
if (status_code !=CURLcode::CURLE_OK) {
obj["curl_error_code"]=status_code;
obj_=obj;
return obj; // TODO: maybe should exit
}

// 4. make string to json object
generateJson(response, obj);

// if access token is invalid or expired, we will get a new one
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 Animal::getAllResult(std::vector<AnimalInfo>& results)
{
results.reserve(top_num_);
AnimalInfo tmp;

for (int i=0; i < top_num_; ++i) {
tmp.name=UTF8ToGB(obj_["result"][i]["name"].asString().c_str());
tmp.score=obj_["result"][i]["score"].asString();
tmp.baikeurl=obj_["result"][i]["baike_info"].get("baike_url", "null").asString();
tmp.imageurl=obj_["result"][i]["baike_info"].get("image_url", "null").asString();
tmp.baikedesc=UTF8ToGB(obj_["result"][i]["baike_info"].get("description", "null").asString().c_str());
results.push_back(tmp);
}
}

void Animal::getResult(AnimalInfo & result)
{
result.name=UTF8ToGB(obj_["result"][0]["name"].asString().c_str());
result.score=obj_["result"][0]["score"].asString();
result.baikeurl=obj_["result"][0]["baike_info"].get("baike_url", "null").asString();
result.imageurl=obj_["result"][0]["baike_info"].get("image_url", "none").asString();
result.baikedesc=UTF8ToGB(obj_["result"][0]["baike_info"].get("description", "none").asString().c_str());
}


void animalTest() {
// read image and encode to base64
std::string img_file="https://busyboxs.github.io/blogs/cb803aa6/images/cat.jpg";
std::string out;
readImageFile(img_file.c_str(), out);
std::string img_base64=base64_encode(out.c_str(), (int)out.size());

// set options
std::map<std::string, std::string> options;
options["top_num"]="5";
options["baike_num"]="5";


Json::Value obj;
Animal animalObj;
AnimalInfo result;
obj=animalObj.request(img_base64, options);

animalObj.getResult(result);
result.print();

std::vector<AnimalInfo> results;
animalObj.getAllResult(results);

for (auto & vec : results) {
vec.print();
}
}

代码如下:

#include "util.h"
#include "Animal.h"
#include <stdlib.h>

int main() {
animalTest();

system("pause");
return EXIT_SUCCESS;
}

测试图像

上一篇:苹果相机不让打开访问权限怎么回事

栏    目:PHPCMS

下一篇:4个拍摄方案让你轻松搞定昆虫摄影

本文标题:(简单调用篇 03) 动物识别 - C++ 简单调用

本文地址:http://028ta.com/index.php?m=home&c=View&a=index&aid=347

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:88888888 | 邮箱:88888888@qq.com

Copyright © 2002-2021 傲世皇朝资源教程下载平台 版权所有琼ICP备87456123号

平台注册入口