0%

c++测试文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//#include <torch/script.h>
#include <torch/extension.h>
#include <vector>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;
using namespace std;

torch::Tensor extend_gray(torch::Tensor image, torch::Tensor warp) {
// BEGIN image_mat
cv::Mat image_mat(/*rows=*/image.size(0),
/*cols=*/image.size(1),
/*type=*/CV_32FC1,
/*data=*/image.data_ptr<float>());
// END image_mat

// BEGIN warp_mat
cv::Mat warp_mat(/*rows=*/warp.size(0),
/*cols=*/warp.size(1),
/*type=*/CV_32FC1,
/*data=*/warp.data_ptr<float>());
// END warp_mat

// BEGIN output_mat
cv::Mat output_mat;
cv::warpPerspective(image_mat, output_mat, warp_mat, /*dsize=*/{8, 8});
// END output_mat

// BEGIN output_tensor
torch::Tensor output = torch::from_blob(output_mat.ptr<float>(), /*sizes=*/{8, 8});
return output.clone();
// END output_tensor
}

// pybind11 绑定
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.def("extend_gray", &extend_gray, "extend gray");
}

同目录下的 setup.py文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from setuptools import setup
import os
import glob
from torch.utils.cpp_extension import BuildExtension, CppExtension

# 头文件目录
include_dirs = os.path.dirname(os.path.abspath(__file__)) ## 头文件路径
# 源代码目录
source_cpu = glob.glob(os.path.join(include_dirs, '*.cpp')) ## cpp文件列表 ['', '']

setup(
name='extend_gray', # 模块名称,需要在python中调用
version="0.1",
ext_modules=[
CppExtension('extend_gray',
sources=source_cpu,
library_dirs=['/usr/local/lib'], # '/usr/local/lib'为opencv的动态库路径 -L/usr/...
include_dirs=[include_dirs, '/usr/local/include/opencv', '/usr/local/include'], ## 头文件路径后两个为 opencv的
libraries=["opencv_core", "opencv_imgproc", "opencv_imgcodecs", "opencv_highgui"]),
## 相当于g++ 编译的 -lopencv_core 一定要写全, 否则不写全编译不会报错但是运行会出错,必要时可以直接g++编译测试看用到哪些动态库
],
cmdclass={
'build_ext': BuildExtension.with_options(no_python_abi_suffix=True)
}
)

测试文件

1
2
3
4
import extend_gray
import torch

print(extend_gray.extend_gray(torch.randn(32, 32), torch.rand(3, 3)))

​ 遇到提示 .so 库找不到 使用 find 命令在环境中搜,然后 添加到 LD_LIBRARY_PATH 变量中 写入 .bashrc 文件后面

pytorch&python

python * ** 的用法

1566285511946

用在函数的输入参数

​ 在定义一个方法时,使用*表示输入参数列表不确定。会将输入的参数放入一个元组中,函数内可通过访问元组的方法访问里面的数据。使用**arg也可以表示不确定参数列表,但是会将输入参数打包为字典结构。因此函数内部可以通过访问字典结构的方法访问输入参数

1
2
3
4
5
6
7
8
def myprint(*arg)
print arg
myprint(1,2,3,4)
#打印的结果是一个元组

def myprint(*arg)
for i in range(len(arg))
#输出1,2,3,4
1
2
3
4
def myprint(**arg)
print(arg)
myprint(a=1,b=2,c=3)
#打印结果:{'a':1, 'b':2, 'c':3}

解包

​ 与上述过程相反

1
2
3
4
5
6
7
8
9
def addxy):
print x+y
para = (1,2)
add(*para)

def add(x,y):
print x+y
kkwd = {'x' :1,'y':2}
add(**kkwd)

值传递,引用传递 ,可变对象,不可变对象

一般来说,将数字、字符串、元组是不可变对象,传入函数,相当于对内存进行了拷贝,在函数内修改其值不会改变函数外的值。但是对于列表、字典等可以增删的数据结构,传入函数后,相当于传递进去的是c语言中的指向地址的指针。所以在函数内对其进行有关地址的操作都可以修改函数外的变量的值。

参考链接:https://blog.csdn.net/qq_41987033/article/details/81675514

使用tensorboard数据可视化

