VPC图像处理典型功能
VPC(Vision Preprocessing Core)负责图像处理功能,支持对图片做抠图、缩放、格式转换等操作。关于VPC功能的详细介绍请参见功能说明,关于VPC功能对输入、输出的约束要求,请参见约束说明。
本节以抠图、缩放为例说明VPC图像处理时的接口调用流程,同时配合以下典型功能的示例代码辅助理解该接口调用流程:
接口调用流程(以抠图、缩放为例)
开发应用时,如果涉及抠图、缩放等图片处理,则应用程序中必须包含图片处理的代码逻辑,关于图片处理的接口调用流程,请先参见pyACL接口调用流程了解整体流程,再查看本节中的流程说明。
关键接口的说明如下(以抠图、缩放处理为例):
- 调用acl.media.dvpp_create_channel_desc接口创建通道描述信息。
- 调用acl.media.dvpp_create_channel接口创建图片数据处理的通道。
- 调用acl.media.dvpp_create_roi_config接口、acl.media.dvpp_create_resize_config接口分别创建抠图区域位置的配置、缩放配置。
- 实现抠图、缩放功能前,若需要申请Device上的内存存放输入或输出数据,需调用acl.media.dvpp_malloc申请内存。
- 执行抠图、缩放。
- 关于抠图:
- 调用acl.media.dvpp_vpc_crop_async异步接口,按指定区域从输入图片中抠图,再将抠的图片存放到输出内存中,作为输出图片。
输出图片区域与抠图区域“crop_area”不一致时会对图片再做一次缩放操作。
- 当前系统还提供了acl.media.dvpp_vpc_crop_and_paste_async异步接口,支持按指定区域从输入图片中抠图,再将抠的图片贴到目标图片的指定位置,作为输出图片。
- 抠图区域“crop_area”的宽高与贴图区域“paste_area”宽高不一致时会对图片再做一次缩放操作。
- 如果用户需要将目标图片读入内存用于存放输出图片,将贴图区域叠加在目标图片上,则需要编写代码逻辑:在申请输出内存后,将目标图片读入输出内存。
- 调用acl.media.dvpp_vpc_crop_async异步接口,按指定区域从输入图片中抠图,再将抠的图片存放到输出内存中,作为输出图片。
- 关于缩放:
- 对于异步接口,还需调用acl.rt.synchronize_stream接口阻塞程序运行,直到指定Stream中的所有任务都完成。
- 关于抠图:
- 调用acl.media.dvpp_free接口释放输入、输出内存。
- 调用acl.media.dvpp_destroy_roi_config接口、acl.media.dvpp_destroy_resize_config接口分别销毁抠图区域位置的配置、缩放配置。
- 调用acl.media.dvpp_destroy_channel接口销毁图片数据处理的通道。
销毁图片数据处理的通道后,再调用acl.media.dvpp_destroy_channel_desc接口销毁通道描述信息。
图片缩放示例代码
- 调用acl.media.dvpp_create_channel接口创建图片数据处理的通道、调用acl.media.dvpp_destroy_channel接口销毁图片数据处理的通道。
- 调用acl.media.dvpp_vpc_resize_async异步接口,将输入图片缩放到输出图片大小。对于异步接口,还需调用acl.rt.synchronize_stream接口阻塞程序运行,直到指定Stream中的所有任务都完成。
- 调用acl.media.dvpp_create_resize_config接口创建图片缩放配置数据。
如果不想使用默认缩放算法,也可以调用acl.media.dvpp_set_resize_config_interpolation接口指定缩放算法。
您可以从获取样例中获取完整样例代码。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
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 |
import acl # ...... # 1.ACL初始化。 ret = acl.init() # 2.运行管理资源申请。 # 3.创建图片缩放配置数据,不支持指定缩放算法,默认缩放算法为“最近邻插值”。 # self.resize_config是acldvppResizeConfig类型。 self.resize_config = acl.media.dvpp_create_resize_config() # 4.创建图片数据处理通道时的通道描述信息,self.dvpp_channel_desc是acldvppChannelDesc类型。 self.dvpp_channel_desc = acl.media.dvpp_create_channel_desc() # 5.创建图片数据处理的通道。 ret = acl.media.dvpp_create_channel(self.dvpp_channel_desc) # 6.申请缩放输入内存,内存大小根据计算公式得出; w和h是输入图片的实际尺寸。 width_stride = ((w + 15) // 16) * 16 height_stride = ((h + 1) // 2) * 2 buffer_size = (width_stride * height_stride * 3) // 2 dev_in, ret = acl.media.dvpp_malloc(buffer_size ) self.dev_buffer['input_0'] = dev # 7.申请缩放输出内存,内存大小根据计算公式得出; w和h是输入图片的缩放尺寸。 width_stride = ((w + 15) // 16) * 16 height_stride = ((h + 1) // 2) * 2 buffer_size = (width_stride * height_stride * 3) // 2 dev_out, ret = acl.media.dvpp_malloc(buffer_size ) self.dev_buffer['output_0'] = dev # 8.创建缩放输入图片的描述信息,并设置各属性值。 # self.input_desc是acldvppPicDesc类型。 self.input_desc = acl.media.dvpp_create_pic_desc() ret = acl.media.dvpp_set_pic_desc_data(self.input_desc, buffer) ret = acl.media.dvpp_set_pic_desc_format(self.input_desc, YUV420) ret = acl.media.dvpp_set_pic_desc_width(self.input_desc, width) ret = acl.media.dvpp_set_pic_desc_height(self.input_desc, height) ret = acl.media.dvpp_set_pic_desc_width_stride(self.input_desc, wstride) ret = acl.media.dvpp_set_pic_desc_height_stride(self.input_desc, hstride) ret = acl.media.dvpp_set_pic_desc_size(self.input_desc, size) # 9.创建缩放输出图片的描述信息,并设置各属性值。 # 如果缩放的输出图片作为模型推理的输入,则输出图片的宽高要与模型要求的宽高保持一致。 # self.output_desc是acldvppPicDesc类型。 self.output_desc= acl.media.dvpp_create_pic_desc() ret = acl.media.dvpp_set_pic_desc_data(self.output_desc, buffer) ret = acl.media.dvpp_set_pic_desc_format(self.output_desc, YUV420) ret = acl.media.dvpp_set_pic_desc_width(self.output_desc, width) ret = acl.media.dvpp_set_pic_desc_height(self.output_desc, height) ret = acl.media.dvpp_set_pic_desc_width_stride(self.output_desc, wstride) ret = acl.media.dvpp_set_pic_desc_height_stride(self.output_desc, hstride) ret = acl.media.dvpp_set_pic_desc_size(self.output_desc, size) # 10.执行异步缩放,再调用acl.rt.synchronize_stream接口阻塞Host运行,直到指定Stream中的所有任务都完成。 ret = acl.media.dvpp_vpc_resize_async(self.dvpp_channel_desc, self.input_desc, self.output_desc, self.resize_config, self.stream) ret = acl.rt.synchronize_stream(self.stream) # 11.缩放结束后,释放资源,包括缩放输入/输出图片的描述信息、缩放输入/输出内存。 ret = acl.media.dvpp_destroy_pic_desc(self.output_desc) ret = acl.media.dvpp_destroy_pic_desc(self.input_desc) ret = acl.media.dvpp_free(self.dev_buffer['input_0'] ) ret = acl.media.dvpp_free(self.dev_buffer['output_0'] ) # 12.释放运行管理资源。 ret = acl.finalize() # ...... |
格式转换示例代码
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
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 |
import acl # ...... ACL_MEMCPY_HOST_TO_DEVICE = 1 ACL_MEMCPY_DEVICE_TO_HOST = 2 PIXEL_FORMAT_YUV_400 = 0 PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1 # 1.ACL初始化。 ret = acl.init() # 2.运行管理资源申请。 # 3.创建图片数据处理通道时的通道描述信息,dvpp_channel_desc是acldvppChannelDesc类型。 dvpp_channel_desc = acl.media.dvpp_create_channel_desc() # 4.创建图片数据处理的通道。 ret = acl.media.dvpp_create_channel(dvpp_channel_desc) # 5.申请输入内存。 input_width_stride = ((input_width + 15) // 16) * 16 input_height_stride = ((input_height + 1) // 2) * 2 # input_width_stride、input_height_stride分别表示图片的对齐后宽、对齐后高,此处以YUV420SP格式的图片为例。 in_buffer_size = (input_width_stride * input_height_stride * 3) // 2 in_dev_buffer, ret = acl.media.dvpp_malloc(in_buffer_size) np_yuv = np.fromfile(path, dtype=np.byte) buffer_size = np_yuv.itemsize * np_yuv.size bytes_data = np_yuv.tobytes() np_yuv_ptr = acl.util.bytes_to_ptr(bytes_data) ret = acl.rt.memcpy(in_dev_buffer, buffer_size, np_yuv_ptr, buffer_size, ACL_MEMCPY_HOST_TO_DEVICE) # 6.申请色域转换输出内存。 output_width_stride = ((output_width + 15) // 16) * 16 output_height_stride = ((output_height + 1) // 2) * 2 # output_width_stride、output_height_stride分别表示图片的对齐后宽、对齐后高,此处以YUV420SP格式的图片为例。 out_buffer_size = (output_width_stride * output_height_stride * 3) // 2 out_dev_buffer, ret = acl.media.dvpp_malloc(out_buffer_size) # 7.创建色域转换输入图片的描述信息,并设置各属性值。 input_desc = acl.media.dvpp_create_pic_desc() ret = acl.media.dvpp_set_pic_desc_data(input_desc, in_dev_buffer) ret = acl.media.dvpp_set_pic_desc_format(input_desc, PIXEL_FORMAT_YUV_SEMIPLANAR_420) ret = acl.media.dvpp_set_pic_desc_width(input_desc, input_width) ret = acl.media.dvpp_set_pic_desc_height(input_desc, input_height) ret = acl.media.dvpp_set_pic_desc_width_stride(input_desc, input_width_stride) ret = acl.media.dvpp_set_pic_desc_height_stride(input_desc, input_height_stride) ret = acl.media.dvpp_set_pic_desc_size(input_desc, in_buffer_size) # 8.创建色域转换的输出图片的描述信息,并设置各属性值, 输出的宽和高要求和输入一致。 # 如果色域转换的输出图片作为模型推理的输入,则输出图片的宽高要与模型要求的宽高保持一致。 output_desc = acl.media.dvpp_create_pic_desc() ret = acl.media.dvpp_set_pic_desc_data(output_desc, out_dev_buffer) ret = acl.media.dvpp_set_pic_desc_format(output_desc, PIXEL_FORMAT_YUV_400) ret = acl.media.dvpp_set_pic_desc_width(output_desc, output_width) ret = acl.media.dvpp_set_pic_desc_height(output_desc, output_height) ret = acl.media.dvpp_set_pic_desc_width_stride(output_desc, output_width_stride) ret = acl.media.dvpp_set_pic_desc_height_stride(output_desc, output_height_stride) ret = acl.media.dvpp_set_pic_desc_size(output_desc, out_buffer_size) # 9.执行异步色域转换,再调用acl.rt.synchronize_stream接口阻塞程序运行,直到指定Stream中的所有任务都完成。 ret = acl.media.dvpp_vpc_convert_color_async(dvpp_channel_desc, input_desc, output_desc, stream) ret = acl.rt.synchronize_stream(stream) # 10.色域转换结束后,释放资源,包括输入/输出图片的描述信息、输入/输出内存。 ret = acl.media.dvpp_destroy_pic_desc(input_desc) ret = acl.media.dvpp_destroy_pic_desc(output_desc) np_output = np.zeros(out_buffer_size, dtype=np.byte) bytes_data = np_output.tobytes() np_output_ptr = acl.util.bytes_to_ptr(bytes_data) # 将Device的处理结果数据传输到Host。 ret = acl.rt.memcpy(np_output_ptr, out_buffer_size, out_dev_buffer, out_buffer_size, ACL_MEMCPY_DEVICE_TO_HOST) ret = acl.media.dvpp_free(in_dev_buffer) ret = acl.media.dvpp_free(out_dev_buffer) # 11.释放运行管理资源。 ret = acl.finalize() # ...... |
抠图(一图一框)示例代码
调用acl.media.dvpp_vpc_crop_async异步接口,按指定区域从输入图片中抠图,再将抠的图片存放到输出内存中,作为输出图片。
您可以从获取样例中获取完整样例代码。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
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 |
import acl # ...... # 1.pyACL初始化。 ret = acl.init() # 2.运行管理资源申请。 # 3.指定抠图区域的位置、指定贴图区域的位置。 # 按左上角为原点做偏移。w,h为图片原始宽高。 self.crop_area = acl.media.dvpp_create_roi_config(w // 2, w - 1, h // 2, h - 1) # 4.创建图片数据处理通道时的通道描述信息,dvpp_channel_desc 是acldvppChannelDesc类型。 self.dvpp_channel_desc = acl.media.dvpp_create_channel_desc() # 5.创建图片数据处理的通道。 ret = acl.media.dvpp_create_channel(self.dvpp_channel_desc) # 6.创建输入输出图片的描述信息,并设置各属性值。 self.input_desc = acl.media.dvpp_create_pic_desc() assert self.input_desc is not None # 6.1 自定义方法 set_picture_desc 设置输入图片描述。 # 根据计算公式计算内存大小存储图片数据,并设置到图片描述,同时设置其他属性。 self.set_picture_desc(self.input_desc, w, h, "input", 0) self.output_desc = acl.media.dvpp_create_pic_desc() assert self.output_desc is not None # 6.2 自定义方法 set_picture_desc 设置输出图片描述。 out_buffer_size = self.set_picture_desc(self.output_desc, w // 2, h // 2, "output", 0) # 7.执行异步抠图,再调用acl.rt.synchronize_stream接口阻塞Host运行,直到指定Stream中的所有任务都完成。 ret = acl.media.dvpp_vpc_crop_async(self.dvpp_channel_desc, self.input_desc, self.output_desc, self.crop_area, self.stream) ret = acl.rt.synchronize_stream(self.stream) # 8.释放资源,包括输入/输出图片的描述信息、输入/输出内存、通道描述信息、通道等。 ret = acl.media.dvpp_destroy_pic_desc(self.input_desc) ret = acl.media.dvpp_destroy_pic_desc(self.output_desc) # dev_buffer是字典对象,存储device侧申请内存。 for key in self.dev_buffer.keys(): if self.dev_buffer[key]: ret = acl.media.dvpp_free(self.dev_buffer[key]) if self.dvpp_channel_desc: ret = acl.media.dvpp_destroy_channel(self.dvpp_channel_desc) assert ret == 0 ret = acl.media.dvpp_destroy_channel_desc(self.dvpp_channel_desc) assert ret == 0 # 9.释放运行管理资源。 # 10.pyACL去初始化。 ret = acl.finalize() # ...... |
抠图缩放(一图一框)示例代码
- 调用acl.media.dvpp_vpc_crop_resize_async异步接口,按指定区域从输入图片中抠图,再将抠的图片存放到输出内存中,作为输出图片。对于异步接口,还需调用acl.rt.synchronize_stream接口阻塞程序运行,直到指定Stream中的所有任务都完成。
- 输出图片区域与抠图区域“crop_area”不一致时会对图片再做一次缩放操作。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
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 |
import acl # ...... # 1.pyACL初始化。 ret = acl.init() # 2.运行管理资源申请。 # 3.指定抠图区域的位置、指定贴图区域的位置。 # 按左上角为原点做偏移。w,h为图片原始宽高。 self.crop_area = acl.media.dvpp_create_roi_config(w // 2, w - 1, h // 2, h - 1) # 4.创建图片数据处理通道时的通道描述信息,dvpp_channel_desc 是acldvppChannelDesc类型。 self.dvpp_channel_desc = acl.media.dvpp_create_channel_desc() # 5.创建图片数据处理的通道。 ret = acl.media.dvpp_create_channel(self.dvpp_channel_desc) # 6.创建输入输出图片的描述信息,并设置各属性值。 self.input_desc = acl.media.dvpp_create_pic_desc() assert self.input_desc is not None # 6.1 自定义方法 set_picture_desc 设置输入图片描述。 # 根据计算公式计算内存大小存储图片数据,并设置到图片描述,同时设置其他属性。 self.set_picture_desc(self.input_desc, w, h, "input", 0) self.output_desc = acl.media.dvpp_create_pic_desc() assert self.output_desc is not None # 6.2 自定义方法 set_picture_desc 设置输出图片描述。 resize_width = w // 4 resize_height = h // 4 out_buffer_size = self.set_picture_desc(self.output_desc, resize_width, resize_height, "output", 0) # 7.执行异步抠图,再调用acl.rt.synchronize_stream接口阻塞Host运行,直到指定Stream中的所有任务都完成。 self.resize_config = acl.media.dvpp_create_resize_config() ret = acl.media.dvpp_vpc_crop_resize_async(self.dvpp_channel_desc, self.input_desc, self.output_desc, self.crop_area, self.resize_config, self.stream) ret = acl.rt.synchronize_stream(self.stream) # 8.释放资源,包括输入/输出图片的描述信息、输入/输出内存、通道描述信息、通道等。 ret = acl.media.dvpp_destroy_pic_desc(self.input_desc) ret = acl.media.dvpp_destroy_pic_desc(self.output_desc) # dev_buffer是字典对象,存储device侧申请内存。 for key in self.dev_buffer.keys(): if self.dev_buffer[key]: ret = acl.media.dvpp_free(self.dev_buffer[key]) if self.dvpp_channel_desc: ret = acl.media.dvpp_destroy_channel(self.dvpp_channel_desc) assert ret == 0 ret = acl.media.dvpp_destroy_channel_desc(self.dvpp_channel_desc) assert ret == 0 # 9.释放运行管理资源。 # 10.pyACL去初始化。 ret = acl.finalize() # ...... |
抠图贴图(一图一框)示例代码
- 调用acl.media.dvpp_vpc_crop_and_paste_async异步接口,按指定区域从输入图片中抠图,再将抠的图片贴到目标图片的指定位置,作为输出图片。对于异步接口,还需调用acl.rt.synchronize_stream接口阻塞程序运行,直到指定Stream中的所有任务都完成。
- 抠图区域“crop_area”的宽高与贴图区域“paste_area”宽高不一致时会对图片再做一次缩放操作。
- 如果用户需要将目标图片读入内存用于存放输出图片,将贴图区域叠加在目标图片上,则需要编写代码逻辑:在申请输出内存后,将目标图片读入输出内存。
您可以从获取样例中获取完整样例代码。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
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 |
import acl # ...... # 1.pyACL初始化。 ret = acl.init() # 2.运行管理资源申请。 # 3.指定抠图区域的位置、指定贴图区域的位置。 # 按左上角为原点做偏移。w,h为图片原始宽高。 self.crop_area = acl.media.dvpp_create_roi_config(w // 2, w - 1, h // 2, h - 1) self.paste_area = acl.media.dvpp_create_roi_config(w // 2, w - 1, h // 2, h - 1) # 4.创建图片数据处理通道时的通道描述信息,dvpp_channel_desc 是acldvppChannelDesc类型。 self.dvpp_channel_desc = acl.media.dvpp_create_channel_desc() # 5.创建图片数据处理的通道。 ret = acl.media.dvpp_create_channel(self.dvpp_channel_desc) # 6.创建输入输出图片的描述信息,并设置各属性值。 self.input_desc = acl.media.dvpp_create_pic_desc() assert self.input_desc is not None # 6.1 自定义方法 set_picture_desc 设置输入图片描述。 # 根据计算公式计算内存大小存储图片数据,并设置到图片描述,同时设置其他属性。 self.set_picture_desc(self.input_desc, w, h, "input", 0) self.output_desc = acl.media.dvpp_create_pic_desc() assert self.output_desc is not None # 6.2 自定义方法 set_picture_desc 设置输出图片描述。 out_buffer_size = self.set_picture_desc(self.output_desc, w, h, "output", 0) # 7.执行异步抠图粘贴,再调用acl.rt.synchronize_stream接口阻塞Host运行,直到指定Stream中的所有任务都完成。 ret = acl.media.dvpp_vpc_crop_and_paste_async(self.dvpp_channel_desc, self.input_desc, self.output_desc, self.crop_area, self.paste_area, self.stream) ret = acl.rt.synchronize_stream(self.stream) # 8.释放资源,包括输入/输出图片的描述信息、输入/输出内存、通道描述信息、通道等。 ret = acl.media.dvpp_destroy_pic_desc(self.input_desc) ret = acl.media.dvpp_destroy_pic_desc(self.output_desc) # dev_buffer是字典对象,存储device侧申请内存。 for key in self.dev_buffer.keys(): if self.dev_buffer[key]: ret = acl.media.dvpp_free(self.dev_buffer[key]) if self.dvpp_channel_desc: ret = acl.media.dvpp_destroy_channel(self.dvpp_channel_desc) assert ret == 0 ret = acl.media.dvpp_destroy_channel_desc(self.dvpp_channel_desc) assert ret == 0 # 9.释放运行管理资源。 # 10.pyACL去初始化。 ret = acl.finalize() # ...... |
抠图贴图缩放(一图一框)示例代码
- 调用acl.media.dvpp_vpc_crop_resize_paste_async异步接口,按指定区域从输入图片中抠图,再将抠的图片贴到目标图片的指定位置,作为输出图片。对于异步接口,还需调用acl.rt.synchronize_stream接口阻塞程序运行,直到指定Stream中的所有任务都完成。
调用acl.media.dvpp_vpc_crop_resize_paste_async实现抠图缩放贴图时,支持指定缩放算法。
- 抠图区域“crop_area”的宽高与贴图区域“paste_area”宽高不一致时会对图片再做一次缩放操作。
- 如果用户需要将目标图片读入内存用于存放输出图片,将贴图区域叠加在目标图片上,则需要编写代码逻辑:在申请输出内存后,将目标图片读入输出内存。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
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 |
import acl # ...... # 1.pyACL初始化。 ret = acl.init() # 2.运行管理资源申请。 # 3.创建图片数据处理通道时的通道描述信息,dvpp_channel_desc 是acldvppChannelDesc类型。 self.dvpp_channel_desc = acl.media.dvpp_create_channel_desc() # 4.创建图片数据处理的通道。 ret = acl.media.dvpp_create_channel(self.dvpp_channel_desc) # 5.创建输出图片的描述信息,并设置各属性值。 self.output_desc = acl.media.dvpp_create_pic_desc() assert self.output_desc is not None out_buffer_size = self.set_picture_desc(self.output_desc, w // 2, h // 2, "output", 0) # 6.创建输入图片的描述信息,并设置各属性值。 self.input_desc = acl.media.dvpp_create_pic_desc() assert self.input_desc is not None self.set_picture_desc(self.input_desc, w, h, "input", 0) # 7.加载图片数据,并拷贝到Device侧。 np_yuv = np.fromfile(path, dtype=np.byte) in_buffer_size = np_yuv.itemsize * np_yuv.size bytes_data = np_yuv.tobytes() np_yuv_ptr = acl.util.bytes_to_ptr(bytes_data) ret = acl.rt.memcpy(self.dev_buffer["input_0"], in_buffer_size, np_yuv_ptr, in_buffer_size, ACL_MEMCPY_HOST_TO_DEVICE) assert ret == 0 # 8.指定抠图、贴图区域的位置。 self.crop_area = acl.media.dvpp_create_roi_config(w // 2, w - 1, h // 2, h - 1) self.paste_area = acl.media.dvpp_create_roi_config(w // 4, w // 2 - 1, h // 4, h // 2 - 1) # 9.执行异步抠图贴图缩放。 self.resize_config = acl.media.dvpp_create_resize_config() ret = acl.media.dvpp_vpc_crop_resize_paste_async(self.dvpp_channel_desc, self.input_desc, self.output_desc, self.crop_area, self.paste_area, self.resize_config, self.stream) assert ret == 0 ret = acl.rt.synchronize_stream(self.stream) assert ret == 0 # 10.将输出数据拷贝到Host侧。 np_output = np.zeros(out_buffer_size, dtype=np.byte) bytes_data = np_output.tobytes() np_output_ptr = acl.util.bytes_to_ptr(bytes_data) ret = acl.rt.memcpy(np_output_ptr, out_buffer_size, self.dev_buffer["output_0"], out_buffer_size, ACL_MEMCPY_DEVICE_TO_HOST) assert ret == 0 # 11.释放资源,包括输入/输出图片的描述信息、输入/输出内存、通道描述信息、通道等。 ret = acl.media.dvpp_destroy_pic_desc(self.input_desc) ret = acl.media.dvpp_destroy_pic_desc(self.output_desc) # dev_buffer是字典对象,存储device侧申请内存。 for key in self.dev_buffer.keys(): if self.dev_buffer[key]: ret = acl.media.dvpp_free(self.dev_buffer[key]) if self.dvpp_channel_desc: ret = acl.media.dvpp_destroy_channel(self.dvpp_channel_desc) assert ret == 0 ret = acl.media.dvpp_destroy_channel_desc(self.dvpp_channel_desc) assert ret == 0 # 12.释放运行管理资源。 # 13.pyACL去初始化。 ret = acl.finalize() # ...... |
抠图贴图(一图多框)示例代码
- 调用dvpp_vpc_batch_crop_and_paste_async异步接口,按指定区域从输入图片中抠图,再将抠的图片贴到目标图片的指定位置,作为输出图片。对于异步接口,还需调用acl.rt.synchronize_stream接口阻塞程序运行,直到指定Stream中的所有任务都完成。
- 抠图区域“crop_area”的宽高与贴图区域“paste_area”宽高不一致时会对图片再做一次缩放操作。
- 如果用户需要将目标图片读入内存用于存放输出图片,将贴图区域叠加在目标图片上,则需要编写代码逻辑:在申请输出内存后,将目标图片读入输出内存。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
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 |
import acl # ...... # 1.pyACL初始化。 ret = acl.init() # 2.运行管理资源申请。 # 3.创建图片批处理输入输出描述。 self.out_batch_pic_desc = acl.media.dvpp_create_batch_pic_desc(self.out_batch_size) self.in_batch_pic_desc = acl.media.dvpp_create_batch_pic_desc(self.in_batch_size) # 3.1 指定批量抠图区域的位置、指定批量贴图区域的位置。 # 3.2 设置输入输出图片描述:如果抠图贴图的输出图片作为模型推理的输入,则输出图片的宽高要与模型要求的宽高保持一致。 for i in range(self.in_batch_size): input_desc = acl.media.dvpp_get_pic_desc(self.in_batch_pic_desc, i) assert input_desc is not None # 申请内存并设置输出图片描述。 self.set_picture_desc(input_desc, w, h, "input", i) # copy from host to device. key = "input" + '_' + str(i) ret = acl.rt.memcpy(self.dev_buffer[key], in_buffer_size, np_yuv_ptr, in_buffer_size, 1) assert ret == 0 # 创建roiNums,每张图对应需要抠图和贴图的数量。 roiList.append(self.out_batch_size // self.in_batch_size) for i in range(self.out_batch_size): output_desc = acl.media.dvpp_get_pic_desc(self.out_batch_pic_desc, i) assert output_desc is not None # 自定义方法申请内存并设置输出图片描述。 self.set_picture_desc(output_desc, w, h, "output", i) if i == 0: crop_area = acl.media.dvpp_create_roi_config(w // 2, w - 1, h // 2, h - 1) else: crop_area = acl.media.dvpp_create_roi_config(0, w - 1, h // 2, h - 1) paste_area = acl.media.dvpp_create_roi_config(w // 2, w - 1, h // 2, h - 1) self.cropList.append(crop_area) self.pasteList.append(paste_area) # 3.3 roiList,每张图对应需要抠图和贴图的数量。输出图片数相对输入多出来的,加到最后一张输入图片的输出。 total_num = 0 for i in range(self.in_batch_size): total_num += roiList[i] if self.out_batch_size % self.in_batch_size != 0: roiList[-1] = self.out_batch_size - total_num + roiList[-1] # 4.创建图片数据处理通道时的通道描述信息,dvppChannelDesc_是acldvppChannelDesc类型。 self.dvpp_channel_desc = acl.media.dvpp_create_channel_desc() # 5.创建图片数据处理的通道。 ret = acl.media.dvpp_create_channel(self.dvpp_channel_desc) # 6.执行异步缩放,再调用acl.rt.synchronize_stream接口阻塞程序运行,直到指定Stream中的所有任务都完成。 _, ret = acl.media.dvpp_vpc_batch_crop_and_paste_async(self.dvpp_channel_desc, self.in_batch_pic_desc, roiList, self.out_batch_pic_desc, self.cropList, self.pasteList, self.stream) ret = acl.rt.synchronize_stream(self.stream) # 7.释放资源,包括输入/输出图片的描述信息、输入/输出内存、通道描述信息、通道等。 # 7.1 释放图片描述和批量图片描述。 self._free_pic_desc() for i in range(len(self.cropList)): ret = acl.media.dvpp_destroy_roi_config(self.cropList[i]) assert ret == 0 for i in range(len(self.pasteList)): ret = acl.media.dvpp_destroy_roi_config(self.pasteList[i]) assert ret == 0 for key in self.dev_buffer.keys(): if self.dev_buffer[key]: ret = acl.media.dvpp_free(self.dev_buffer[key]) # 7.2 销毁通道和通道描述。 if self.dvpp_channel_desc: ret = acl.media.dvpp_destroy_channel(self.dvpp_channel_desc) assert ret == 0 ret = acl.media.dvpp_destroy_channel_desc(self.dvpp_channel_desc) assert ret == 0 # 8.释放运行管理资源。 # 9.pyACL去初始化。 ret = acl.finalize() |