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.

TDA4VH-Q1: Is it able to Create display node, then keep changing the display image while running graph?

Part Number: TDA4VH-Q1

Hi experts,

I'm trying to display different images while running the graph (like single-cam app example).

How I want to do is:

1. receive 4 cv::mat

2. resize and concat into 1 cv::mat

3. convert into vx image

4. display this image

Then keep looping through it.

Last time you provided the code for image display, but it can only display a fixed image.

/*
*
* Copyright (c) 2017 Texas Instruments Incorporated
*
* All rights reserved not granted herein.
*
* Limited License.
*
* Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
* license under copyrights and patents it now or hereafter owns or controls to make,
* have made, use, import, offer to sell and sell ("Utilize") this software subject to the
* terms herein.  With respect to the foregoing patent license, such license is granted
* solely to the extent that any such patent is necessary to Utilize the software alone.
* The patent license shall not apply to any combinations which include this software,
* other than combinations with devices manufactured by or for TI ("TI Devices").
* No hardware patent is licensed hereunder.
*
* Redistributions must preserve existing copyright notices and reproduce this license
* (including the above copyright notice and the disclaimer and (if applicable) source
* code license limitations below) in the documentation and/or other materials provided
* with the distribution
*
* Redistribution and use in binary form, without modification, are permitted provided
* that the following conditions are met:
*
* *       No reverse engineering, decompilation, or disassembly of this software is
* permitted with respect to any software provided in binary form.
*
* *       any redistribution and use are licensed by TI for use only with TI Devices.
*
* *       Nothing shall obligate TI to provide you with source code for the software
* licensed and provided to you in object code.
*
* If software source code is provided to you, modification and redistribution of the
* source code are permitted provided that the following conditions are met:
*
* *       any redistribution and use of the source code, including any resulting derivative
* works, are licensed by TI for use only with TI Devices.
*
* *       any redistribution and use of any object code compiled from the source code
* and any resulting derivative works, are licensed by TI for use only with TI Devices.
*
* Neither the name of Texas Instruments Incorporated nor the names of its suppliers
*
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* DISCLAIMER.
*
* THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#include <stdio.h>
#include <VX/vx.h>
#include <TI/tivx.h>
#include <vx_internal.h>
#include <TI/video_io_kernels.h>
#include <TI/video_io_display.h>
#include <utils/app_init/include/app_init.h>


static vx_status readYUVInput(char* file_name, vx_image in_img)
{
    vx_status status;

    FILE * fp = fopen(file_name,"rb");
    vx_int32 j;

    if(fp == NULL)
    {
        printf("Unable to open file %s \n", file_name);
        return (VX_FAILURE);
    }

    vx_rectangle_t rect;
    vx_imagepatch_addressing_t image_addr;
    vx_map_id map_id;
    void * data_ptr;
    vx_uint32  img_width;
    vx_uint32  img_height;
    vx_uint32  num_bytes = 0;

    vxQueryImage(in_img, VX_IMAGE_WIDTH, &img_width, sizeof(vx_uint32));
    vxQueryImage(in_img, VX_IMAGE_HEIGHT, &img_height, sizeof(vx_uint32));

    printf("%d x %d \n", img_width, img_height);

    rect.start_x = 0;
    rect.start_y = 0;
    rect.end_x = img_width;
    rect.end_y = img_height;
    status = vxMapImagePatch(in_img,
                            &rect,
                            0,
                            &map_id,
                            &image_addr,
                            &data_ptr,
                            VX_WRITE_ONLY,
                            VX_MEMORY_TYPE_HOST,
                            VX_NOGAP_X);

    /* Copy Luma */
    for (j = 0; j < img_height; j++)
    {
        num_bytes += fread(data_ptr, 1, img_width, fp);
        data_ptr += image_addr.stride_y;
    }
    printf("data_ptr = 0x%p\n", data_ptr);

    if(num_bytes != (img_width*img_height))
    {
        printf("Luma bytes read = %d, expected = %d\n", num_bytes, img_width*img_height);
    }
    else
    {
        printf("Luma bytes success read = %d, expected = %d\n", num_bytes, img_width*img_height);
    }

    vxUnmapImagePatch(in_img, map_id);

    rect.start_x = 0;
    rect.start_y = 0;
    rect.end_x = img_width;
    rect.end_y = img_height / 2;
    status = vxMapImagePatch(in_img,
                            &rect,
                            1,
                            &map_id,
                            &image_addr,
                            &data_ptr,
                            VX_WRITE_ONLY,
                            VX_MEMORY_TYPE_HOST,
                            VX_NOGAP_X);

    /* Copy CbCr */
    num_bytes = 0;
    for (j = 0; j < img_height/2; j++)
    {
        num_bytes += fread(data_ptr, 1, img_width, fp);
        data_ptr += image_addr.stride_y;
    }
    printf("U data_ptr = 0x%p\n", data_ptr);

    if(num_bytes != (img_width*img_height/2))
    {
        printf("CbCr bytes read = %d, expected = %d\n", num_bytes, img_width*img_height/2);
    }
    else
    {
        printf("CbCr bytes success read = %d, expected = %d\n", num_bytes, img_width*img_height/2);
    }

    vxUnmapImagePatch(in_img, map_id);

    fclose(fp);

    return(status);
}

