zoukankan      html  css  js  c++  java
  • (简单调用篇 02) 图像主体检测

    图像主体检测能检测出图片主体的坐标位置,可使用该接口裁剪出图像主体区域,配合图像识别接口提升识别精度。广泛适用于美图类 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('-') << '
    ';
    		std::cout << "left: " << left << "
    ";
    		std::cout << "top: " << top << "
    ";
    		std::cout << " " << width << "
    ";
    		std::cout << "height: " << height << "
    ";
    	}
    
    	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.hutil.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('-') << '
    ';
    		std::cout << "left: " << left << "
    ";
    		std::cout << "top: " << top << "
    ";
    		std::cout << " " << width << "
    ";
    		std::cout << "height: " << height << "
    ";
    	}
    
    	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) << "
    ";
    
    	// 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;
    }
    

    运行结果

    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    将十六进制的颜色字符串转为UIColor
    NSXMLParser读取XML文件并将数据显示到TableView上
    TouchJSON的简单使用
    NSJSONSerialization的简单用法
    Android 开发之修改 app 的字体大小(老人模式)
    android sqlite3:数据库操作
    设计模式-观察者模式(Observer Pattern)
    Android 7.0 介绍和适配问题
    Appium的安装和使用
    Android:使用 DownloadManager 进行版本更新,出现 No Activity found to handle Intent 及解决办法
  • 原文地址:https://www.cnblogs.com/busyboxs/p/12245433.html
Copyright © 2011-2022 走看看