前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用opencv在PC端部署深度神经网络模型

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

作者头像
languageX
发布2021-01-26 22:32:29
1.4K0
发布2021-01-26 22:32:29
举报
文章被收录于专栏:计算机视觉CV

这篇文章介绍了怎么通过源码编译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结构,不要直接一个数值,不然会导致结果不一致。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/11/09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Opencv_dnn应用
    • opencv_dnn使用流程:
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档