static vx_status writeYUVInput(char* file_name, vx_image out_img)
{
    vx_status status;

    FILE * fp = fopen(file_name,"wb");
    vx_int32 j;

    if(fp == NULL)
    {
        printf("Unable to open file %s \n", file_name);
        return (VX_FAILURE);
    }

    vx_rectangle_t rect;
    vx_imagepatch_addressing_t image_addr;
    vx_map_id map_id;
    void * data_ptr;
    vx_uint32  img_width;
    vx_uint32  img_height;
    vx_uint32  num_bytes = 0;

    vxQueryImage(out_img, VX_IMAGE_WIDTH, &img_width, sizeof(vx_uint32));
    vxQueryImage(out_img, VX_IMAGE_HEIGHT, &img_height, sizeof(vx_uint32));

    rect.start_x = 0;
    rect.start_y = 0;
    rect.end_x = img_width;
    rect.end_y = img_height;
    status = vxMapImagePatch(out_img,
                            &rect,
                            0,
                            &map_id,
                            &image_addr,
                            &data_ptr,
                            VX_READ_ONLY,
                            VX_MEMORY_TYPE_HOST,
                            VX_NOGAP_X);

    /* Copy Luma */
    for (j = 0; j < img_height; j++)
    {
        num_bytes += fwrite(data_ptr, 1, img_width, fp);
        data_ptr += image_addr.stride_y;
    }
    printf("O data_ptr = 0x%p\n", data_ptr);

    if(num_bytes != (img_width*img_height))
        printf("Luma bytes written = %d, expected = %d\n", num_bytes, img_width*img_height);

    vxUnmapImagePatch(out_img, map_id);

    rect.start_x = 0;
    rect.start_y = 0;
    rect.end_x = img_width;
    rect.end_y = img_height / 2;
    status = vxMapImagePatch(out_img,
                            &rect,
                            1,
                            &map_id,
                            &image_addr,
                            &data_ptr,
                            VX_READ_ONLY,
                            VX_MEMORY_TYPE_HOST,
                            VX_NOGAP_X);

    /* Copy CbCr */
    num_bytes = 0;
    for (j = 0; j < img_height/2; j++)
    {
        num_bytes += fwrite(data_ptr, 1, img_width, fp);
        data_ptr += image_addr.stride_y;
    }
    printf("OU data_ptr = 0x%p\n", data_ptr);

    if(num_bytes != (img_width*img_height/2))
        printf("CbCr bytes written = %d, expected = %d\n", num_bytes, img_width*img_height/2);

    vxUnmapImagePatch(out_img, map_id);

    fclose(fp);

    return(status);
}

/**
 * \brief Tutorial Entry Point
 */
