Opencv中使用cuda进行 dft 与 idft滤波运算

opencv源代码中包含了dft的demo,但没有使用cuda的demo。下文会简单给出一个cuda例程,并进行简单的高频滤波。

为方便说明,将程序分成了若干部分
1.头文件

#include <iostream>

#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core/cuda.hpp>
#include <opencv2/cudaarithm.hpp>

using namespace cv;

2.导入图片加载到GPU,为简单使用了单色图

继续阅读

opencv 中使用 cudnn 预测CNN网络

opencv从3版本开始就已经支持CNN网络模型的预测,到4版本,主流工具tensorflow,pytorch 生成的模型文件大部分都可以支持。但其一直没有使用到CUDNN。但最新发布的4.2版本的opencv已经支持CUDNN了。以下是功能测试

一。安装编译环境

CUDNN的安装方法可以参考tensorflow中关于cudnn的安装方法https://www.tensorflow.org/install/gpu 接下来也会使用tensorflow作为例子。

二。编译opencv

编译方法参考链接https://docs.opencv.org/4.2.0/d3/d52/tutorial_windows_install.html 其中为了加入CUDNN的支持,有以下需要设置一下

1.勾选cuda和cudnn

2.设置CUDA_ARCH_BIN
cudnn不支持3.5下的显卡。需要根据自己使用的显卡来设置,列表参考https://developer.nvidia.com/cuda-gpus

3.代码bug修正
由于我使用的是vs2015,版本低了点。导致编译时会出错。github上已经修复了这个bug,估计会在下一个版本发布。所以低版本vs编译时 需要手动修改一下

文件 modules/dnn/src/cuda/grid_stride_range.hpp

namespace detail {
    template <int>  __device__ auto getGridDim()>decltype(dim3::x);
    template <> inline __device__ auto getGridDim<0>()>decltype(dim3::x) { return gridDim.x; }
    template <> inline __device__ auto getGridDim<1>()>decltype(dim3::x) { return gridDim.y; }
    template <> inline __device__ auto getGridDim<2>()>decltype(dim3::x) { return gridDim.z; }

    template <int> __device__ auto getBlockDim()>decltype(dim3::x);
    template <> inline __device__ auto getBlockDim<0>()>decltype(dim3::x) { return blockDim.x; }
    template <> inline __device__ auto getBlockDim<1>()>decltype(dim3::x) { return blockDim.y; }
    template <> inline __device__ auto getBlockDim<2>()>decltype(dim3::x) { return blockDim.z; }

    template <int> __device__ auto getBlockIdx()>decltype(uint3::x);
    template <> inline __device__ auto getBlockIdx<0>()>decltype(uint3::x) { return blockIdx.x; }
    template <> inline __device__ auto getBlockIdx<1>()>decltype(uint3::x) { return blockIdx.y; }
    template <> inline __device__ auto getBlockIdx<2>()>decltype(uint3::x) { return blockIdx.z; }

    template <int> __device__ auto getThreadIdx()>decltype(uint3::x);
    template <> inline __device__ auto getThreadIdx<0>()>decltype(uint3::x) { return threadIdx.x; }
    template <> inline __device__ auto getThreadIdx<1>()>decltype(uint3::x) { return threadIdx.y; }
    template <> inline __device__ auto getThreadIdx<2>()>decltype(uint3::x) { return threadIdx.z; }
}

替换为

namespace detail {
    using dim3_member_type = decltype(dim3::x);

    template <int>  __device__ dim3_member_type getGridDim();
    template <> inline __device__ dim3_member_type getGridDim<0>() { return gridDim.x; }
    template <> inline __device__ dim3_member_type getGridDim<1>() { return gridDim.y; }
    template <> inline __device__ dim3_member_type getGridDim<2>() { return gridDim.z; }

    template <int> __device__ dim3_member_type getBlockDim();
    template <> inline __device__ dim3_member_type getBlockDim<0>() { return blockDim.x; }
    template <> inline __device__ dim3_member_type getBlockDim<1>() { return blockDim.y; }
    template <> inline __device__ dim3_member_type getBlockDim<2>() { return blockDim.z; }

    using uint3_member_type = decltype(uint3::x);

    template <int> __device__ uint3_member_type getBlockIdx();
    template <> inline __device__ uint3_member_type getBlockIdx<0>() { return blockIdx.x; }
    template <> inline __device__ uint3_member_type getBlockIdx<1>() { return blockIdx.y; }
    template <> inline __device__ uint3_member_type getBlockIdx<2>() { return blockIdx.z; }

