将电脑上的已有项目迁移到AidLux平台,并加入到examples-gpu
案例中,实现可视化一键运行,避免了重复的命令行操作。
下面用一个图像去噪(Image Denoising)的示例作为演示:
1. 第一步:将项目文件拷贝到手机上
打开AidLux上的Cloud_ip
,可以看到其ip地址,在电脑上的浏览器里输入此网址远程访问Aid桌面。选择文件图标, 在/sdcard
目录下新建文件夹,将项目放到该路径下。项目也可放到任意指定路径下,笔者这里推荐/sdcard
,避免重装AidLux示例被重置。
2. 第二步:调试代码
打开终端,试运行代码,看是否缺失必要的依赖库和包,可在应用中心直接下载,也可通过aid install
命令进行安装。
下面对denoise_img.py
代码做简略说明:
import cv2 import torchvision import numpy as np import torch
from UNet import UNet # UNet.py文件定义模型架构
使用opencv读取图像
img_cv = cv2.imread(‘./noise_img/test4.jpg’) # np.array, (H x W x C), [0, 255], BGR
print(img_cv.shape)加载模型路径
checkpoint = torch.load(‘./checkpoints/chk_2_1_0.5.pt’, map_location=torch.device(‘cpu’))
model_test = UNet(in_channels=3, out_channels=3).double()
model_test.load_state_dict(checkpoint[‘model_state_dict’])
model_test = model_test.cpu()将图像数据处成模型输入需要的格式
torch.set_default_tensor_type(torch.DoubleTensor)
tensor_cv = torch.from_numpy(np.transpose(img_cv, (2, 0, 1))) # (C x H x W)
tensor_cv = tensor_cv.unsqueeze(0)
tensor_cv = tensor_cv / 127.5 - 1 # range: [-1, 1]print(tensor_cv.shape, tensor_cv)
denoise_img = torchvision.utils.make_grid(model_test(tensor_cv)) # 运行模型
print(denoise_img.shape)保存图片降噪结果
cv2.imwrite(‘cv_img.jpg’, np.transpose(denoise_img.detach().numpy().astype(np.uint8), (1, 2, 0)))
print(‘Save denoising image successfully!’)
3. 第三步:编写可视化界面
上边是常见模型推断演示的一般过程,不过将待处理的图片直接写死了,每次替换图片都需要修改代码,过于繁琐。下边写一个简单的界面,通过可视化窗口手动选择图片,执行代码。
import PIL.Image as Image import base64 import remi.gui as gui from urllib.request import urlopen from remi import start, App from threading import Timer
import cv2
import torchvision
import numpy as np
import torchimport android
droid = android.Android()from UNet import UNet
try:
import socketiosio = socketio.Client() sio.connect('ws://0.0.0.0:9909') socket_connection = True
except:
socket_connection = Falsedef base64_to_style_image(base64_image):
return ‘data:image/png;base64,’+base64_imageclass MyApp(App):
def init(self, *args):
super(MyApp, self).init(*args)def main(self): # 定义窗体 verticalContainer = gui.Container(width=404, height=700, style={'display': 'block', 'overflow': 'hidden','text-align': 'center'}) # 窗口1 self.img_lr = gui.Image('', width=256,height=256,margin='1px') verticalContainer.append(self.img_lr) # 控件1 self.btFileDiag = gui.Button('Select Image', width='100%', height=30, margin='0px') self.btFileDiag.onclick.do(self.open_fileselection_dialog) verticalContainer.append(self.btFileDiag) # 窗口2 self.img_hr = gui.Image('',width=256, height=256, margin='1px') verticalContainer.append(self.img_hr) # 控件2,注意退出程序需要点此处 self.btClose = gui.Button('Exit', width=404, height=30, margin='0px') self.btClose.onclick.do(self.server_close) verticalContainer.append(self.btClose) return verticalContainer def open_fileselection_dialog(self, widget): print('open_fileselection_dialog') self.fileselectionDialog = gui.FileSelectionDialog('File Selection Dialog', 'Select files and folders', False,'.') self.fileselectionDialog.confirm_value.do( self.on_fileselection_dialog_confirm) # here is returned the Input Dialog widget, and it will be shown self.fileselectionDialog.show(self) def on_fileselection_dialog_confirm(self, widget, filelist): print('filelist', filelist) if (len(filelist) > 0): file_name = filelist[0] with open(filelist[0], "rb") as f: lr, hr = self.imageDemo(file_name) print(lr.shape, hr.shape) lr = cv2.imencode('.jpg',lr)[1] hr = cv2.imencode('.jpg',hr)[1] bs64_str_lr = str(base64.b64encode(lr))[2:-1] bs64_str_hr = str(base64.b64encode(hr))[2:-1] if not isinstance(bs64_str_lr, str): bs64_str_lr = bs64_str_lr.decode() if not isinstance(bs64_str_hr, str): bs64_str_hr = bs64_str_hr.decode() self.img_lr.set_image(base64_to_style_image(bs64_str_lr)) self.img_hr.set_image(base64_to_style_image(bs64_str_hr)) def imageDemo(self, image_path): # 使用opencv读取图像 img = cv2.imread(image_path) # np.array, (H x W x C), [0, 255], BGR # img = cv2.resize(img, (256, 256)) checkpoint = torch.load('./checkpoints/chk_2_1_0.5.pt', map_location=torch.device('cpu')) model_test = UNet(in_channels=3, out_channels=3).double() model_test.load_state_dict(checkpoint['model_state_dict']) model_test = model_test.cpu() torch.set_default_tensor_type(torch.DoubleTensor) tensor_cv = torch.from_numpy(np.transpose(img, (2, 0, 1))) # (C x H x W) tensor_cv = tensor_cv.unsqueeze(0) tensor_cv = tensor_cv / 127.5 - 1 # range: [-1, 1] # print(tensor_cv.shape, tensor_cv) denoise_img = torchvision.utils.make_grid(model_test(tensor_cv)) print('----denoise shape:', denoise_img.shape, type(denoise_img)) pred = (denoise_img + 1) * 127.5 # unnormalize [0, 255] pred = pred.detach().numpy() pred = np.transpose(pred, (1, 2, 0)) pred = pred.astype(np.uint8) print('----pred shape:', pred.shape) # cv2.imwrite('res_test.jpg', pred) return img, pred def server_close(self, widget): pname = 'image_denoising.py' urlopen('http://127.0.0.1:9000/?name=kill~' + pname)
if name == "main":
droid.showCustomDialog(5556)
# sio.emit(‘request_open_window’, {‘data’: {‘url’: ‘http://0.0.0.0:’ + str(5556),
# ‘title’: ‘Deniose’, ‘icon’: ‘’, ‘camid’: 0}})
start(MyApp, update_interval=0.1, address=‘0.0.0.0’, port=5556, start_browser=False, enable_file_cache=False)
通过在命令行运行该文件,手机上会跳出界面,选择指定图片文件,确定后,便会执行图片降噪处理,并将处理前后图片显示在界面上。
4. 第四步:将该实例放入examples-gpu中
修改前端文件,路径/root/User/demo/aid.dev/
i.在index.html
中添加新增示例的代码块,在./assets/img/photos/
路径下添加事先准备的封面图像x.png
(本文为方便起见,直接复用了其他示例封面)
ii.添加代码块
<div class="col-12 col-md-6 d-flex"> <!-- Card --> <div class="card mb-6 shadow-light-lg lift lift-lg"> <!-- Image --> <script>document.write("<a class='card-img-top' href=http://"+window.location.hostname+":8900/sdcard/kuhn/image_denoising/image_denoising.py~editor>");</script>
<!--<a class="card-img-top" href="https://www.aidlearning.net/box_tracking">--> <!-- Image --> <img src="assets/img/photos/x.png" alt="..." class="card-img-top"> </a> <!-- Body --> <!--<a class="card-body" href="https://www.aidlearning.net/box_tracking">--> <script>document.write("<a class='card-body' href=http://"+window.location.hostname+":8900/sdcard/kuhn/image_denoising/image_denoising.py~editor>");</script> <h3>Image Denoising</h3> <p class="mb-0 text-muted">图片去噪 </p> </a>
</div>
</div>
以上代码主要改动有5处
a) Image块里指定运行的python文件路径
b) 指定界面显示图像路径assets/img/photos/x.jpg
c) Body块里再次指定待运行的python文件路径
d) 修改标题Image Denoising
e) 添加示例简要中文描述
至此,在示例中心就能看见新鲜上线的示例啦!
Ps: 非正常退出窗口,下次启动可能会造成端口号被占用。通过ps aux|grep python
命令能查到哪些进程在运行,用kill -9 [端口号]
命令 杀掉指定进程