This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: Does LDC need padding?

Part Number: TDA4VM

Hello,

When I tested 640x480 input and 640x480 ouput, bilinear interpoation result at 639/640 colulmn and 479/480 row were always abnormal. LUT offset is zero and fraction is also zero at right/bottom most column/row.

After adding two row/column padding(input 642x482, output 640x480), I can get correct output.

Does this mean LDC need padding? Or I missed seeting requited for LUT to access two right/bottom most columns/rows?

Best regards,

Wilson.

  • Hi Wilson,

    The size of your LUT shall be "ceil(W/2^m + 1)" x "ceil(H/2^m + 1)" and it shall be continuous at the boundaries.
    In some sense, we pad the LUT rather than the input image.

    Please refer to the TDA4 LDC FAQ if you have more details: e2e.ti.com/.../faq-tda4vm-how-to-create-a-ldc-mesh-lut-for-fisheye-distortion-correction-on-tda4

    Best,
    Gang

  • Hi Gang,

    Boundary values are still abnormal. Could you review my code?

        //mesh param
        tivx_vpac_ldc_mesh_params_init(&mesh_param_);
        mesh_param_.mesh_frame_width = output_info_.width;
        mesh_param_.mesh_frame_height = output_info_.height;
        mesh_param_.subsample_factor = 0; //no sub sampling.
    
        //mesh image creation
        uint32_t lut_w = (uint32_t)ceil(mesh_param_.mesh_frame_width/pow(2.0, mesh_param_.subsample_factor))  + 1u;
        uint32_t lut_h = (uint32_t)ceil(mesh_param_.mesh_frame_height/pow(2.0, mesh_param_.subsample_factor)) + 1u;
        mesh_ = vxCreateImage(context_, lut_w, lut_h, VX_DF_IMAGE_U32);
    
        //LUT copy
        uint32_t w, h;
        w = output_info_.width;
        h = output_info_.height;
        /* Mesh copy*/
        vx_rectangle_t rect;
        rect.start_x = 0;
        rect.start_y = 0;
        rect.end_x = w;
        rect.end_y = h;
        vx_imagepatch_addressing_t image_addr;
        image_addr.dim_x    = w;
        image_addr.dim_y    = h;
        image_addr.step_x   = 1;
        image_addr.step_y   = 1;
        image_addr.stride_x = 4u;
        image_addr.stride_y = w*4u;
        int32_t status;
        status = vxCopyImagePatch(mesh_, &rect, 0, &image_addr,
                                  (uint8_t*)mesh_table_.get(),
                                  VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST);
        

    Best regards,

    Wilson.

  • Hi Wilson,

    I don't spot any issue in your code.

    What is abnormal in your output image?

  • Hi Gang,

    In case of 640x480 NV12 in/out with bi-linear interpoation,

    638/639 column and 478/479 row has different values than expected. 

    Could you provide C source code which generates bit exact result for NV12 bi-linear interpolation? No need to simulate hardware. 

    Best regards,

    Wilson.

  • Hi Wilson,

    OK, I see you expect the input and output to match in this special case with all 0 offsets.

    LDC H/W is designed to clip the pixel coordinates for the ease and safety of interpolation.
    In this special case and with NV12 (UV is down-sampled more than Y), LDC clips coordinates conservatively to avoid out of boundary pixels in bilinear interpolation.
    The expectation of LDC is that output image is completely within the boundary of input image including the extra pixel needed for interpolation.

    Best,
    Gang

  • Hi Gang,

    Thanks for clarifying. 

    I have one more question.  

    I could get bit exact result with following code for Y plane.

      inline uint8_t bilinear_Q_3(uint8_t p00, uint8_t p10, uint8_t p01, uint8_t p11, uint8_t x_frac, uint8_t y_frac) {
        uint32_t p00_q6 = p00*(8u-x_frac)*(8u-y_frac);
        uint32_t p10_q6 = p10*(   x_frac)*(8u-y_frac);
        uint32_t p01_q6 = p01*(8u-x_frac)*(   y_frac);
        uint32_t p11_q6 = p11*(   x_frac)*(   y_frac);
        return (uint8_t)((p00_q6+p10_q6+p01_q6+p11_q6+0x20u) >> 6u);
      }

    But it didn't work with UV plane and I found below code can generate bit exact result. Could you guide why LDC is using different interpolation for Y/UV?

      inline uint8_t bilinear_uv(uint8_t p00, uint8_t p10, uint8_t p01, uint8_t p11, uint8_t x_frac, uint8_t y_frac) {
        uint32_t p00_q6 = p00*(16u-x_frac)*(16u-y_frac);
        uint32_t p10_q6 = p10*(    x_frac)*(16u-y_frac);
        uint32_t p01_q6 = p01*(16u-x_frac)*(    y_frac);
        uint32_t p11_q6 = p11*(    x_frac)*(    y_frac);
        return (uint8_t)((p00_q6+p10_q6+p01_q6+p11_q6+0x80u) >> 8u);
      }
    

    Best regards,

    Wilson.

  • Hi Wilson,

    We cannot disclose these details on public forum.

    Best,
    Gang