安装

​ 对于pytorch1.0 torch.utils.tensorboard中有这个文件,但是直接在程序中导入会报错,不考虑这个,自行安装tensorboardX。 需要安装tensorboardX为python代码执行,实现pytorch到tensorflow的转化生成一个日志文件,还需要安装tensorflow,才能调用tensorboard命令解析日志文件并上传到浏览器

1
2
pip install tensorboardX
pip install tensorflow #安装的gpu版本

简单使用

​ 在程序调用一下api确保生成日志文件

1
2
3
writer = SummaryWriter('runs/fashion_mnist_experiment_1')  
writer.add_image('four_fashion_mnist_images', img_grid)
writer.close() #必须有close 否则内容写不进去

​ 在系统命令行输入以下命令

1
tensorboard --logdir runs  

​ 上述的runs为刚才在py中生成日志文件的路径,得确保该路径下存放得有生成得日志文件 ​ 输入上述命令后,会产生如下输出,在google浏览器打开http://DESKTOP-F3BBIIO:6006 如果浏览被拒,改为 http://localhost:6006。如果是本机电脑链接远程服务器,则将服务器名字改为服务器的ip地址

pytorch的用法

pytorch踩坑

  • load模型时,他会自动将其加载在这个模型训练时所在的gpu上 此时若这个gpu刚好满了就不能加载。所以最好每次加自增加 map_location='cpu' 参数 load完毕后再to到需要的gpu上

cat stack unqueeze用法总结

​ 相同: cat, stack 输入都为 1. tensor列表,2.另一个参数是维度 (n为输入tensor的维度数)

  • cat : 将输入的tensor按照指定维度连接, 不要求输入的尺寸完全相同。dim的范围为 0~n-1 按照b, c, h, w的顺序对应dim从小到大。例如输入为二维矩阵,dim=0/1 =0表示在 h 维度拼接,即输出矩阵的行数为输入之和。
  • stack: 将输入tensor增加维度堆叠,要求输入的尺寸完全相同。dim范围0~n 也是按照bchw的顺序对应dim。输出的tensor dim=n+1。对于输二维矩阵,dim=0,在c维度堆叠;dim=1,提取每个输入的行向量按行堆叠构成输出的一个通道,输入矩阵有多少行就有多少通道;dim=2,提取每个输入的行向量按列堆叠构成输出的一个通道,输入矩阵有多少行就有多少通道。对于输入三维张量,同理。

双噪声相似度的变分去噪

变分去噪(TV)

假设图像的成像模型为加性噪声,变分去噪模型包含两项,一项是数据保真项,一项是图像的全变分,即图像的梯度。两项都是无约束凸优化问题。由于噪声区域通常都是梯度异常的区域,因此TV项用在去噪中的作用就是保持图像的光滑性,但是也会对图像的细节丢失。

非局部均值滤波 (NLM)

相对对传统邻域滤波方法的一种改进滤波,考虑到了图像的自相似性质,它充分利用了图像中的冗余信息,在去噪的同时能够最大程度的保持图像的细节特征。

非局部变分去噪(NLTV)

借鉴了 非局部 均值滤波中的思想,原始的 变分损失就是度量的当前像素和领域像素的差值,即梯度,作为约束,期望平滑。在非局部变分损失中,将梯度重新定义为其领域一个像素与当前像素之间的差值,权重为以二者像素中心的patch之间的相似度。然后使用 split Bregman算法来求解非局部TV模型

双噪声相似性的非局部变分去噪

在NLTV去噪算法中,度量像素之间的相似性是根据初始噪声图像计算的,没有考虑到算法迭代过程中像素之间的相似性,由于在迭代过程中,像素之间的相似性可能会改变,若一直利用初始噪声的相似权重可能会不准确。因此在计算像素之间的相似性时同时利用初始噪声图像的相似性和迭代过程中像素之间的相似性来计算,以增强度量像素相似性的准确性。

总的来说,就是每次迭代求解过程中 都更新一下权重矩阵,原始的非局部变分损失中的 权重 计算的是原始噪声图像的各个patch之间的相似性,双噪声相似性算法中 在权重中额外添加了一个 当前迭代结果的像素间的相似性作为参考。

image-20210607111125324