4. Ai2d预处理示例#
1. 概述#
基于 nncase_runtime
模块提供的接口,AIDemo 部分对 nncase_runtime.ai2d
进行了二次封装,封装文件在 /sdcard/libs/AI2D.py
模块内,提供的接口见:Ai2d 模块 API 手册。针对Ai2d提供的5种预处理方法,本文档提供示例,将预处理的结果可视化,帮助用户更好的理解使用Ai2d预处理过程。未封装的 nncase_runtime.ai2d
接口见:nncase_usage。
2. resize 方法#
resize方法是一种在图片预处理中广泛使用的操作,它主要用于改变图像的尺寸大小。无论是放大还是缩小图像,都可以通过这个方法来实现。这里给出使用 Ai2d
实现resize过程的示例代码。
from libs.PipeLine import PipeLine, ScopedTiming
from libs.AI2D import Ai2d
from media.media import *
import nncase_runtime as nn
import ulab.numpy as np
import gc
import sys,os
if __name__ == "__main__":
# 显示模式,默认"hdmi",可以选择"hdmi"和"lcd"
display_mode="hdmi"
if display_mode=="hdmi":
display_size=[1920,1080]
else:
display_size=[800,480]
# 初始化PipeLine,用于图像处理流程
pl = PipeLine(rgb888p_size=[512,512], display_size=display_size, display_mode=display_mode)
pl.create() # 创建PipeLine实例
my_ai2d=Ai2d(debug_mode=0) #初始化Ai2d实例
my_ai2d.set_ai2d_dtype(nn.ai2d_format.NCHW_FMT, nn.ai2d_format.NCHW_FMT, np.uint8, np.uint8)
# 配置resize预处理方法
my_ai2d.resize(nn.interp_method.tf_bilinear, nn.interp_mode.half_pixel)
# 构建预处理过程
my_ai2d.build([1,3,512,512],[1,3,640,640])
try:
while True:
os.exitpoint() # 检查是否有退出信号
with ScopedTiming("total",1):
img = pl.get_frame() # 获取当前帧数据
print(img.shape) # 原图shape为[3,512,512]
ai2d_output_tensor=my_ai2d.run(img) # 执行resize预处理
ai2d_output_np=ai2d_output_tensor.to_numpy() # 类型转换
print(ai2d_output_np.shape) # 预处理后的shape为[1,3,640,640]
gc.collect() # 垃圾回收
except Exception as e:
sys.print_exception(e) # 打印异常信息
finally:
pl.destroy() # 销毁PipeLine实例
3. crop 方法#
crop方法是一种用于从原始图像中提取(裁剪)出感兴趣区域(ROI,Region of Interest)的操作。它可以根据指定的坐标和尺寸,从图像中选取一部分作为新的图像。这里给出使用 Ai2d
实现crop过程的示例代码。
from libs.PipeLine import PipeLine, ScopedTiming
from libs.AI2D import Ai2d
from media.media import *
import nncase_runtime as nn
import ulab.numpy as np
import gc
import sys,os
import image
if __name__ == "__main__":
# 显示模式,默认"hdmi",可以选择"hdmi"和"lcd"
display_mode="hdmi"
if display_mode=="hdmi":
display_size=[1920,1080]
else:
display_size=[800,480]
# 初始化PipeLine,用于图像处理流程
pl = PipeLine(rgb888p_size=[512,512], display_size=display_size, display_mode=display_mode)
pl.create() # 创建PipeLine实例
my_ai2d=Ai2d(debug_mode=0) #初始化Ai2d实例
my_ai2d.set_ai2d_dtype(nn.ai2d_format.NCHW_FMT, nn.ai2d_format.NCHW_FMT, np.uint8, np.uint8)
# 配置crop预处理方法
my_ai2d.crop(100,100,300,300)
# 构建预处理过程
my_ai2d.build([1,3,512,512],[1,3,200,200])
try:
while True:
os.exitpoint() # 检查是否有退出信号
with ScopedTiming("total",1):
img = pl.get_frame() # 获取当前帧数据
print(img.shape) # 原图shape为[1,3,512,512]
ai2d_output_tensor=my_ai2d.run(img) # 执行crop预处理,H/W维度均裁剪100~300px范围内的数据
ai2d_output_np=ai2d_output_tensor.to_numpy() # 类型转换
print(ai2d_output_np.shape) # 预处理后的shape为[1,3,200,200]
# 使用transpose处理输出为HWC排布的np数据,然后在np数据上创建RGB888格式的Image实例用于在IDE显示效果
shape=ai2d_output_np.shape
ai2d_output_tmp = ai2d_output_np.reshape((shape[0] * shape[1], shape[2]*shape[3]))
ai2d_output_tmp_trans = ai2d_output_tmp.transpose()
ai2d_output_hwc=ai2d_output_tmp_trans.copy().reshape((shape[2],shape[3],shape[1]))
out_img=image.Image(200, 200, image.RGB888,alloc=image.ALLOC_REF,data=ai2d_output_hwc)
out_img.compress_for_ide()
gc.collect() # 垃圾回收
except Exception as e:
sys.print_exception(e) # 打印异常信息
finally:
pl.destroy() # 销毁PipeLine实例
4. pad 方法#
pad(填充)方法是一种在图片预处理阶段,对图像边缘进行填充操作的技术。它通过在图像的四周(上下左右)添加像素值,来改变图像的尺寸大小。这些添加的像素值可以自定义。这里给出使用 Ai2d
实现pad过程的示例代码。
from libs.PipeLine import PipeLine, ScopedTiming
from libs.AI2D import Ai2d
from media.media import *
import nncase_runtime as nn
import ulab.numpy as np
import gc
import sys,os
import image
if __name__ == "__main__":
# 显示模式,默认"hdmi",可以选择"hdmi"和"lcd"
display_mode="hdmi"
if display_mode=="hdmi":
display_size=[1920,1080]
else:
display_size=[800,480]
# 初始化PipeLine,用于图像处理流程
pl = PipeLine(rgb888p_size=[512,512], display_size=display_size, display_mode=display_mode)
pl.create() # 创建PipeLine实例
my_ai2d=Ai2d(debug_mode=0) #初始化Ai2d实例
my_ai2d.set_ai2d_dtype(nn.ai2d_format.NCHW_FMT, nn.ai2d_format.NCHW_FMT, np.uint8, np.uint8)
# 配置pad预处理方法
my_ai2d.pad(paddings=[0,0,0,0,15,15,30,30],pad_mode=0,pad_val=[114,114,114])
# 构建预处理过程
my_ai2d.build([1,3,512,512],[1,3,512+15+15,512+30+30])
try:
while True:
os.exitpoint() # 检查是否有退出信号
with ScopedTiming("total",1):
img = pl.get_frame() # 获取当前帧数据
print(img.shape) # 原图shape为[1,3,512,512]
ai2d_output_tensor=my_ai2d.run(img) # 执行pad预处理,H维度上下padding 15px,W维度左右padding 30px
ai2d_output_np=ai2d_output_tensor.to_numpy() # 类型转换
print(ai2d_output_np.shape) # 预处理后的shape为[1,3,542,572]
# 使用transpose处理输出为HWC排布的np数据,然后在np数据上创建RGB888格式的Image实例用于在IDE显示效果
shape=ai2d_output_np.shape
ai2d_output_tmp = ai2d_output_np.reshape((shape[0] * shape[1], shape[2]*shape[3]))
ai2d_output_tmp_trans = ai2d_output_tmp.transpose()
ai2d_output_hwc=ai2d_output_tmp_trans.copy().reshape((shape[2],shape[3],shape[1]))
out_img=image.Image(512+30+30, 512+15+15, image.RGB888,alloc=image.ALLOC_REF,data=ai2d_output_hwc)
out_img.compress_for_ide()
gc.collect() # 垃圾回收
except Exception as e:
sys.print_exception(e) # 打印异常信息
finally:
pl.destroy() # 销毁PipeLine实例
5. affine 方法#
affine(仿射变换)方法是一种在图像预处理中用于对图像进行几何变换的技术。它可以实现图像的旋转、平移、缩放等多种几何变换操作,并且能够保持图像的 “平直性”(即直线在变换后仍然是直线)和 “平行性”(即平行的线在变换后仍然平行)。这里给出使用 Ai2d
实现affine过程的示例代码。
from libs.PipeLine import PipeLine, ScopedTiming
from libs.AI2D import Ai2d
from media.media import *
import nncase_runtime as nn
import ulab.numpy as np
import gc
import sys,os
import image
if __name__ == "__main__":
# 显示模式,默认"hdmi",可以选择"hdmi"和"lcd"
display_mode="hdmi"
if display_mode=="hdmi":
display_size=[1920,1080]
else:
display_size=[800,480]
# 初始化PipeLine,用于图像处理流程
pl = PipeLine(rgb888p_size=[512,512], display_size=display_size, display_mode=display_mode)
pl.create() # 创建PipeLine实例
my_ai2d=Ai2d(debug_mode=0) #初始化Ai2d实例
my_ai2d.set_ai2d_dtype(nn.ai2d_format.NCHW_FMT, nn.ai2d_format.NCHW_FMT, np.uint8, np.uint8)
# 创建仿射变换矩阵,缩放0.5倍,X/Y方向各平移50px
affine_matrix = [0.5,0,50,
0,0.5,50]
# 设置仿射变换预处理
my_ai2d.affine(nn.interp_method.cv2_bilinear,0, 0, 127, 1,affine_matrix)
# 构建预处理过程
my_ai2d.build([1,3,512,512],[1,3,256,256])
try:
while True:
os.exitpoint() # 检查是否有退出信号
with ScopedTiming("total",1):
img = pl.get_frame() # 获取当前帧数据
print(img.shape) # 原图shape为[1,3,512,512]
ai2d_output_tensor=my_ai2d.run(img) # 执行affine预处理,H/W维度各缩小为0.5倍,同时向X/Y方向平移50px
ai2d_output_np=ai2d_output_tensor.to_numpy() # 类型转换
print(ai2d_output_np.shape) # 预处理后的shape为[1,3,256,256]
# 使用transpose处理输出为HWC排布的np数据,然后在np数据上创建RGB888格式的Image实例用于在IDE显示效果
shape=ai2d_output_np.shape
ai2d_output_tmp = ai2d_output_np.reshape((shape[0] * shape[1], shape[2]*shape[3]))
ai2d_output_tmp_trans = ai2d_output_tmp.transpose()
ai2d_output_hwc=ai2d_output_tmp_trans.copy().reshape((shape[2],shape[3],shape[1]))
out_img=image.Image(256, 256, image.RGB888,alloc=image.ALLOC_REF,data=ai2d_output_hwc)
out_img.compress_for_ide()
gc.collect() # 垃圾回收
except Exception as e:
sys.print_exception(e) # 打印异常信息
finally:
pl.destroy() # 销毁PipeLine实例
6. shift 方法#
shift方法是数据预处理中比特位右移的方法,每右移一位原数据变为原来的1/2。这里给出使用 Ai2d
实现affine过程的示例代码。
from libs.PipeLine import PipeLine, ScopedTiming
from libs.AI2D import Ai2d
from media.media import *
import nncase_runtime as nn
import ulab.numpy as np
import gc
import sys,os
import image
if __name__ == "__main__":
# 显示模式,默认"hdmi",可以选择"hdmi"和"lcd"
display_mode="hdmi"
if display_mode=="hdmi":
display_size=[1920,1080]
else:
display_size=[800,480]
background=np.ones((1,3,512,512),dtype=np.uint8)
data_input=np.ones((1,3,256,256),dtype=np.uint8)*240
background[:,:,0:256,0:256]=data_input.copy()
my_ai2d=Ai2d(debug_mode=0) #初始化Ai2d实例
my_ai2d.set_ai2d_dtype(nn.ai2d_format.RAW16, nn.ai2d_format.NCHW_FMT, np.int16, np.uint8)
# 设置shift预处理,右移一位,值变为1/2
my_ai2d.shift(1)
# 构建预处理过程
my_ai2d.build([1,3,256,256],[1,3,256,256])
try:
with ScopedTiming("total",1):
print(data_input.shape) # 原图shape为[1,3,256,256],原值都是240
ai2d_output_tensor=my_ai2d.run(data_input) # 执行shift操作后,右移一位,值变为原来的1/2,也就是120
ai2d_output_np=ai2d_output_tensor.to_numpy() # 类型转换
print(ai2d_output_np.shape) # 预处理后的shape为[1,3,256,256],值从240变为120
background[:,:,256:,256:]=ai2d_output_np.copy()
# 使用transpose处理输出为HWC排布的np数据,然后在np数据上创建RGB888格式的Image实例用于在IDE显示效果
shape=background.shape
background_tmp = background.reshape((shape[0] * shape[1], shape[2]*shape[3]))
background_trans = background_tmp.transpose()
background_hwc=background_trans.copy().reshape((shape[2],shape[3],shape[1]))
img=image.Image(512, 512, image.RGB888,alloc=image.ALLOC_REF,data=background_hwc)
img.compress_for_ide()
gc.collect() # 垃圾回收
except Exception as e:
sys.print_exception(e) # 打印异常信息
finally:
pass