Super_Resolution.md 4.79 KB
Newer Older
lijian6's avatar
lijian6 committed
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 超分辨率重建

## 模型简介

图像超分辨率重建技术是指设计并采用某种算法,使得可以通过观测到的低分辨率(Low Resolution, LR)图像重建出近似真实高分辨率(High Resolution , HR)图像的方法。本次部署的超分模型是2016提出的ESPCN网络,主要通过一系列卷积层不断提取图像特征,最后通过sub-pixel亚像素卷积层提高图像分辨率,从而实现图像超分辨率的方法。ESPCN网络结构如下图所示:
![Superresolution_01](../Images/Superresolution_01.png)

本示例采用onnx官方提供的ESPCN模型示例:https://github.com/onnx/models/tree/main/vision/super_resolution/sub_pixel_cnn_2016,将super.onnx文件保存在Resource\Models\Super_Resolution文件夹下。

## 预处理

在将数据输入到模型之前,需要对输入图像做如下预处理操作:

​      1.图像尺寸resize到224x224

​      2.分离图像通道,变为B、G、R三个通道图像;

​      3.BGR格式通过公式转换为YCrCb格式,得到Y、Cb、Cr三通道图像;

​      4.只处理Y通道图像,转换数据排布为NCHW;

本示例代码采用了OpenCV实现预处理操作:

```python
def bgr_to_ycbcr(B, G, R):
    Y = 0.299 * R + 0.587 * G + 0.114 * B
    Cr = (R - Y) * 0.713 + 128
    Cb = (B - Y) * 0.564 + 128
    return Y, Cr, Cb

def Preprocessing(pathOfImage):
    orig_img = cv2.imread(pathOfImage, cv2.IMREAD_COLOR) # cv2.IMREAD_COLOR:彩色图,cv2.IMREAD_GRAYSCALE:灰度图
    img = cv2.resize(orig_img, (224,224))                # 调整图像为固定尺寸224x224
    bImg, gImg, rImg = cv2.split(img)                    # 分离图片
    img_y_0, img_cr, img_cb = bgr_to_ycbcr(bImg, gImg, rImg) # bgr转换为YCbCr
    img_ndarray = np.asarray(img_y_0)                    # 复制img_y_0对象,转换为array([224,224])
    img_y = np.reshape(img_ndarray, (1,1,224,224))       # 改变数组形状,满足模型输入,变为(1,1,224,224) 转换为(N,C,H,W)格式
    img_y = img_y.astype(np.float32) / 255.0             # unit8转换成float32
    return img_y, img_cr, img_cb
```

## 推理

完成图像预处理后,就开始执行推理,得到推理结果。

```python
if __name__ == '__main__':
    # 加载模型
    model = migraphx.parse_onnx("../../Resource/Models/Super/super.onnx")
    inputName = model.get_parameter_names()
    inputShape = model.get_parameter_shapes()
    print("inputName:{0} \ninputShape:{1}".format(inputName, inputShape))

    # 编译模型
    model.compile(t=migraphx.get_target("gpu"), device_id=0)  # device_id: 设置GPU设备,默认为0号设备

    # 图像预处理
    pathOfImage = "../../Resource/Images/cat.jpg"
    img_Y, img_cr, img_cb = Preprocessing(pathOfImage)

    # 模型推理结果
    results = model.run({"input": img_Y})

    # 获取输出节点属性
    result = results[0]                      # 获取第一个输出节点的数据,migraphx.argument类型
    outputShape = result.get_shape()         # 输出节点的shape,migraphx.shape类型
    outputSize = outputShape.lens()          # 每一维大小,维度顺序为(N,C,H,W)
    numberOfOutput = outputShape.elements()  # 输出节点元素的个数

    data = np.array(results[0])[0]
    img_out_y = np.uint8((data * 255.0).clip(0, 255)[0]) # 将浮点型数据转换为0-255之间整型数据
    
    # 将YCbCr格式转换为BGR格式,再将三通道合并到一起,得到重建图像
    img_cr = cv2.resize(img_cr, (672, 672))
    img_cb = cv2.resize(img_cb, (672, 672))
    final_img = ycbcr_to_bgr(img_out_y, img_cr, img_cb)
    cv2.imwrite("output.jpg", final_img)     # 保存超分辨率重建图像的结果
```

 1.Preprocessing函数返回Y、Cr、Cb三通道图像,只将Y通道图像作为输入数据,通过执行model.run({"input": img_Y})得到推理结果,因为只有输入一张图片,所以只通过results[0]获取第一个输出节点的数据即可。
 2.该模型只处理Y通道图像,得到推理结果之后,再通过ycrcb_to_bgr()函数将YCrCb格式转换为BGR格式,转换公式采用的是opencv官方提供的公式,链接:https://docs.opencv.org/3.4.11/de/d25/imgproc_color_conversions.html,最后再将三通道合并到一起,得到最终的重建图像。

## 运行示例

1.参考《MIGraphX教程》中的安装方法安装MIGraphX并设置好PYTHONPATH

2.安装依赖:

```
# 进入migraphx samples工程根目录
cd <path_to_migraphx_samples>

# 进入示例程序目录
cd Python/Super_Resolution

# 安装依赖
pip install -r requirements.txt
```

3.在Python/Super_Resolution目录下执行如下命令运行该示例程序:

```python
# 运行示例
python Espcn.py
```

输出结果如下,左图为原图,右图为重建过后的图像,分辨率提高了三倍。

![Superresolution_03](../Images/Superresolution_03.png)