Part Number:SK-TDA4VM
TI专家您好,
关于如何从opencv创建的Mat类型的数据如何在TIOVX中利用vxNorNode的取反操作时,我发现利用vx_image in_img1 vxCreateImageFromHandle(context,VX_DF_IMAGE_U8,&addr,&ptr,VX_MEMORY_TYPE_HOST)从opencv获取的图像,在进行vxNorNode后并未输出算法效果。
而另外一种将opencv的数据通过imwrite写到本地后,再利用vx_image in_img2 tivx_utils_create_vximage_from_bmpfile加载出来的图像,在进行vxNorNode后则能执行取反算法。
对此,我比较疑惑,vxCreateImageFromHandle的用法不就是创建对外部分配图像对象的引用吗?而opencv创建Mat对象的地址相关信息已传给vxCreateImageFromHandle,且通过vxQueryImage获取in_img1的图像相关属性和in_img2的都是一摸一样,且两者在vxNorNode节点操作前打印的像素值也是一致的,但vx_node node0=vxNotNode(graph,in_img1,out_img)和node0=vxNotNode(graph,in_img2,out_img)后,打印 out_img 的像素值,前者却没有进行图像取反操作。
是否vxCreateImageFromHandle从外部系统获取的图像不能直接进行图像的相关处理?如果确实不能这样直接操作的话,那么是否只能用后者的方式,那么关于vxCreateImageFromHandle的用法又该如何利用呢?而通过保存到本地再加载出来处理的方式是否比较耗时呢?
望不吝赐教,期待您的回复!
best wish!
Ling Wang
opencv创建图像的代码如下:
vx_uint32 width=16;
vx_uint32 height=5;
cv::Mat img(height,width,CV_8UC1,Scalar(0));
img(Rang(1,5),Rang(1,5))=Scalar(255);
//imwrite("inImg_cvSave.bmp",img);
vx_imagepatch_addressing_t addr;
addr.dim_x=width;
addr.dim_y=height;
addr.stride_x=1;
addr.stride_y=16;
addr.step_x=1;
addr.step_y=1;
addr.scale_x=VX_SCALE_UNITY;
addr.scale_y=VX_SCALE_UNITY;
void * ptr=img.data;
Cherry Zhou:
您好,您的问题我们已升级到英文论坛寻求帮助,链接如下:
https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1249571/sk-tda4vm-the-image-created-by-opencv-is-processed-in-tiovx
,
Cherry Zhou:
您好,
使用从 vxCreateImageFromHandle 创建的输入映像执行 vxNorNode ()时是否出现任何错误? 如果有的话,您能否分享下运行此应用程序的log?
,
wang ling:
************************************************************************代码*******************************************************************void show_image_all_pixel(vx_image in_img){ vx_uint32 width; vx_uint32 height;
vxQueryImage(in_img, (vx_enum)VX_IMAGE_WIDTH, &width, sizeof(vx_uint32)); vxQueryImage(in_img, (vx_enum)VX_IMAGE_HEIGHT, &height, sizeof(vx_uint32));
vx_map_id map_id_in; vx_rectangle_t rect_in = {0, 0, width, height}; vx_imagepatch_addressing_t map_addr_in; vx_uint8* map_ptr_in; vxMapImagePatch(in_img, &rect_in, 0, &map_id_in, &map_addr_in, (void **)&map_ptr_in, VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X);
printf("/************************************打印图像像素值************************************/\n"); volatile vx_uint32 i,j,k; i=j=k=0; for(volatile vx_uint32 y = 0; y < map_addr_in.dim_y; y+=map_addr_in.step_y) { j = (map_addr_in.stride_y*y*map_addr_in.scale_y)/VX_SCALE_UNITY; for (volatile vx_uint32 x = 0; x < map_addr_in.dim_x; x+=map_addr_in.step_x) { i = j + (map_addr_in.stride_x*x*map_addr_in.scale_x)/VX_SCALE_UNITY; k++; if (0 == k%width) { printf("%u\n", *(map_ptr_in+i)); } else { printf("%u, ", *(map_ptr_in+i)); } } } printf("/************************************打印图像像素值结束************************************/\n"); vxUnmapImagePatch(in_img, map_id_in);}
void main(void){ vx_uint32 width = 16; vx_uint32 height = 5;
// 创建opencv图像 Mat img(height,width,CV_8UC1,Scalar(0)); img(Range(1,5), Range(1,5)) = Scalar(255); printf("opencv创建图像(高*宽*通道数):%d*%d*%d\n", img.rows, img.cols, img.channels()); cout << "img.elemSize(): " << img.elemSize() << endl; cout << "img.elemSize1(): " << img.elemSize1() << endl; cout << "img.step: " << img.step << endl; cout << "img.step1(): " << img.step1() << endl; imwrite("pics/inImg_cvSave.bmp", img); // 打印opencv创建的图像的所有像素 cout << "———————————打印opencv创建的图像的所有像素———————————" << endl; int tt=0; for (int i=0; i<(int)height; i++) { for(int j=0; j<(int)width; j++) { tt++; if (0 == tt%width) { cout << img.at<uchar>(i,j) << endl; } else { cout << (int)img.at<uchar>(i,j) << ", "; } } }
// 利用opencv图像信息配置openvx图像地址结构 vx_imagepatch_addressing_t addr; addr.dim_x = width; addr.dim_y = height; addr.stride_x = (vx_uint32)img.elemSize(); addr.stride_y = (vx_uint32)img.step; addr.step_x = 1; addr.step_y = 1; addr.scale_x = VX_SCALE_UNITY; addr.scale_y = VX_SCALE_UNITY; void* ptr = img.data; // 创建上下文,输入图像 vx_context context = vxCreateContext(); ERROR_CHECK_OBJECT(context); vx_image in_img; vx_status status = VX_SUCCESS;
// 从句柄中导入输入图像,打印图像属性,openvx图像地址结构 in_img = vxCreateImageFromHandle(context, VX_DF_IMAGE_U8, &addr, &ptr, VX_MEMORY_TYPE_HOST); cout << "———————————打印vxCreateImageFromHandle创建的图像的所有像素———————————" << endl; show_image_all_pixel(in_img); // 创建图,创建输出图像 vx_graph graph = vxCreateGraph(context); vx_image out_img = vxCreateImage(context, width, height, VX_DF_IMAGE_U8); // 创建节点 vx_node n0 = vxNotNode(graph, in_img, out_img); // 验证图,保存图结构 status = vxVerifyGraph(graph); // 调度图 status = vxScheduleGraph(graph); status = vxWaitGraph(graph);
if (VX_SUCCESS == status) { cout << "———————————打印vxNotNode输出图像的所有像素———————————" << endl; show_image_all_pixel(out_img); }
// 释放资源 vxReleaseImage(&in_img); vxReleaseImage(&out_img); vxReleaseNode(&n0); vxReleaseGraph(&graph); vxReleaseContext(&context);}
************************************************************************日志*******************************************************************APP: Init … !!!MEM: Init … !!!MEM: Initialized DMA HEAP (fd=4) !!!MEM: Init … Done !!!IPC: Init … !!!IPC: Init … Done !!!REMOTE_SERVICE: Init … !!!REMOTE_SERVICE: Init … Done !!! 30433.712534 s: GTC Frequency = 200 MHzAPP: Init … Done !!! 30433.712892 s: VX_ZONE_INIT:Enabled 30433.712904 s: VX_ZONE_ERROR:Enabled 30433.712948 s: VX_ZONE_WARNING:Enabled 30433.713889 s: VX_ZONE_INIT:[tivxInitLocal:130] Initialization Done !!! 30433.715078 s: VX_ZONE_INIT:[tivxHostInitLocal:93] Initialization Done for HOST !!!/************************************打印Target使能情况************************************/TIVX_TARGET_A72_0 Enable: YESTIVX_TARGET_A72_1 Enable: YESTIVX_TARGET_A72_2 Enable: YESTIVX_TARGET_A72_3 Enable: YESTIVX_TARGET_DSP1 Enable: YESTIVX_TARGET_DSP2 Enable: YESTIVX_TARGET_DSP_C7_1 Enable: YES/************************************打印Target使能情况结束************************************/opencv创建图像(高*宽*通道数):5*16*1img.elemSize(): 1img.elemSize1(): 1img.step: 16img.step1(): 16———————————打印opencv创建的图像的所有像素———————————0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ———————————打印vxCreateImageFromHandle创建的图像的所有像素———————————/************************************打印图像像素值************************************/0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0/************************************打印图像像素值结束************************************/———————————打印vxNotNode输出图像的所有像素———————————/************************************打印图像像素值************************************/90, 30, 1, 1, 22, 0, 0, 0, 33, 0, 0, 0, 44, 0, 0, 00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0/************************************打印图像像素值结束************************************/ 30433.719841 s: VX_ZONE_INIT:[tivxHostDeInitLocal:107] De-Initialization Done for HOST !!! 30433.724260 s: VX_ZONE_INIT:[tivxDeInitLocal:193] De-Initialization Done !!!APP: Deinit … !!!REMOTE_SERVICE: Deinit … !!!REMOTE_SERVICE: Deinit … Done !!!IPC: Deinit … !!!IPC: DeInit … Done !!!MEM: Deinit … !!!DDR_SHARED_MEM: Alloc's: 1 alloc's of 80 bytes DDR_SHARED_MEM: Free's : 1 free's of 80 bytes DDR_SHARED_MEM: Open's : 0 allocs of 0 bytes DDR_SHARED_MEM: Total size: 536870912 bytes MEM: Deinit … Done !!!APP: Deinit … Done !!!
,
Annie Liu:
已将您的问题反馈给产品工程师,一旦有回复,回尽快告知您。
,
Cherry Zhou:
wang ling said:vx_imagepatch_addressing_t addr; addr.dim_x = width; addr.dim_y = height; addr.stride_x = (vx_uint32)img.elemSize(); addr.stride_y = (vx_uint32)img.step; addr.step_x = 1; addr.step_y = 1; addr.scale_x = VX_SCALE_UNITY; addr.scale_y = VX_SCALE_UNITY; void* ptr = img.data;
工程师从 vxCreateImage()和 handle 创建映像的唯一区别是您提供了上述值(尤其是 STRIDE_y)
输出可能会成为问题,可能由于提供的跨度错误。
您能否确认 STRIDE_y 是否正确? 理想情况下,应该是 width* mul_FACTOR,其中 mul_FACTOR (8位格式为1,16位格式为2,等等)
,
wang ling:
我确认 STRIDE_y 是正确的!因为我从opencv创建的图像宽度为16,高度为5,像素格式为无符号8bit的灰度图像(即一个像素一个字节),那么像素间距为1字节,行间距的跨度当为16*1=16字节。
不知您说的从vxCreateImage()和handle创建映像的唯一区别是我提供了如下跨度有何问题?如有问题,那么您在通过handle创建图像后再对图像做vxNotNode取反操作后的输出结果是正常的吗?您是怎么通过handle来创建图像的呢?我有尝试过把opencv创建的图像通过imwrite保存后再通过tivx_utils_create_vximage_from_bmpfile()加载出来,再利用vxNotNode取反操作则结果是正确的呢。对此我还是比较疑惑,望不吝赐教,期待您的回复,谢谢。vx_imagepatch_addressing_t addr;addr.dim_x = width;addr.dim_y = height;addr.stride_x = 1; //像素间距为1个字节addr.stride_y = 16;//行间距为行宽度*像素字节数,即为16*1addr.step_x = 1;addr.step_y = 1;addr.scale_x = VX_SCALE_UNITY;addr.scale_y = VX_SCALE_UNITY;void* ptr = img.data;
代码简化如下 :
void main(void){
void show_image_all_pixel(vx_image in_img);//声明打印图像像素点函数
vx_uint32 width = 16;vx_uint32 height = 5;
// 创建opencv图像Mat img(height,width,CV_8UC1,Scalar(0)); //创建宽度为16,高度为5,像素格式为无符号8bit的图像,初始化为0img(Range(1,5), Range(1,5)) = Scalar(255); //将图像的第1~4行,1~4列赋值为255printf("opencv创建图像(高*宽*通道数):%d*%d*%d\n", img.rows, img.cols, img.channels());
// 利用opencv图像信息配置openvx图像地址结构vx_imagepatch_addressing_t addr;addr.dim_x = width;addr.dim_y = height;addr.stride_x = 1; //像素间距为1个字节addr.stride_y = 16;//行间距为行宽度*像素字节数,即为16*1addr.step_x = 1;addr.step_y = 1;addr.scale_x = VX_SCALE_UNITY;addr.scale_y = VX_SCALE_UNITY;void* ptr = img.data; //imwrite("image.bmp",img);
// 创建上下文,输入图像vx_context context = vxCreateContext();// 创建图vx_graph graph = vxCreateGraph(context);
vx_image in_img;vx_status status = VX_SUCCESS;
// 从句柄中导入输入图像,打印图像属性in_img = vxCreateImageFromHandle(context, VX_DF_IMAGE_U8, &addr, &ptr, VX_MEMORY_TYPE_HOST);cout << "———————————打印vxCreateImageFromHandle创建的图像的所有像素———————————" << endl;show_image_all_pixel(in_img); //打印显示图像像素点//创建输出图像vx_image out_img = vxCreateImage(context, width, height, VX_DF_IMAGE_U8);// 创建节点,图像取反操作vx_node n0 = vxNotNode(graph, in_img, out_img);// 验证图,保存图结构status = vxVerifyGraph(graph);// 调度图status = vxScheduleGraph(graph);status = vxWaitGraph(graph);
if (VX_SUCCESS == status){cout << "———————————打印vxNotNode输出图像的所有像素———————————" << endl;show_image_all_pixel(out_img);}
// 释放资源vxReleaseImage(&in_img);vxReleaseImage(&out_img);vxReleaseNode(&n0);vxReleaseGraph(&graph);vxReleaseContext(&context);}
void show_image_all_pixel(vx_image in_img){vx_uint32 width;vx_uint32 height;
vxQueryImage(in_img, (vx_enum)VX_IMAGE_WIDTH, &width, sizeof(vx_uint32));vxQueryImage(in_img, (vx_enum)VX_IMAGE_HEIGHT, &height, sizeof(vx_uint32));
vx_map_id map_id_in;vx_rectangle_t rect_in = {0, 0, width, height};vx_imagepatch_addressing_t map_addr_in;vx_uint8* map_ptr_in;vxMapImagePatch(in_img, &rect_in, 0, &map_id_in, &map_addr_in, (void **)&map_ptr_in, VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X);
printf("/************************************打印图像像素值************************************/\n");volatile vx_uint32 i,j,k;i=j=k=0;for(volatile vx_uint32 y = 0; y < map_addr_in.dim_y; y+=map_addr_in.step_y){j = (map_addr_in.stride_y*y*map_addr_in.scale_y)/VX_SCALE_UNITY;for (volatile vx_uint32 x = 0; x < map_addr_in.dim_x; x+=map_addr_in.step_x){i = j + (map_addr_in.stride_x*x*map_addr_in.scale_x)/VX_SCALE_UNITY;k++;if (0 == k%width){printf("%u\n", *(map_ptr_in+i));}else{printf("%u, ", *(map_ptr_in+i));}}}printf("/************************************打印图像像素值结束************************************/\n");vxUnmapImagePatch(in_img, map_id_in);}
************************************************************************日志*******************************************************************APP: Init … !!!MEM: Init … !!!MEM: Initialized DMA HEAP (fd=4) !!!MEM: Init … Done !!!IPC: Init … !!!IPC: Init … Done !!!REMOTE_SERVICE: Init … !!!REMOTE_SERVICE: Init … Done !!!30433.712534 s: GTC Frequency = 200 MHzAPP: Init … Done !!!30433.712892 s: VX_ZONE_INIT:Enabled30433.712904 s: VX_ZONE_ERROR:Enabled30433.712948 s: VX_ZONE_WARNING:Enabled30433.713889 s: VX_ZONE_INIT:[tivxInitLocal:130] Initialization Done !!!30433.715078 s: VX_ZONE_INIT:[tivxHostInitLocal:93] Initialization Done for HOST !!!———————————打印vxCreateImageFromHandle创建的图像的所有像素———————————/************************************打印图像像素值************************************/0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0/************************************打印图像像素值结束************************************/———————————打印vxNotNode输出图像的所有像素———————————/************************************打印图像像素值************************************/90, 30, 1, 1, 22, 0, 0, 0, 33, 0, 0, 0, 44, 0, 0, 00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0/************************************打印图像像素值结束************************************/30433.719841 s: VX_ZONE_INIT:[tivxHostDeInitLocal:107] De-Initialization Done for HOST !!!30433.724260 s: VX_ZONE_INIT:[tivxDeInitLocal:193] De-Initialization Done !!!APP: Deinit … !!!REMOTE_SERVICE: Deinit … !!!REMOTE_SERVICE: Deinit … Done !!!IPC: Deinit … !!!IPC: DeInit … Done !!!MEM: Deinit … !!!DDR_SHARED_MEM: Alloc's: 1 alloc's of 80 bytesDDR_SHARED_MEM: Free's : 1 free's of 80 bytesDDR_SHARED_MEM: Open's : 0 allocs of 0 bytesDDR_SHARED_MEM: Total size: 536870912 bytesMEM: Deinit … Done !!!APP: Deinit … Done !!!
,
Cherry Zhou:
wang ling said:我有尝试过把opencv创建的图像通过imwrite保存后再通过tivx_utils_create_vximage_from_bmpfile()加载出来,再利用vxNotNode取反操作则结果是正确的呢。
如果在通过此 API 进行写入和加载时得到正确的输出,您是否可以调用"vxMapImagePatch()"到由此生成的 vx_image 并从中读取 image_addr?
然后将此 image_addr 与您正在设置的以下值进行比较,看下是否相同?
vx_imagepatch_addressing_t addr;addr.dim_x = width;addr.dim_y = height;addr.stride_x = 1; //Pixel pitch is 1 byte addr.stride_y = 16;//Line spacing is line width * number of pixels bytes, which is 16 * 1 addr.step_x = 1;addr.step_y = 1;addr.scale_x = VX_SCALE_UNITY;addr.scale_y = VX_SCALE_UNITY;void* ptr = img.data;
,
wang ling:
通过imwrite保存后再通过tivx_utils_create_vximage_from_bmpfile()加载出来的vx_image,调用vxMapImagePatch,并从中读取打印如下值
addr.dim_x = width;addr.dim_y = height;addr.stride_x = 1; //Pixel pitch is 1 byte addr.stride_y = 16;//Line spacing is line width * number of pixels bytes, which is 16 * 1 addr.step_x = 1;addr.step_y = 1;addr.scale_x = VX_SCALE_UNITY;addr.scale_y = VX_SCALE_UNITY;
void* ptr = img.data; 除了最后一项图像地址外,其他与设定的值都是一样的,保存到本地再加载出来的图像通过vxMapImagePatch出来的地址 ,与opencv创建openvx图像时的地址本来就不一样吧,但这个不应该影响通过vxCreateImageFromHandle创建图后再做节点的取反操作的输出结果呀
,
wang ling:
另外我在通过in_image=vxCreateImageFromHandle(context,VX_DF_IAMGE_U8,&addr,&ptr,VX_MEMORY_TYPE_HOST)设置的mem_typ是VX_MEMORY_TYPE_HOST,但是当我通过vxQueryImage(in_image,(vx_enum)VX_IMAGE_MEMORY_TYPE,&memory_type,sizeof(vx_enum))查询并打印memory_type值却是VX_MEMORY_TYPE_NONE,这点也比较疑惑,是否最终节点的取反操作没有执行是与此处的memory_type没有设置上有关联吗?
期待您的回复,谢谢!!!
,
Cherry Zhou:
都已跟进给工程师,请关注英文论坛的答复。