Opencv在3.3版本之后就加入了深度神经网络模块的支持,可以导入caffe,tensorflow,pytorch等主流框架的模型。
我们以之前大头分割项目的模型为例,介绍下opencv_dnn模块的python和C++的使用,以及在PC端部署。
在PC端对摄像头数据实时分割,最终效果如下图所示:
我们的模型是使用tensorflow框架训练的,Opencv导入pb格式的模型,所以首先我们需要把ckpt转为pb。
Python版本:
安装opencv-python>3.3,我安装的最新版本4.1
opencv_dnn使用流程:
1.读取图像
2.cv2.dnn.readNetFromTensorflow读取pb模型
3.cv2.dnn.blobFromImage对图像进行resize,减均值等预处理并转为blob
4.blob作为网络输入
5.dnn的forward接口进行inference计算
6.得到网络输出进行后处理输出最终结果
上代码:
# -\*- 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()
ofrw1zcemf.jpg
C++版本我使用的win10系统+VS2017+编译安装Opencv3.3以上版本 VS2017新建工程配置引用Opencv目录和库上代码:
// seg\_cv.cpp
//
#include "pch.h"
#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)
{
const int rows = output.size2;
const int cols = output.size3;
const int chns = output.size1;
result = Mat::zeros(rows, cols, CV\_8UC1);
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);
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+"\_2", result);
}
void infer\_capture(cv::dnn::Net net) {
// Create a window
static const std::string kWinName = "Deep learning image classification in OpenCV";
namedWindow(kWinName, WINDOW\_NORMAL);
//! Open a video file or an image file or a camera stream
VideoCapture cap;
cap.open(0);
// Process frames.
Mat frame, blob;
while (waitKey(1) < 0) {
cap >> frame;
if (frame.empty()) {
waitKey();
break;
}
else {
infer\_image(kWinName,frame, net);
}
}
}
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;
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。