使用opencv在PC端部署深度神经网络模型

2021-01-26 22:32:29 浏览数 (1)

这篇文章介绍了怎么通过源码编译opencv。其实Opencv在3.3版本之后就加入了深度神经网络模块的支持,可以导入caffe,tensorflow,pytorch等主流框架的模型。

我们大多项目都是在后台或者移动端部署的,这篇介绍下opencv_dnn模块的python和C 的使用,以及在PC端如何部署模型。

Opencv_dnn应用

我的模型是使用tensorflow框架训练的,Opencv导入pb格式的模型,所以首先我们需要把ckpt转为pb。

opencv_dnn使用流程:

  1. 读取图像
  2. dnn.readNetFromTensorflow读取pb模型
  3. dnn.blobFromImage对图像进行resize,减均值等预处理并转为blob
  4. blob作为网络输入
  5. dnn的forward接口进行inference计算
  6. 得到网络输出进行后处理输出最终结果
python版本:

安装opencv-python>3.3,我安装的最新版本4.1

代码语言:javascript复制
pip install opencv-python

直接上代码~

代码语言:javascript复制
# -*- coding: utf-8 -*-
import cv2
import numpy as np
from PIL import Image
#预处理
def preprocessing(file):
    pic = cv2.imread(file)
    return pic
def test_dnn_module():
    """ Function to test OpenCV DNN module. """
    model = './model/test/opencv/seg.pb'
    file = "test.jpg"
    frame = preprocessing(file)
    print("frame", frame.shape)
     #读取pb模型
    net = cv2.dnn.readNetFromTensorflow(model)
     #输入图像img转为blob
    blob = cv2.dnn.blobFromImage(frame, 1.0/255.0, (320,320), swapRB=False, crop=False)
     #blob作为网络输入
    net.setInput(blob)
    #进行inference
    raw_output = net.forward()
    raw_output = np.squeeze(raw_output)
    # print("raw_output",raw_output[:,0,0],raw_output.shape)
    #argmax得到分割结果
    output = np.argmax(raw_output, axis=0)
    #保存分割图
    image = output * 255.0
    images = np.asarray(image, np.uint8)
    im_o = Image.fromarray(images)
    im_o.save("./reslut_opencv.png")
if __name__ == '__main__':
         test_dnn_module()

效果图

C 版本:

我使用的win10系统 VS2017 编译安装Opencv3.3以上版本

VS2017新建工程

配置引用Opencv目录和库,可以看我opencv专栏文章配置

处理流程和上面一样,上代码~

代码语言:javascript复制
#include <iostream> 
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
using namespace dnn;
void get_segResult(cv::Mat output,cv::Mat &result)
{
//NCHW
    const int rows = output.size[2];
    const int cols = output.size[3];
    const int chns = output.size[1];
    result = Mat::zeros(rows, cols, CV_8UC1);
//get label result
    Mat maxVal(rows, cols, CV_32FC1, output.data);
    for (int ch = 0; ch < chns; ch  ) {
        for (int row = 0; row < rows; row  ) {
            const float *ptrout = output.ptr<float>(0, ch, row);
            uint8_t *ptrMaxCl = result.ptr<uint8_t>(row);
            float *ptrMaxVal = maxVal.ptr<float>(row);
            for (int col = 0; col < cols; col  ) {
                if (ptrout[col] > ptrMaxVal[col]) {
                    ptrMaxVal[col] = ptrout[col];
                    ptrMaxCl[col] = (uchar)ch * 255;
                }
            }
        }
    }
}

void infer_image(String win_name,cv::Mat img, cv::dnn::Net net) {
    cv::Scalar mean{ 0, 0, 0 };
    bool swapRB{ false };
    int inputW = 320;
    int inputH = 320;
    //image to blob
    cv::Mat blob = cv::dnn::blobFromImage(img, 1.0 / 255.0, cv::Size(inputW, inputH), mean, swapRB, false);
    //setInput
    net.setInput(blob);
    //infer image
    cv::Mat output = net.forward();
    std::cout << ",output size:" << output.size << std::endl; //[1,3,320,320]
    //求argmax
    cv::Mat result;
    get_segResult(output, result);
    imshow(win_name, img);
    imshow(win_name "_label", result);
}

int main()
{
    String model = "res/seg.pb";
    //读取网络pb
    cv::dnn::Net net = cv::dnn::readNetFromTensorflow(model);
    int backendId = cv::dnn::DNN_BACKEND_OPENCV;
    net.setPreferableBackend(backendId);
    //单张图片infer
    cv::Mat img = cv::imread("E:\resize.jpg");
    infer_image("out",img,net);
    waitKey();
    return 0;
}

C 要注意的问题是cv::Scalar mean{ 0, 0, 0 };一定要定位为scalar结构,不要直接一个数值,不然会导致结果不一致。

0 人点赞