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:内核输出不符合预期

Guru**** 2457760 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1481079/tda4vm-kernel-output-is-not-as-expected

器件型号:TDA4VM

工具与软件:

大家好、团队成员:

我正在使用 PSDK 08_02_00_05 (Linux+RTOS)。

我生成了一个内核、用于使用 LUT 调整1280x944到512x320 RGB 图像的大小。

该应用程序正在运行、没有出现任何问题、但内核输出不符合预期。 它采用白色和黑色虚线图像。 我在内核中转储到了我的函数中、我能够获得我期望的输出。 请查找随附的文件、并告诉我为什么输出映像无法正确传递到下一个节点。 如果我错过了什么、请告诉我。

e2e.ti.com/.../vx_5F00_resolution_5F00_resize_5F00_target.cpp

此致、

Chaitanya Prakash Uppala

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Chaitanya、

    但是、您使用哪个内核来使用 LUT 调整 RGB 格式的大小?  

    此致、

    Brijesh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Brijesh:

    为了实现这一目标、我正在开发定制内核。

    此致、

    Chaitanya Prakash Uppala

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Chaitanya、

    为什么要在过程函数中更改输出图像缓冲区的大小?

    output_image_desc->mem_size[0]=491520;

    当您说内核中的映像正确时、您是指 raW_dump.bin 吗? 但在这里、您使用以下语句仅节省了100个字节?  

    fwrite(output_image_target_ptr , 1, 100 、FP);

    此外、您如何在应用中访问输出映像?

    此致、

    Brijesh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    output_image_desc->mem_size[0]=491520;

    我不是要更改缓冲区大小。 我刚才添加了该行、以确保分配正确的缓冲区大小(512x320x3=491520)。 即使没有添加这一行、我在使用  printf 打印时也会得到与491520相同的大小("output_image_desc->mem_size[0] is %d \n"、output_image_desc->mem_size[0]);

    在添加和不添加此行的情况下、应用程序的行为保持不变。

    [报价 userid="80721" url="~/support/processors-group/processors/f/processors-forum/1481079/tda4vm-kernel-output-is-not-as-expected/5686951 #5686951"]

    fwrite(output_image_target_ptr , 1, 100 、FP);

    [报价]

    我正在尝试检查前100个字节的值、以确保输出指针的值。

    如果您说内核中的映像正确、您是指 raw_dump.bin

    对调试打印造成的任何混淆深表歉意。  

    在中  转换 FevToLdc  函数我有一个名为的子函数  处理器单映像。  在这个函数中、我将转储输出、如下所示。

    void processSingleImage(std::vector<unsigned char>& inputImg,
                            std::vector<unsigned char>& outputImg,
                            SRLUT_RGB& lutConverter) {
        try {
            // Ensure input image is not empty
            if (inputImg.empty()) {
                throw std::runtime_error("Error: Input image data is empty!");
            }
    
            // Process image using LUT converter
            outputImg = lutConverter.sphere2cyl_bgr(inputImg);
    
            // Validation check
            if (outputImg.empty()) {
                throw std::runtime_error("Error: Converted image data is empty!");
            }
            if (outputImg.size() != static_cast<size_t>(ldcWidth * ldcHeight * NUM_CHANNELS)) {
                throw std::runtime_error("Error: Converted image size mismatch!");
            }
    
            // Save the processed image
            std::string output_path =  "./cylindrical_output.jpg";
            if (!stbi_write_jpg(output_path.c_str(), ldcWidth, ldcHeight, NUM_CHANNELS, outputImg.data(), 100)) {
                throw std::runtime_error("Error: Could not save the output image!");
            }
    
            std::cout << "Cylindrical image saved at: " << output_path << std::endl;
        }
        catch (const std::exception& e) {
            std::cerr << "Exception caught: " << e.what() << std::endl;
        }
    }

    我转储的 cylindrical_output.jpg 文件与要求匹配(即根据 LUT 调整大小并重新映射到512x320)。

    [报价 userid="80721" url="~/support/processors-group/processors/f/processors-forum/1481079/tda4vm-kernel-output-is-not-as-expected/5686951 #5686951"]

    此外、您如何在应用中访问输出映像?

    [报价]

    static vx_status app_create_graph(AppObj *obj)
    {
        vx_status status = VX_SUCCESS;
        vx_graph_parameter_queue_params_t graph_parameters_queue_params_list[2];
        vx_int32 graph_parameter_index;
        obj->graph = vxCreateGraph(obj->context);
        status = vxGetStatus((vx_reference)obj->graph);
        //vx_char output_file_name[APP_MAX_FILE_PATH];
    
        if(status == VX_SUCCESS)
        {
            status = vxSetReferenceName((vx_reference)obj->graph, "OpenVxGraph");
        }
        if(status == VX_SUCCESS)
        {
            status = app_create_graph_res_resize(obj->graph, &obj->resResizeObj, obj->input.arr[0]);
            APP_PRINTF(" app_create_graph_res_resize graph done!\n");
        }
        if(status == VX_SUCCESS)
        {
            status = app_create_graph_color_conv_RGB_NV12(obj->graph, &obj->colorConvRGBNV12Obj, obj->resResizeObj.output_image_arr);
            APP_PRINTF(" app_create_graph_color_conv_RGB_NV12 graph done!\n");
        }
    
        if(status == VX_SUCCESS)
        {
            //status = app_create_graph_ldc(obj->graph, &obj->ldcObj, obj->colorConvRGBNV12Obj.dst_image_arr);
            //APP_PRINTF("LDC graph done!\n");
        }
        if(status == VX_SUCCESS)
        {
            status = app_create_graph_scaler(obj->context, obj->graph, &obj->scalerObj,obj->colorConvRGBNV12Obj.dst_image_arr);
            APP_PRINTF("scaler Create Done! \n");
        }
        if(status == VX_SUCCESS)
        {
            status = app_create_graph_pre_proc(obj->graph, &obj->preProcObj, obj->scalerObj.output[0].arr);
            APP_PRINTF("pre proc Create Done! \n");
        }
        if(status == VX_SUCCESS)
        {
            status = app_create_graph_tidl(obj->context, obj->graph, &obj->tidlObj, obj->preProcObj.output_tensor_arr);
            APP_PRINTF("TIDL Create Done! \n");
        }
        if(status == VX_SUCCESS)
        {
            status = app_rci_create_graph_postproc(obj->graph, &obj->rcipostprocObj, obj->tidlObj.output_tensor_arr);
            APP_PRINTF("RCI Create Postproc Done!\n");
        }
    
    #ifdef APP_ENABLE_PIPELINE_FLOW
        /* Scalar Node - input is in Index 0 */
        if(status == VX_SUCCESS)
        {
            graph_parameter_index = 0;
            status = add_graph_parameter_by_node_index(obj->graph, obj->resResizeObj.node, 0);
            obj->resResizeObj.graph_parameter_index = graph_parameter_index;
            graph_parameters_queue_params_list[graph_parameter_index].graph_parameter_index = graph_parameter_index;
            graph_parameters_queue_params_list[graph_parameter_index].refs_list_size = APP_BUFFER_Q_DEPTH;
            graph_parameters_queue_params_list[graph_parameter_index].refs_list = (vx_reference*)&obj->input_images[0];
            graph_parameter_index++;
        }
        /*if(status == VX_SUCCESS)
        {
            graph_parameter_index = 0;
            status = add_graph_parameter_by_node_index(obj->graph, obj->colorConvRGBNV12Obj.node, 0);
            obj->colorConvRGBNV12Obj.graph_parameter_index = graph_parameter_index;
            graph_parameters_queue_params_list[graph_parameter_index].graph_parameter_index = graph_parameter_index;
            graph_parameters_queue_params_list[graph_parameter_index].refs_list_size = APP_BUFFER_Q_DEPTH;
            graph_parameters_queue_params_list[graph_parameter_index].refs_list = (vx_reference*)&obj->input_images[0];
            graph_parameter_index++;
        }*/
        if(status == VX_SUCCESS)
        {
            status = vxSetGraphScheduleConfig(obj->graph,
                        VX_GRAPH_SCHEDULE_MODE_QUEUE_AUTO,
                        graph_parameter_index,
                        graph_parameters_queue_params_list);
        }
        if(status == VX_SUCCESS)
        {
            status = tivxSetGraphPipelineDepth(obj->graph, APP_PIPELINE_DEPTH);
        }
        if(status == VX_SUCCESS)
        {
            tivxSetNodeParameterNumBufByIndex(obj->resResizeObj.node, 2,1);
        }
        if(status == VX_SUCCESS)
        {
            tivxSetNodeParameterNumBufByIndex(obj->colorConvRGBNV12Obj.node, 2,1);
        }
        if(status == VX_SUCCESS)
        {
            //tivxSetNodeParameterNumBufByIndex(obj->ldcObj.node, 7,1);
        }
        if(status == VX_SUCCESS)
        {
            status = tivxSetNodeParameterNumBufByIndex(obj->scalerObj.node, 1, 2);
        }
        if(status == VX_SUCCESS)
        {
            status = tivxSetNodeParameterNumBufByIndex(obj->scalerObj.node, 2, 6);
        }
        if(status == VX_SUCCESS)
        {
            status = tivxSetNodeParameterNumBufByIndex(obj->preProcObj.node, 2, 2);
        }
        if(status == VX_SUCCESS)
        {
            status = tivxSetNodeParameterNumBufByIndex(obj->tidlObj.node, 4, 2);
        }
        if(status == VX_SUCCESS)
        {
            status = tivxSetNodeParameterNumBufByIndex(obj->tidlObj.node, 7, 2);
        }
        if(status == VX_SUCCESS)
        {
            status = tivxSetNodeParameterNumBufByIndex(obj->rcipostprocObj.node, 2, 2);
        }
    #endif
    
        return status;
    }

    此致、

    Chaitanya Prakash Uppala

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Chaitanya、

    我没有更改缓冲区大小。 我刚才添加了该行以确保分配正确的缓冲区大小(512x320x3=491520)

    不应对此进行更改。 框架将根据不同的参数计算大小、您可以将其用作只读参数、但不应更新它。  

    此外、如何在应用程序中访问输出映像?

    抱歉、此代码未说明如何保存输出图像。  

    此致、

    Brijesh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Brijesh:

    这不应更改。 框架将根据不同的参数计算大小、您可以将其用作只读参数、但不应更新它。  [报价]

    感谢您提供的投入。 如上所述、我在内核的创建函数中也使用了相同的方法。 在"过程函数"中、我刚才添加了以确保正确通过。 此外、删除行(output_image_desc->mem_size[0]=491520;)不会更改输出行为。

    [报价 userid="80721" url="~/support/processors-group/processors/f/processors-forum/1481079/tda4vm-kernel-output-is-not-as-expected/5688374 #5688374"]

    抱歉、此代码未说明如何保存输出图像。  

    [报价]

    在中 处理器单映像 函数、行号23用于转储用于调试的输出映像。  STBI_WRITE_jpg 函数用于转储输出图像。 第11行执行我所需的操作(使用 LUT 调整大小和重映射)。

    此致、

    Chaitanya Prakash Uppala

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Chaitanya、

    此外、如何在应用程序中访问输出映像?

    我的意思是、如何保存输出映像? 这里共享的代码只从模块文件夹调用很少的 API、然后调用很少的 OpenVX API、但不会保存输出图像。  

    本质上、我希望查看您是否正确映射输出缓冲区、然后保存输出图像。 这必须是访问应用域中的缓冲区。  

    此致、

    Brijesh

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Brijesh:

    我指的是应用程序代码、如何保存输出映像? 这里共享的代码只从模块文件夹调用很少的 API、然后调用很少的 OpenVX API、但不会保存输出图像。  [报价]

    是什么意思? 如果是、在我的函数末尾附近、我使用 stbi_WRITE_jpg 函数转储、还使用了 上述文件中存在的 dump_rgb_bmp 函数。

    如果大家提到应用级别、我已经在 APP_RUN_graph_for_one_frame_pipeline 中使用了以下代码段。

    vx_image src_image2 =(vx_image) vxGetObjectArrayItem (obj->ressizeObj.output_image_arr、0);
    snprintf (output_file_name、app_MAX_file_path、"%s/resize_output_img_arr.bmp"、obj->output_file_path);
    tivx_utils_save_vximage_to_bmpfile (output_file_name、src_image2);

    此致、

    Chaitanya Prakash Uppala

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    在该文件中、在我的函数调用  convertFevToLdc (inputImg、lutTable、outputImg)后; 在行号 :248、 我添加了 std:memcpy (output_image_target_char、outputImg.data ()、outputg.size ()*未签名的当前问题[/尺寸]。

    好的、哪一个问题得到了解决? 它现在是否与应用输出匹配?  

    您是指内核级别? 如果是、在我的函数末尾附近、我使用 stbi_WRITE_jpg 函数转储、还使用了 上述文件中存在的 dump_rgb_bmp 函数。[/QUOT]

    是的、但 这只是 API 调用、因此不确定此 API 包含的内容。  

    您是否比较 Res_resizeOutput_img.bmp 和 raW_dump.bin? 它似乎是从同一输出指针转储的、但一个是带有标头的 bmp 图像、第二个则仅为原始文件。 您比较是否正确?

    此致、

    Brijesh

    [/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Brijesh:

    [报价 userid="80721" url="~/support/processors-group/processors/f/processors-forum/1481079/tda4vm-kernel-output-is-not-as-expected/5692935 #5692935"]

    好的、哪一个问题得到了解决? 它现在是否与应用输出匹配?  

    [报价]

    我提到的内核输出是白色和黑色虚线图像的问题现在得到解决,并能够在内核输出中获得适当的像素。

    [报价 userid="80721" url="~/support/processors-group/processors/f/processors-forum/1481079/tda4vm-kernel-output-is-not-as-expected/5692935 #5692935"]

    是的、但 这只是 API 调用、因此不确定此 API 包含的内容。  

    [报价]

    stbi_WRITE_jpg 是一个开源 API。  

    您正在对比 Res_resizeOutput_img.bmp 和 raw_dump.bin 吗? 它似乎是从同一输出指针转储的、但一个是带有标头的 bmp 图像、第二个则仅为原始文件。 您比较是否正确?

    由于内核的输出是白色和黑色的虚线图像,而不是正确的像素,我试图转储前100个字节,以检查值是指向255 (白色)还是其他一些值。 我只是转储原始 bin、因为我知道这些 values..not 用于与 bmp 图像进行比较。

    希望现在清楚。

    此致、

    Chaitanya Prakash Uppala

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    当然、 Chaitanya、您是否还有关于该主题的其他问题? 否则、请关闭该主题。