int main()
{
    int status = 0;
    tivx_display_params_t display_params;
    vx_user_data_object display_param_obj;
    vx_node displayNode;
    vx_image display_image;
    int i = 0;
    vx_imagepatch_addressing_t  input_image_addr, display_image_addr;
    tivx_obj_desc_image_t *input_obj_desc = NULL;
    tivx_obj_desc_image_t *output_obj_desc = NULL;

    status = appInit();

    if(status == VX_SUCCESS)
    {

        vx_context context = vxCreateContext();

        tivxVideoIOLoadKernels(context);

        vx_graph graph = vxCreateGraph(context);

        memset(&display_params, 0, sizeof(tivx_display_params_t));
        display_params.opMode = TIVX_KERNEL_DISPLAY_ZERO_BUFFER_COPY_MODE;
        display_params.pipeId = 2;
        display_params.outHeight = OUTPUT_TEX_HEIGHT;
        display_params.outWidth = OUTPUT_TEX_WIDTH;
        display_params.posX = 0;
        display_params.posY = 0;

        display_image = vxCreateImage(context, OUTPUT_TEX_WIDTH, OUTPUT_TEX_HEIGHT, VX_DF_IMAGE_NV12);

        // Display Initialization    

        display_param_obj = vxCreateUserDataObject(context, "tivx_display_params_t", sizeof(tivx_display_params_t), &display_params);
        displayNode = tivxDisplayNode(graph, display_param_obj, display_image);

        if(status == VX_SUCCESS)
        {
            status = vxSetNodeTarget(displayNode, VX_TARGET_STRING, TIVX_TARGET_DISPLAY1);
            printf("Display Set Target done\n");
        }

        if(status == VX_SUCCESS)
        {
            status = vxVerifyGraph(graph);
            printf("Verify Graph\n");
        }

        status = readYUVInput(IN_FILE_NAME, display_image);
        printf("Input file filled\n");

        if(status == VX_SUCCESS)
        {
            status = writeYUVInput(OUT_FILE_NAME, display_image);
            printf("Output file to test if the image read correctly before sending to display\n");
        }
        if(status == VX_SUCCESS)
        {
            if(status == VX_SUCCESS)
            {
                for(i = 0; i < LOOPCOUNT; i++)
                {
                    status = vxProcessGraph(graph);
                }
            }
        }


        if(status == VX_SUCCESS)
        {
            status = vxReleaseUserDataObject(&display_param_obj);

            status |= vxReleaseImage(&display_image);

            status |= vxReleaseNode(&displayNode);

            status |= vxReleaseGraph(&graph);

            tivxVideoIOUnLoadKernels(context);
    
            status |= vxReleaseContext(&context);
            printf("Release Graph and context\n");
        }
    }
    else
    {
        printf("app init fail \n");
    }

    return 0;
}

Is it able to keep displaying the new image without keep creating and deleting the graph?

