圖像主體檢測能檢測出圖片主體的座標位置,可使用該接口裁剪出圖像主體區域,配合圖像識別接口提升識別精度。廣泛適用於美圖類 app、輔助智能識圖等業務場景中。
應用場景
- 智能美圖:根據用戶上傳照片進行主體檢測,實現圖像裁剪或背景虛化等功能,可應用於含美圖功能 app 等業務場景中
- 圖像識別輔助:可使用圖像主體檢測裁剪出圖像主體區域,配合圖像識別接口提升識別精度
接口描述
用戶向服務請求檢測圖像中的主體位置。
請求說明
- HTTP 方法:
POST
- 請求 URL:
https://aip.baidubce.com/rest/2.0/image-classify/v1/object_detect
- URL參數:
access_token
- Header 參數:
Content-Type
=application/x-www-form-urlencoded
- Body 參數:見下表
參數 | 是否必選 | 類型 | 可選值範圍 | 說明 |
---|---|---|---|---|
image | true | string | - | 圖像數據,base64 編碼,要求 base64 編碼後大小不超過 4M,最短邊至少 15px ,最長邊最大 4096px ,支持 jpg/png/bmp 格式 。注意:圖片需要 base64 編碼、去掉編碼頭後再進行 urlencode |
with_face | false | number | - | 如果檢測主體是人,主體區域是否帶上人臉部分,0 - 不帶人臉區域,其他 - 帶人臉區域,裁剪類需求推薦帶人臉,檢索/識別類需求推薦不帶人臉。默認取 1 ,帶人臉 |
返回說明
返回參數如下表:
字段 | 是否必選 | 類型 | 說明 |
---|---|---|---|
log_id |
是 | uint64 |
唯一的 log id,用於問題定位 |
result |
否 | watermark-location |
裁剪結果 |
+left |
否 | uint32 |
表示定位位置的長方形左上頂點的水平座標 |
+top |
否 | uint32 |
表示定位位置的長方形左上頂點的垂直座標 |
+width |
否 | uint32 |
表示定位位置的長方形的寬度 |
+height |
否 | uint32 |
表示定位位置的長方形的高度 |
返回示例如下:
{
"log_id": 895582300,
"result": {
"width": 486,
"top": 76,
"left": 134,
"height": 394
}
}
C++ 代碼實現調用
這裏假設已經將環境配置好了,環境配置的文章可以參考 Windows 下使用 Vcpkg 配置百度 AI 圖像識別 C++開發環境(VS2017)。
爲了方便,首先根據返回參數定義了一個結構體,該結構體包括了返回參數中的參數,如下:
struct ObjDetInfo {
uint32_t left;
uint32_t top;
uint32_t width;
uint32_t height;
void print() {
std::cout << std::setw(20) << std::setfill('-') << '\n';
std::cout << "left: " << left << "\n";
std::cout << "top: " << top << "\n";
std::cout << "width: " << width << "\n";
std::cout << "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);
}
};
在 ObjInfo
結構體中,定義了一個 print
方法以打印獲取的結果,draw
方法以在圖像上畫出邊框。
然後定義了一個類來調用接口並獲取結果
class ObjectDetection
{
public:
ObjectDetection();
~ObjectDetection();
Json::Value request(std::string imgBase64, std::map<std::string, std::string>& options);
// only get first result
void getResult(ObjDetInfo& result);
private:
Json::Value obj_;
std::string url_;
// file to save token key
std::string filename_;
};
類中的私有成員 obj_
表示返回結果對應的 json 對象。url_
表示請求的 url,filename_
表示用於存儲 access token
的文件的文件名。
request
函數輸入請求圖像的 base64 編碼以及請求參數,返回一個 json 對象,json 對象中包含請求的結果。
getResult
獲取請求的結果。
完整代碼如下
util.h
和 util.cpp
代碼參見 (簡單調用篇 01) 通用物體和場景識別高級版 - C++ 簡單調用
ObjectDetection.h
代碼如下:
#pragma once
#include <string>
#include <iostream>
#include <opencv2/opencv.hpp>
#include "util.h"
struct ObjDetInfo {
uint32_t left;
uint32_t top;
uint32_t width;
uint32_t height;
void print() {
std::cout << std::setw(20) << std::setfill('-') << '\n';
std::cout << "left: " << left << "\n";
std::cout << "top: " << top << "\n";
std::cout << "width: " << width << "\n";
std::cout << "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);
}
};
class ObjectDetection
{
public:
ObjectDetection();
~ObjectDetection();
Json::Value request(std::string imgBase64, std::map<std::string, std::string>& options);
// only get first result
void getResult(ObjDetInfo& result);
private:
Json::Value obj_;
std::string url_;
// file to save token key
std::string filename_;
};
void objectDetectionTest();
ObjectDetection.cpp
代碼如下:
#include "ObjectDetection.h"
ObjectDetection::ObjectDetection()
{
filename_ = "tokenKey";
url_ = "https://aip.baidubce.com/rest/2.0/image-classify/v1/object_detect";
}
ObjectDetection::~ObjectDetection()
{
}
Json::Value ObjectDetection::request(std::string imgBase64, std::map<std::string, std::string>& options)
{
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 ObjectDetection::getResult(ObjDetInfo & result)
{
result.left = obj_["result"].get("left", "0").asInt();
result.top = obj_["result"].get("top", "0").asInt();
result.width = obj_["result"].get("width", "0").asInt();
result.height = obj_["result"].get("height", "0").asInt();
}
void objectDetectionTest()
{
std::cout << "size: " << sizeof(ObjDetInfo) << "\n";
// read image and encode to base64
std::string img_file = "./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["with_face"] = "0";
Json::Value obj;
ObjectDetection objDetObj;
obj = objDetObj.request(img_base64, options);
//std::cout << (obj.get("result", "null")) << std::endl;
ObjDetInfo result;
objDetObj.getResult(result);
result.print();
cv::Mat img = cv::imread(img_file);
result.draw(img);
cv::namedWindow("Object Detection", cv::WINDOW_NORMAL);
cv::imshow("Object Detection", img);
cv::waitKey();
}
main.cpp
代碼如下:
#include "util.h"
#include "ObjectDetection.h"
#include <stdlib.h>
int main() {
objectDetectionTest();
system("pause");
return EXIT_SUCCESS;
}