Typical Functions of VPC

This section takes image cropping and resizing as an example to explain the API call sequence when the VPC processes images and provides sample code of typical functions to help you better understand the API call sequence.

Vision Preprocessing Core (VPC) supports image cropping, resizing, pasting, and format conversion. For details about the VPC function and constraints, see DVPP Media Acceleration Library.

Typical API Call Sequence (Image Resizing)

Figure 1 Process of calling the zoom function

The current system supports image cropping and resizing. The key APIs are described as follows:

  1. Call aclInit to initialize the system.
  2. Call aclrtSetDevice to specify the compute device.
  3. Call the hi_mpi_sys_init API to initialize the media data processing system.
  4. Call the hi_mpi_vpc_sys_create_chn API to create a stream.
  5. Call the hi_mpi_dvpp_malloc API to allocate device memory for storing the input or output data.
  6. Execute the image processing task. This step uses resizing as an example.

    Call the hi_mpi_vpc_resize API to resize the image. The hi_mpi_vpc_resize API is an asynchronous API. If this API is successfully called, the task is successfully delivered. You also need to call the hi_mpi_vpc_get_process_result API to wait until the task is complete.

    • The hi_mpi_vpc_get_process_result interface can be invoked in the same thread as the hi_mpi_vpc_resize interface, or a new thread can be created to invoke the hi_mpi_vpc_get_process_result interface. The latter method uses multiple threads concurrently to improve efficiency. However, you need to implement synchronization between threads.
    • When the resizing API is called, you can set the formats of the input and output images to different values to convert the image format.
    • If the DVPP APIs are called on the host, the image processing result will be stored in the device memory. To access this result, transfer the result data to the host.
  7. Call the hi_mpi_dvpp_free API to free the input and output buffers.
  8. Call the hi_mpi_vpc_destroy_chn API to destroy the channel.
  9. Call the hi_mpi_sys_exit API to deinitialize the media data processing system.
  10. Call aclrtResetDevice to reset the device and free the resources on the device.
  11. Call aclFinalize to deinitialize the system and free the resources used by the acl API in the process.

Sample Code for Image Resizing

The following is a code example of key steps of the image resizing function. It is for reference only and cannot be directly copied for compilation and running. After APIs are called, you need to add exception handling branches and record error logs and info logs.

You can click vpc_sample to obtain the sample.

 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
// 1. Initialize the media data processing system.
int32_t ret = hi_mpi_sys_init();

// 2. Create a channel.
hi_vpc_chn chnId;
hi_vpc_chn_attr stChnAttr;
ret = hi_mpi_vpc_sys_create_chn(&chnId, &stChnAttr);

//3. Perform resizing.
// 3.1 Construct a struct for storing input image information.
hi_vpc_pic_info inputPic;
inputPic.picture_width = 1920;
inputPic.picture_height = 1080;
inputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
inputPic.picture_width_stride = 1920;
inputPic.picture_height_stride = 1080;
inputPic.picture_buffer_size = inputPic.picture_width_stride * inputPic.picture_height_stride * 3 / 2;

//3.2 Prepare input image data.
//Load the input image into the device buffer. The ReadPicFile function is defined by the user.
ReadPicFile(picName, inputPic.picture_address, inputPic.picture_buffer_size);

// 3.3 Construct a struct for storing output image information.
hi_vpc_pic_info outputPic;
outputPic.picture_width = 960;
outputPic.picture_height  = 540;
outputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
outputPic.picture_width_stride = 960;
outputPic.picture_height_stride = 540;
outputPic.picture_buffer_size = outputPic.picture_width_stride * outputPic.picture_height_stride * 3 / 2;
ret = hi_mpi_dvpp_malloc(0, &outputPic.picture_address, outputPic.picture_buffer_size);

//Initialize the buffer.
memset(outputPic.picture_address, 0, outputPic.picture_buffer_size);

//3.4 Call the image resizing API.
uint32_t taskID = 0;
ret = hi_mpi_vpc_resize(chnId, &inputPic, &outputPic, 0, 0, 0, &taskID, -1);

// 3.5 Wait until the task processing is complete. The output image data is stored in the buffer specified by outputPic.picture_address.
uint32_t taskIDResult = taskID;
ret = hi_mpi_vpc_get_process_result(chnId, taskIDResult, -1);