Thanks.

  • Hi,

    You can put the readYUVInput or your equivalent function which does the step 1 to 3 inside the loop along with the vxProcessGraph(), to keep displaying new images.

    Currently, since this function is outside the for loop, it is displaying a fixed image, but if you bring it inside the loop and modify the image in each iteration, it shall display new images every iteration as you feed in.

    Regards,

    Nikhil

  • Hi,

    I tried to modify the image in the for loop.

    For example, I modified obj->display_image1 from 2 difference image preprocess functions.

    The image should change after the 50th iteration, but it still displayed the same image.

    Where should I modify next?

    vx_status app_run_graph(AppObj *obj)
    {
        vx_status status = VX_SUCCESS;
    
        if(status == VX_SUCCESS)
        {
            for(int i = 0; i < 100; i++)
            {
                if (i < 50) {
                    std::cout << "image_preprocess1: " << i << std::endl;
                    image_preprocess(obj);
    
                } else {
                    std::cout << "image_preprocess2: " << i << std::endl;
                    image_preprocess_2(obj);
                }
                status = vxProcessGraph(obj->graph);
                vxReleaseImage(&obj->display_image1);  
                // std::cout << "Processed iterations: " << i << std::endl;
            }
        }
    
        return status;
    }
    

  • This is my full example code for reference, thanks!

    #include <iostream>
    #include <stdexcept>
    
    //OpenVX includes
    #include <VX/vx.h>
    
    extern "C" 
    {
    #include <utils/app_init/include/app_init.h>
    #include <utils/grpx/include/app_grpx.h>
    #include "display_common.h"
    #include <TI/video_io_display.h>
    #include <TI/hwa_kernels.h>
    #include <TI/video_io_kernels.h>
    #include <TI/tivx.h>
    #include <TI/tivx_task.h>
    }
    
    #include "test_vximage_concat.h"
    
    //OpenCV includes
    #include "opencv2/core.hpp"
    #include "opencv2/imgproc.hpp"
    #include "opencv2/imgcodecs.hpp"
    #include "opencv2/highgui.hpp"
    
    vx_status app_init_display1(vx_context context, DisplayObj *displayObj, char *objName);
    
    void app_deinit_display1(DisplayObj *displayObj);
    
    void app_delete_display1(DisplayObj *displayObj);
    
    vx_status app_create_graph_display1(vx_graph graph, DisplayObj *displayObj, vx_image disp_image);
    
    vx_status app_run_graph(AppObj *obj);
    void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type);
    vx_status app_create_graph(AppObj *obj);
    inline vx_image vxCvMatToVxImage(const vx_context context, const cv::Mat &cv_image);
    vx_image convertCvMatToVxImage(vx_context context, cv::Mat image, bool toCopy);
    void image_preprocess(AppObj *obj);
    void image_preprocess_2(AppObj *obj);
    
    void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type)
    {
      AppObj *obj = &gAppObj;
    
      appGrpxDrawDefault(handle, draw2dBufInfo, update_type);
    
      if(update_type == 0)
      {
        Draw2D_FontPrm sHeading;
        Draw2D_FontPrm sAlgo1;
        Draw2D_FontPrm sAlgo2;
        Draw2D_FontPrm sAlgo3;
        Draw2D_FontPrm sAlgo4;
        Draw2D_FontPrm sAlgo5;
        Draw2D_FontPrm sAlgo6;
    
        Draw2D_BmpPrm bmp;
    
        sHeading.fontIdx = 5;
        Draw2D_drawString(handle, 620, 40, "Image Display Test", &sHeading);
    
        // sAlgo1.fontIdx = 1;
        // Draw2D_drawString(handle, INPUT_DISPLAY_WIDTH/2 - 120 , (DISPLAY_HEIGHT + INPUT_DISPLAY_HEIGHT)/2 - 75, "Display 1", &sAlgo1);
        // sAlgo1.fontIdx = 1;
        // Draw2D_drawString(handle, DISPLAY_WIDTH - (INPUT_DISPLAY_WIDTH2/2 + 120) , (DISPLAY_HEIGHT + INPUT_DISPLAY_HEIGHT2)/2 - 75, "Display 2", &sAlgo1);
      }
    
      return;
    }
    
    
    vx_status app_init(AppObj *obj)
    {
        app_grpx_init_prms_t grpx_prms;
        vx_status status = VX_SUCCESS;
    
        obj->context = vxCreateContext();
        if(status == VX_SUCCESS)
        {
            status = vxGetStatus((vx_reference) obj->context);
        }
    
        tivxHwaLoadKernels(obj->context);
    
        tivxVideoIOLoadKernels(obj->context);
    
        /* Initialize modules */
        if(status == VX_SUCCESS)
        {
            status = app_init_display1(obj->context, &obj->displayObj , "display1Obj");
        }
    
        if (1 == obj->displayObj.display_option)
        {
            appGrpxInitParamsInit(&grpx_prms, obj->context);
            grpx_prms.draw_callback = app_draw_graphics;
            appGrpxInit(&grpx_prms);
        }
        return status;
    }
    
    vx_status app_create_graph(AppObj *obj)
    {
        vx_status status = VX_SUCCESS;
    
        obj->graph = vxCreateGraph(obj->context);
    
        status = vxGetStatus((vx_reference) obj->graph);
    
        if (status == VX_SUCCESS)
        {
            status = app_create_graph_display1(obj->graph, &obj->displayObj, obj->display_image1);
        }
        if(status == VX_SUCCESS)
        {
            status = vxVerifyGraph(obj->graph);
        }
    
        return status;
    }
    
    vx_status app_run_graph(AppObj *obj)
    {
        vx_status status = VX_SUCCESS;
    
        if(status == VX_SUCCESS)
        {
            for(int i = 0; i < 100; i++)
            {
                if (i < 50) {
                    std::cout << "image_preprocess1: " << i << std::endl;
                    image_preprocess(obj);
    
                } else {
                    std::cout << "image_preprocess2: " << i << std::endl;
                    image_preprocess_2(obj);
                }
                status = vxProcessGraph(obj->graph);
                vxReleaseImage(&obj->display_image1);  
                // std::cout << "Processed iterations: " << i << std::endl;
            }
        }
    
        return status;
    }
    
    vx_status app_init_display1(vx_context context, DisplayObj *displayObj, char *objName)
    {
      vx_status status = VX_SUCCESS;
    
        if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (1 == displayObj->display_option))
        {
            memset(&displayObj->display_params1, 0, sizeof(tivx_display_params_t));
            displayObj->display_config1 = vxCreateUserDataObject(context, "tivx_display_params_t",
                 sizeof(tivx_display_params_t), NULL);
            APP_ASSERT_VALID_REF(displayObj->display_config1);
    
            vxSetReferenceName((vx_reference)displayObj->display_config1, "InputDisplayConfiguration");
    
            displayObj->display_params1.opMode=TIVX_KERNEL_DISPLAY_ZERO_BUFFER_COPY_MODE;
            displayObj->display_params1.pipeId = 2;
            displayObj->display_params1.outWidth = 1920;
            displayObj->display_params1.outHeight = 720;
            displayObj->display_params1.posX = 0;
            displayObj->display_params1.posY = 0;
    
            status = vxCopyUserDataObject(displayObj->display_config1, 0, sizeof(tivx_display_params_t), &displayObj->display_params1, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST);
            APP_ASSERT(status==VX_SUCCESS);
        }
      return status;
    }
    
    
    void app_deinit_display1(DisplayObj *displayObj)
    {
        if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (displayObj->display_option == 1))
        {
            vxReleaseUserDataObject(&displayObj->display_config1);
        }
    }
    
    
    void app_delete_display1(DisplayObj *displayObj)
    {
    
        if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (displayObj->display_option == 1))
        {
            vxReleaseNode(&displayObj->node1);
        }
    
    }
    
    vx_status app_create_graph_display1(vx_graph graph, DisplayObj *displayObj, vx_image disp_image)
    {
        vx_status status = VX_SUCCESS;
    
        if (vx_true_e == tivxIsTargetEnabled(TIVX_TARGET_DISPLAY1) && (displayObj->display_option == 1))
        {
            displayObj->node1 = tivxDisplayNode(
                graph,
                displayObj->display_config1,
                disp_image);
            status = vxGetStatus((vx_reference)displayObj->node1);
            if (VX_SUCCESS != status)
            {
                printf("# ERROR: Display is not enabled on this platform, please disable it in config \n");
            }
            APP_ASSERT(VX_SUCCESS == status);
            status = vxSetNodeTarget(displayObj->node1, VX_TARGET_STRING, TIVX_TARGET_DISPLAY1);
            APP_ASSERT(status==VX_SUCCESS);
            vxSetReferenceName((vx_reference)displayObj->node1, "Output Display");
            
        }
    
        return status;
    }
    
    
    inline vx_image vxCvMatToVxImage(const vx_context context, const cv::Mat &cv_image)
    {
        vx_df_image vx_image_type;
        switch (cv_image.type())
        {
        case CV_8UC1:
            vx_image_type = VX_DF_IMAGE_U8;
            break;
        case CV_8UC3:
            vx_image_type = VX_DF_IMAGE_RGB;
            break;
        default:
            return NULL;
        }
    
        int width = cv_image.cols;
        int height = cv_image.rows;
    
    
        vx_image image = vxCreateImage(context, width, height, vx_image_type);
    
        vx_rectangle_t patch;
        patch.start_x = 0;
        patch.start_y = 0;
        patch.end_x = width;
        patch.end_y = height;
    
        vx_map_id map_id;
        vx_imagepatch_addressing_t addr;
        unsigned char *ptr;
        vx_status status = vxMapImagePatch(image, &patch, 0, &map_id, &addr, (void **)&ptr, VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X);
        if (status != VX_SUCCESS)
        {
            return NULL;
        }
    
        if (addr.stride_x != 1 && addr.stride_x != 3)
        {
            return NULL;
        }
    
        for (int y = 0; y < height; y++)
        {
            unsigned char *ptr_y = ptr + y * addr.stride_y;
            memcpy(ptr_y, cv_image.ptr(y), addr.stride_y);
        }
    
        status = vxUnmapImagePatch(image, map_id);
        if (status != VX_SUCCESS)
        {
            return NULL;
        }
    
        return image;
    }
    
    void image_preprocess(AppObj *obj) {
            auto start = std::chrono::high_resolution_clock::now();
    
            // resize images
            cv::resize(obj->cv_image1, obj->cv_image1, cv::Size(1920/2, 360));
            cv::resize(obj->cv_image2, obj->cv_image2, cv::Size(1920/2, 360));
            cv::resize(obj->cv_image3, obj->cv_image3, cv::Size(1920/2, 360));
            cv::resize(obj->cv_image4, obj->cv_image4, cv::Size(1920/2, 360));
    
            auto end = std::chrono::high_resolution_clock::now();
            auto duration = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(end - start).count();
            std::cout << "Resized images: " << duration << " ms" << std::endl;
    
            // concat cvimage1, cvimage2, cvimage3, cvimage4
            cv::Mat cvimage_concat12;
            cv::Mat cvimage_concat34;
            cv::Mat cvimage_concat_all;
    
            auto start2 = std::chrono::high_resolution_clock::now();
    
            cv::hconcat(obj->cv_image1, obj->cv_image2, cvimage_concat12);
            cv::hconcat(obj->cv_image3, obj->cv_image4, cvimage_concat34);
            cv::vconcat(cvimage_concat12, cvimage_concat34, cvimage_concat_all);
    
            auto end2 = std::chrono::high_resolution_clock::now();
            auto duration2 = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(end2 - start2).count();
            std::cout << "Concatenated images: " << duration2 << " ms" << std::endl;
    
    
            auto start3 = std::chrono::high_resolution_clock::now();
    
            vx_image image1 = vxCvMatToVxImage(obj->context, cvimage_concat_all);
    
            auto end3 = std::chrono::high_resolution_clock::now();
            auto duration3 = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(end3 - start3).count();
            std::cout << "Cv image to vx image: " << duration3 << " ms" << std::endl;
    
            obj->display_image1 = image1;
    
    }
    
    void image_preprocess_2(AppObj *obj) {
            auto start = std::chrono::high_resolution_clock::now();
    
            // resize images
            cv::resize(obj->cv_image1, obj->cv_image1, cv::Size(1920/2, 360));
            cv::resize(obj->cv_image2, obj->cv_image2, cv::Size(1920/2, 360));
            cv::resize(obj->cv_image3, obj->cv_image3, cv::Size(1920/2, 360));
            cv::resize(obj->cv_image4, obj->cv_image4, cv::Size(1920/2, 360));
    
            auto end = std::chrono::high_resolution_clock::now();
            auto duration = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(end - start).count();
            std::cout << "Resized images: " << duration << " ms" << std::endl;
    
            // concat cvimage1, cvimage2, cvimage3, cvimage4
            cv::Mat cvimage_concat12;
            cv::Mat cvimage_concat34;
            cv::Mat cvimage_concat_all;
    
            auto start2 = std::chrono::high_resolution_clock::now();
    
            cv::hconcat(obj->cv_image1, obj->cv_image2, cvimage_concat12);
            cv::hconcat(obj->cv_image3, obj->cv_image4, cvimage_concat34);
            cv::vconcat(cvimage_concat34, cvimage_concat12, cvimage_concat_all);
    
            auto end2 = std::chrono::high_resolution_clock::now();
            auto duration2 = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(end2 - start2).count();
            std::cout << "Concatenated images: " << duration2 << " ms" << std::endl;
    
    
            auto start3 = std::chrono::high_resolution_clock::now();
    
            vx_image image1 = vxCvMatToVxImage(obj->context, cvimage_concat_all);
    
            auto end3 = std::chrono::high_resolution_clock::now();
            auto duration3 = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(end3 - start3).count();
            std::cout << "Cv image to vx image: " << duration3 << " ms" << std::endl;
    
            obj->display_image1 = image1;
    
    }
    
    int main()
    {
    
            // read image from file 
            std::string imgPath1 = "test.jpg";
            cv::Mat cvimage1 = cv::imread(imgPath1);
            cv::cvtColor(cvimage1, cvimage1, cv::COLOR_BGR2RGB);
            // resize image
            // cv::resize(cvimage1, cvimage1, cv::Size(1920/2, 1080/2));
            if (cvimage1.empty()) {
                throw std::runtime_error("Failed to read image from file1");
            }
    
            // read image from file 
            std::string imgPath2 = "test2.jpg";
            cv::Mat cvimage2 = cv::imread(imgPath2);
            cv::cvtColor(cvimage2, cvimage2, cv::COLOR_BGR2RGB);
            // resize image
            // cv::resize(cvimage2, cvimage2, cv::Size(1920/2, 1080/2));
            if (cvimage2.empty()) {
                throw std::runtime_error("Failed to read image from file2");
            }
    
            // read image from file 
            std::string imgPath3 = "test3.jpg";
            cv::Mat cvimage3 = cv::imread(imgPath3);
            cv::cvtColor(cvimage3, cvimage3, cv::COLOR_BGR2RGB);
            // resize image
            // cv::resize(cvimage3, cvimage3, cv::Size(1920/2, 1080/2));
            if (cvimage3.empty()) {
                throw std::runtime_error("Failed to read image from file3");
            }
    
            // read image from file 
            std::string imgPath4 = "test4.jpg";
            cv::Mat cvimage4 = cv::imread(imgPath4);
            cv::cvtColor(cvimage4, cvimage4, cv::COLOR_BGR2RGB);
            // resize image
            // cv::resize(cvimage4, cvimage4, cv::Size(1920/2, 1080/2));
            if (cvimage4.empty()) {
                throw std::runtime_error("Failed to read image from file4");
            }
            
        appInit();
        AppObj *obj = &gAppObj;
        obj->displayObj.display_option = 1;
        vx_status status = VX_SUCCESS;
        obj->cv_image1 = cvimage1;
        obj->cv_image2 = cvimage2;
        obj->cv_image3 = cvimage3;
        obj->cv_image4 = cvimage4;
    
        status = app_init(obj);
        for (int iter = 0; iter < 5; iter++)
        {   
            obj->display_image1 = vxCreateImage(obj->context, 1920, 720, VX_DF_IMAGE_RGB);
    
            auto start4 = std::chrono::high_resolution_clock::now();
    
            status = app_create_graph(obj);
            status = app_run_graph(obj);  
            app_delete_display1(&obj->displayObj);
            vxReleaseGraph(&obj->graph);
    
            auto end4 = std::chrono::high_resolution_clock::now();
            auto duration4 = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(end4 - start4).count();
            std::cout << "run graph: " << duration4 << " ms" << std::endl;
    
        }
        app_deinit_display1(&obj->displayObj);
        if (1 == obj->displayObj.display_option)
        {
            appGrpxDeInit();
        }
        tivxVideoIOUnLoadKernels(obj->context);
        tivxHwaUnLoadKernels(obj->context);
        vxReleaseContext(&obj->context);
    }

  • Hi,

    Are you able to run image_preprocess and image_preprocess_2 individually? i.e. are you able to stream both images as standalone?

    Regards,

    Nikhil

  • Hi,

    Yes, they can be executed individually.

  • Hi,

    I think I found the reason why the image didn't change, now I'm able to display images dynamically.

    Thanks for your help.