    template <int> __device__ uint3_member_type getThreadIdx();
    template <> inline __device__ uint3_member_type getThreadIdx<0>() { return threadIdx.x; }
    template <> inline __device__ uint3_member_type getThreadIdx<1>() { return threadIdx.y; }
    template <> inline __device__ uint3_member_type getThreadIdx<2>() { return threadIdx.z; }
}

文件 modules/dnn/src/cuda4dnn/csl/cudnn/cudnn.hpp

    template <class> auto get_data_type()->decltype(CUDNN_DATA_FLOAT);
    template <> inline auto get_data_type<half>()->decltype(CUDNN_DATA_HALF) { return CUDNN_DATA_HALF; }
    template <> inline auto get_data_type<float>()->decltype(CUDNN_DATA_FLOAT) { return CUDNN_DATA_FLOAT; }

替换为

    using cudnn_data_enum_type = decltype(CUDNN_DATA_FLOAT);
    template <class> cudnn_data_enum_type get_data_type();
    template <> inline cudnn_data_enum_type get_data_type<half>() { return CUDNN_DATA_HALF; }
    template <> inline cudnn_data_enum_type get_data_type<float>() { return CUDNN_DATA_FLOAT; }

修改完成后正常编译就可以了

三。使用

设置为使用cudnn非常简单,只需要在原来的基础上添加两行代码。

net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); 
net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); 

具体opencv怎么使用模型文件可以参考博客之前的文章https://www.yangyouji.info/archives/349

C# 中使用 OpencvSharp 与 TensorflowSharp 进行Mask-RCNN模型的预测

网上可以找到许多TensorFlow的Mask-RCNN版本,现以github上一个Star较多的版本为例,介绍如何在C#中部署Mask-RCNN模型

一.前期准备

1.同步Mask-RCNN的代码,地址为 https://github.com/matterport/Mask_RCNN.git

2.训练模型:
可以使用jupyter打开samples文件夹下的例子进行训练,也可以参考其例子训练自己的模型。目标是生存保存好权重的模型文件。模型每训练一个epochs 会在 model_dir=MODEL_DIR 设置好的文件夹下留下模型文件。具体训练方法就不累述了~~~

3.在VS里使用Nuget,给项目添加OpencvSharp 与 TensorflowSharp

继续阅读

TensorFlowSharp GPU 显存 分配

TensorFlow 运行时默认会最大化使用显存,如果需要控制其显存的分配,可以进行相应的设定。相关设定大多是在python或c++的运行环境下设置的,c#环境下的设置方法可以如下文。主要使用了 options.SetConfig(InPtr protoData,int length)

1.通过python获取protoData
protoData 是一串二进制流,但c#中没有找到生成这个二进制流的方法,所以只好通过python生成,代码如下

import tensorflow as tf

config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.3 最大使用30%的显存

bytes = config.SerializeToString()
hexstring = " ".join("%02d" % b for b in bytes)
print(hexstring)

输出为 50 09 09 51 51 51 51 51 51 211 63

2.TensorFlowSharp 中导入二进制流

TFSessionOptions options = new TFSessionOptions();
byte[] data = { 50, 9, 9, 51, 51, 51, 51, 51, 51, 211, 63 }; //0.3
 
IntPtr buffer = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(data, 0, buffer, data.Length);
TFStatus ts = new TFStatus();
options.SetConfig(buffer, data.Length, ts);
Marshal.FreeHGlobal(buffer);
 
TFSession session = new TFSession(graph, options);

这样实例化出来的session 就会限制在30%显存运行。如果需要其他设置,只需要在python中获取到相应的二进制流,然后在c#中设置一下就可以了

tensorflowsharp中使用CUDA

tensorflowsharp使用C#封装了tensorflow的c-api接口,可以方便的在C#中使用tensorflow的模型。但作者只提供了cpu版本的tensorflow,如果要使用gpu版本的tensorflow,就需要自己编译出一个带CUDA的dll。好在网上资料比较多,编译起来并不是很困难

一.编译环境搭建

windows下搭建tensorflow编译环境可以参考官网上的教程,写得很详细,按照上面一步步操作就可以了。链接https://www.tensorflow.org/install/source_windows

继续阅读

OpencvSharp 中使用 cuda