//3.6 The output image data of VPC can be directly used as the input for model inference.
//You can directly use the output image data of VPC in the buffer specified by outputPic.picture_address.
// TODO: inference-related code logic


//3.7 Free the input and output buffers.
ret = hi_mpi_dvpp_free(inputPic.picture_address);
ret = hi_mpi_dvpp_free(outputPic.picture_address);

// 4. Destroy the channel.
ret = hi_mpi_vpc_destroy_chn(chnId);

//5. Deinitialize the media data processing system.
ret = hi_mpi_sys_exit();

// ....

Sample Code for Image Cropping

The following is a code example of key steps of the image cropping function. It is for reference only and cannot be directly copied for compilation and running. After APIs are called, you need to add exception handling branches and record error logs and info logs.

You can click vpc_sample to obtain the sample.

 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
// 1. Initialize the media data processing system.
int32_t ret = hi_mpi_sys_init();

// 2. Create a channel.
hi_vpc_chn chnId;
hi_vpc_chn_attr stChnAttr;
ret = hi_mpi_vpc_sys_create_chn(&chnId, &stChnAttr);

//3. Perform image cropping.
//3.1 Construct a struct for storing input image information.
hi_vpc_pic_info inputPic;
inputPic.picture_width = 1920;
inputPic.picture_height = 1080;
inputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
inputPic.picture_width_stride = 1920;
inputPic.picture_height_stride = 1080;
inputPic.picture_buffer_size = inputPic.picture_width_stride * inputPic.picture_height_stride * 3 / 2;

//3.2 Prepare input image data.
//Allocate the device buffer for media data processing.
ret = hi_mpi_dvpp_malloc(0, &inputPic.picture_address, inputPic.picture_buffer_size);

//Load the input image into the device buffer. The ReadPicFile function is defined by the user.
ReadPicFile(picName, inputPic.picture_address, inputPic.picture_buffer_size);

//3.3 Construct a struct for storing output image information.
//This parameter indicates the number of crop ROIs.
uint32_t multiCount = 1;
//The size of the cropRegionInfos array must be consistent with the number of crop ROIs.
hi_vpc_crop_region_info cropRegionInfos[1];
hi_vpc_pic_info outputPic;
for (uint32_t i = 0; i < multiCount; i++) {
    outputPic.picture_width = 960;
    outputPic.picture_height  = 540;
    outputPic.picture_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420;
    outputPic.picture_width_stride = 960;
    outputPic.picture_height_stride = 540;
    outputPic.picture_buffer_size = outputPic.picture_width_stride * outputPic.picture_height_stride * 3 / 2;
    ret = hi_mpi_dvpp_malloc(0, &outputPic.picture_address, outputPic.picture_buffer_size);

    //Initialize the buffer.
    memset(outputPic.picture_address, 0, outputPic.picture_buffer_size);
    
    //Crop a 960 x 540 ROI from the input image with the upper-left corner as the origin.
    cropRegionInfos[i].dest_pic_info = outputPic;
    cropRegionInfos[i].crop_region.left_offset = 0;
    cropRegionInfos[i].crop_region.top_offset = 0;
    cropRegionInfos[i].crop_region.crop_width = 960;
    cropRegionInfos[i].crop_region.crop_height = 540;
}

//3.4 Call the image cropping API.
uint32_t taskID = 0;
ret = hi_mpi_vpc_crop(chnId, &inputPic, cropRegionInfos, 1, &taskID, -1);

//3.5 Wait until the task processing is complete. The output image data is stored in the buffer specified by outputPic.picture_address.
uint32_t taskIDResult = taskID;
ret = hi_mpi_vpc_get_process_result(chnId, taskIDResult, -1);

//3.6 The output image data of VPC can be directly used as the input for model inference.
//You can directly use the output image data of VPC in the buffer specified by outputPic.picture_address.
// TODO: inference-related code logic

//3.7 Free the input and output buffers.
ret = hi_mpi_dvpp_free(inputPic.picture_address);
inputPic.picture_address = nullptr;
for (uint32_t i = 0; i < multiCount; i++) {
     hi_mpi_dvpp_free(cropRegionInfos[i].dest_pic_info.picture_address);
     cropRegionInfos[i].dest_pic_info.picture_address = nullptr;
}

//4. Destroy the channel.
ret = hi_mpi_vpc_destroy_chn(chnId);

//5. Deinitialize the media data processing system.
ret = hi_mpi_sys_exit();

// ....