OpenVINO 是英特尔开发的一款功能强大的深度学习工具包,可实现跨多个硬件平台的优化神经网络推理。在本文中,我们讨论了 OpenVINO 的特性和优势,以及它如何与领先的计算机视觉平台 Viso Suite 集成,以构建和交付可扩展的应用程序。
OpenVINO 是英特尔开发的跨平台深度学习工具包。该名称代表“开放式视觉推理和神经网络优化”。OpenVINO 专注于通过面向英特尔硬件平台的一次写入、随处部署的方法优化神经网络推理。
该工具包在 Apache License 2.0 版下免费使用,有两个版本:
● OpenVINO 工具包,由开源社区支持
● Intel Distribution of OpenVINO toolkit,由 Intel 支持。
使用 OpenVINO 工具包,软件开发人员可以通过与应用逻辑集成的高级 C++ 推理引擎 API选择模型并部署预训练的深度学习模型(YOLO v3、ResNet 50等)。
因此,OpenVINO 提供集成功能来加快应用程序和解决方案的开发,这些应用程序和解决方案使用计算机视觉、自动语音识别、自然语言处理(NLP)、推荐系统、机器学习等解决多项任务。
2022.3.1 Runtime OpenVINO Archives
版本.C:\Program Files (x86)\Intel
下。openvino-env
(别的根据需求来安装),详细安装步骤可参考: https://docs.openvino.ai/2023.2/openvino_docs_install_guides_installing_openvino_from_archive_windows.htmlpip install -r tools\requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install -r tools\requirements_onnx.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
mo -h
来验证是否安装正确。python export.py --weights ./weights/yolov5s.pt --img 640 --batch 1 --include onnx
# 这里我将归一化参数写入模型中了, 这样前处理可以不用做归一化处理了
# data_type 32: FP32 16: FP16
mo --input_model ./weights/yolov5s.onnx --output_dir ./weights --data_type FP16 --mean_values [0,0,0] --scale_values [255,255,255]
python export.py --weights ./weights/yolov5s.pt --img 640 --batch 1 --include openvino
获取当前支持的所有的AI硬件推理设备, 如果输出没有设备,则可尝试更新显卡驱动. https://www.intel.com/content/www/us/en/support/products/80939/graphics.html
#include <openvino/openvino.hpp>
#include <iostream>
#include <vector>
int main() {
ov::Core ie;
//获取当前支持的所有的AI硬件推理设备
std::vector<std::string> devices = ie.get_available_devices();
for (int i = 0; i < devices.size(); i++) {
std::cout << devices[i] << std::endl;
}
system("pause");
return 0;
}
// ----------------------- output -----------------------
CPU
GNA
GPU
推理
core.set_property(ov::cache_dir("cache"));
#include <opencv2/dnn.hpp>
#include <openvino/openvino.hpp>
#include <opencv2/opencv.hpp>
using namespace std;
const float SCORE_THRESHOLD = 0.2;
const float NMS_THRESHOLD = 0.4;
const float CONFIDENCE_THRESHOLD = 0.4
struct Detection
{
int class_id;
float confidence;
cv::Rect box;
};
struct Resize
{
cv::Mat resized_image;
int dw;
int dh;
};
Resize resize_and_pad(cv::Mat& img, cv::Size new_shape) {
float width = img.cols;
float height = img.rows;
float r = float(new_shape.width / max(width, height));
int new_unpadW = int(round(width * r));
int new_unpadH = int(round(height * r));
Resize resize;
cv::resize(img, resize.resized_image, cv::Size(new_unpadW, new_unpadH), 0, 0, cv::INTER_AREA);
resize.dw = new_shape.width - new_unpadW;
resize.dh = new_shape.height - new_unpadH;
cv::Scalar color = cv::Scalar(100, 100, 100);
cv::copyMakeBorder(resize.resized_image, resize.resized_image, 0, resize.dh, 0, resize.dw, cv::BORDER_CONSTANT, color);
return resize;
}
int main() {
// Step 1. Initialize OpenVINO Runtime core
ov::Core core;
core.set_property(ov::cache_dir("cache"));
// Step 2. Read a model
std::shared_ptr<ov::Model> model = core.read_model("model/yolov5s.xml", "model/yolov5s.bin");
//此处需要自行修改xml和bin的路径
// Step 3. Read input image
// 图像路径
cv::Mat img = cv::imread("images/bus.jpg");
// resize image
Resize res = resize_and_pad(img, cv::Size(640, 640));
// Step 4. Inizialize Preprocessing for the model
ov::preprocess::PrePostProcessor ppp = ov::preprocess::PrePostProcessor(model);
// Specify input image format
ppp.input().tensor().set_element_type(ov::element::u8).set_layout("NHWC").set_color_format(ov::preprocess::ColorFormat::BGR);
// Specify preprocess pipeline to input image without resizing
//ppp.input().preprocess().convert_element_type(ov::element::f32).convert_color(ov::preprocess::ColorFormat::RGB).scale({ 255., 255., 255. });
ppp.input().preprocess().convert_element_type(ov::element::f32).convert_color(ov::preprocess::ColorFormat::RGB);
// Specify model's input layout
ppp.input().model().set_layout("NCHW");
// Specify output results format
ppp.output().tensor().set_element_type(ov::element::f32);
// Embed above steps in the graph
model = ppp.build();
ov::CompiledModel compiled_model = core.compile_model(model, "GPU");
// Step 5. Create tensor from image
float* input_data = (float*)res.resized_image.data;
ov::Tensor input_tensor = ov::Tensor(compiled_model.input().get_element_type(), compiled_model.input().get_shape(), input_data);
// Step 6. Create an infer request for model inference
ov::InferRequest infer_request = compiled_model.create_infer_request();
infer_request.set_input_tensor(input_tensor);
//增加计时器统计推理时间
double start = clock();
infer_request.infer();
double end = clock();
double last = start - end;
cout << "Detect Time" << last << "ms" << endl;
//Step 7. Retrieve inference results
const ov::Tensor& output_tensor = infer_request.get_output_tensor();
ov::Shape output_shape = output_tensor.get_shape();
float* detections = output_tensor.data<float>();
// Step 8. Postprocessing including NMS
std::vector<cv::Rect> boxes;
vector<int> class_ids;
vector<float> confidences;
for (int i = 0; i < output_shape[1]; i++) {
float* detection = &detections[i * output_shape[2]];
float confidence = detection[4];
if (confidence >= CONFIDENCE_THRESHOLD) {
float* classes_scores = &detection[5];
cv::Mat scores(1, output_shape[2] - 5, CV_32FC1, classes_scores);
cv::Point class_id;
double max_class_score;
cv::minMaxLoc(scores, 0, &max_class_score, 0, &class_id);
if (max_class_score > SCORE_THRESHOLD) {
confidences.push_back(confidence);
class_ids.push_back(class_id.x);
float x = detection[0];
float y = detection[1];
float w = detection[2];
float h = detection[3];
float xmin = x - (w / 2);
float ymin = y - (h / 2);
boxes.push_back(cv::Rect(xmin, ymin, w, h));
}
}
}
std::vector<int> nms_result;
cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, nms_result);
std::vector<Detection> output;
for (int i = 0; i < nms_result.size(); i++)
{
Detection result;
int idx = nms_result[i];
result.class_id = class_ids[idx];
result.confidence = confidences[idx];
result.box = boxes[idx];
output.push_back(result);
}
// Step 9. Print results and save Figure with detections
for (int i = 0; i < output.size(); i++)
{
auto detection = output[i];
auto box = detection.box;
auto classId = detection.class_id;
auto confidence = detection.confidence;
float rx = (float)img.cols / (float)(res.resized_image.cols - res.dw);
float ry = (float)img.rows / (float)(res.resized_image.rows - res.dh);
box.x = rx * box.x;
box.y = ry * box.y;
box.width = rx * box.width;
box.height = ry * box.height;
cout << "Bbox" << i + 1 << ": Class: " << classId << " "
<< "Confidence: " << confidence << " Scaled coords: [ "
<< "cx: " << (float)(box.x + (box.width / 2)) / img.cols << ", "
<< "cy: " << (float)(box.y + (box.height / 2)) / img.rows << ", "
<< "w: " << (float)box.width / img.cols << ", "
<< "h: " << (float)box.height / img.rows << " ]" << endl;
float xmax = box.x + box.width;
float ymax = box.y + box.height;
cv::rectangle(img, cv::Point(box.x, box.y), cv::Point(xmax, ymax), cv::Scalar(0, 255, 0), 3);
cv::rectangle(img, cv::Point(box.x, box.y - 20), cv::Point(xmax, box.y), cv::Scalar(0, 255, 0), cv::FILLED);
cv::putText(img, std::to_string(classId), cv::Point(box.x, box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
}
//显示具体结果
cv::namedWindow("ImageWindow", cv::WINDOW_NORMAL);
cv::resizeWindow("ImageWindow", 800, 600);
cv::imshow("ImageWindow", img);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
输出结果