opencvsharp 是 opencv的c#版本,近期有项目使用了opencvsharp来进行图像处理。这个github上星级很高的项目果然是不错的,运行起来比较稳定,没有出现大的问题。但opencvsharp中没有cuda的完整支持,只有最基本的类型支持,无任何算法支持,想用就只能靠自己添加了。作者的解释如下:

大概就是说cuda需要用户自己编译opencv ,没有一个统一版本的dll提供使用,所以就删除了cuda的支持
其实也对,cuda的使用涉及cuda版本,使用的显卡算力等。使用c++版本的opencv时,也是要自己编译的。
但c#上使用就没有办法了吗?还好作者已经打好了基础,提供了GpuMat的支持,并有大量cup版本的函数进行参考。添加起来还是比较容易的。
项目目录 https://github.com/shimat/opencvsharp

继续阅读

TensorFlow与消息队列–服务器

消息队列(Message Queue,简称 MQ),可以将一些费时的任务放入队列,慢慢处理,改善客户端的体验。与TensorFlow服务结合,可以调高服务器的计算能力,将费时的数据传输与相对较快的预测计算分开来

一.数据流图

说明:
应用场景是收集客户端中的图片,进行分类处理,结果保留到服务器与数据库。客户端不需要实时知道图片的分类结果。如果客户端要知道实时结果,就不能这样设计。
该设计主要解决了2个问题,第一 加快了客户端上传图片的速度;第二 将图像预测的工作分离了出来,单独在GPU上运行,实现最大的效率。
详细流程:
1.客户端将图片通过HTTP协议post到“生产者”
2.“生产者”将收到的图片与其他信息打包发个消息队列
3.“消费者”拿到消息后,先解包,再进行图片预处理,随后将图片张量(数值)发个tensorflow搭建的服务进行分类。
4“消费者”收到结果后,保存结果数据。

继续阅读

opencv + tensorflow + C++ 对RSNet模型进行预测

本文介绍了一种使用opencv + c++ 可以在生产环境下调用tensorflow pb文件进行预测的方法。
该方法不需要在生产环境下搭建python运行环境。 流程上相对简单清晰。如果要将神经网络/机器学习添加到几年前项目中,也比较简单可行。

一.pb文件的生成

本人使用的RsNet模型完全参考github上官方给出的demo训练生成。网址https://github.com/tensorflow/models
训练入口文件official/resnet/imagenet_main.py (主线版本 v1.8.1)
只定义了2个分类,具体的训练方法就不再累

训练完成后会在根目录生成一个imagenet_model文件夹,里面存储了模型文件(ckpt文件)。接下来需要将模型文件固化成pb文件。为了让opencv可以使用这个pb文件,需要定义好神经网络input入口与output出口

继续阅读

Centos7 + Flask + uwsgi + nginx 部署 TensorFlow

本文介绍了一个采用Flask + uwsgi + nginx 部署TensorFlow应用的方法。以此可以搭建一个简单的机器学习云服务器

一. 创建虚拟环境

由于本人安装的电脑带有显卡,所以安装了2个版本的tensorflow,一个带gpu,一个不带gpu。不同版本的tensorflow使用虚拟环境进行分割

pip install virtualenv
mkdir tf_gpu
virtualenv tf_gpu –system-site-packages
mkdir tf_cpu
virtualenv tf_cpu –system-site-packages
注:添加 –system-site-packages 是将系统site-packages里的包 包含进去; 虚拟目录的位置按需设

二.tensorflow安装

tensorflow的安装可以参考官网上的连接通过pip安装或者自己编译

https://www.tensorflow.org/install/pip 或 https://www.tensorflow.org/install/source

继续阅读

windows下编译tensorflow c++ library及与opencv的使用

tensorflow在1.3后加入了官方的windows支持,可以使用cmake在vs2015下编译c++ library。但坑还是很多,简单整理了1.3版本编译及使用过程。并介绍了编译部分kernel的方法。其他版本也可参考进行编译。

编译版本为1.3,只cpu。带gpu的tensorflow可以用1.5以后的版本。

编译前准备

组件下载或安装

1.CMake version 3.5以上

2.git (http://git-scm.com)

3.swig (http://www.swig.org/download.html)

4.Visual Studio 2015

5.Python 3.5 64-bit (选择添加安装lib文件)

6.NumPy 1.11.0 以上

注意事项:CMake 与 git安装时需要将其加入到环境变量中,否则后续编译过程中会出现找不到相关程序的错误

编译过程

1.设置vs使用64位的编译工具(否者有一定概率报out-of-memory的错误)

继续阅读