1.使用opencv的video write编码,提示物理内存(heap2)分配失败
答:
确认heap2 设置的大小,如果heap2 默认大小是几十MB,需要设置heap2 size为1G。目前出厂默认配置是1G。
Update_boot_info #可查询heap2 sizeupdate_boot_info –heap2_size=0x40000000 –dev=0x0 #设置heap2 size为1G。设置后重装驱动。
2.Bm_opencv的imread jpeg解码结果和原生opencv的imread jpeg结果不同,有误差¶
答:是的。原生opencv使用libjpeg-turbo,而bm_opencv采用了bm168x芯片中的jpeg硬件加速单元进行解码。
误差主要来自解码输出YUV转换到BGR的过程中。
1)YUV需要上采样到YUV444才能进行BGR转换。这个upsample的做法没有标准强制统一,jpeg-turbo提供了默认Fancy upsample,也提供了快速复制上采样的算法,原生opencv采用默认的fancy upsample;而BM168x硬件加速单元采用快速复制的算法。
2)YUV444到BGR的转换是浮点运算,浮点系数精度的不同会有+/-1的误差。其中1)是误差的主要来源。
这个误差并不是错误,而是双方采用了不同的upsample算法所导致的。
3.Opencv中mat是如何分配设备内存和系统内存的?
答:
因为受设计影响,这个问题细节比较多,主要从三方面能解释。
- 在soc模式下,设备内存和系统内存是同一份物理内存,通过操作系统的ION内存进行管理,系统内存是ION内存的mmap获得。在pcie模式下,设备内存和系统内存是两份物理内存,设备内存指BM168x卡上的内存,系统内存指服务器上操作系统内存。如果用户想只开辟系统内存,和开源opencv保持一致,可 以参见FAQ26的回答。
- 在sophon opencv中默认会同时开辟设备内存和系统内存,其中系统内存放在mat.u->data或mat.data中,设备内存放在mat.u->addr中。只有以下几种情况会不开辟设备内存,而仅提供系统内存:
- 当data由外部开辟并提供给mat的时候。即用以下方式声明的时候:
Mat mat(h, w, type, data); 或 mat.create(h, w, type, data);
- 在soc模式下,当type不属于(CV_8UC3, CV_32FC1, CV_32FC3)其中之一的时候。这里特别注意CV_8UC1是不开辟的,这是为了保证我们的opencv能够通过开源opencv的opencv_test_core的一致性验证检查。
- 当宽或者高小于16的时候。因为这类宽高,硬件不支持
- 在BM1682和BM1684的SOC模式下,mat分配的CV_8UC3类型的设备内存会自动做64对齐,即分配的内存大小一定是64对齐的(注意:仅对soc模式的CV_8UC3而言,且仅对BM1684/BM1682芯片)。在PCIE模式下,分配的内存是byte对齐的。
4.Opencv mat创建失败,提示“terminate called after throwing an instance of ‘cv::Exception’ what(): OpenCV(4.1.0) …… matrix.cpp:452: error: (-215:Assertion failed) u != 0 in function ‘creat’”
答:
这种错误主要是设备内存分配失败。失败的原因有两种:
- 句柄数超过系统限制,原因有可能是因为句柄泄漏,或者系统句柄数设置过小,可以用如下方法确认:
查看系统定义的最大句柄数:
ulimit -n 查看当前进程所使用的句柄数:
lsof -n|awk ‘{print $2}’|sort|uniq -c|sort -nr|more
- 设备内存不够用。可以用如下方法确认:
- SOC模式下
cat /sys/kernel/debug/ion/bm_vpp_heap_dump/summary
- PCIE模式下, bm-smi工具可以查看设备内存空间
解决方案:在排除代码本身的内存泄漏或者句柄泄漏问题后,可以通过加大系统最大句柄数来解决句柄的限制问题:ulimit -HSn 65536
设备内存不够就需要通过优化程序来减少对设备内存的占用,或者通过修改dts文件中的内存布局来增加对应的设备内存。详细可以参考SM5用户手册中的说明。
5.opencv转bm_image的时候,报错“Memory allocated by user, no device memory assigned. Not support BMCV!”¶
答:这种错误通常发生在soc模式下,所转换的Mat只分配了系统内存,没有分配设备内存,而bm_image要求必须有设备内存,因此转换失败。而在pcie模式下,接口内部会自动分配设备内存,因此不会报这个错误。
会产生这类问题的Mat通常是由外部分配的data内存attach过去的,即调用Mat(h, w, data) 或者Mat.create(h,w, data)来创建的,而data!=NULL,由外部分配。
对于这种情况,因为bm_image必须要求设备内存,因此解决方案有
- 新生成个Mat,默认创建设备内存,然后用copyTo()拷贝一次,把数据移到设备内存上,再重新用这个Mat来转成bm_image
- 直接创建bm_image,然后用bm_image_copy_host_to_device,将Mat.data中的数据拷贝到bm_image的设备内存中。
6.Opencv用已有Mat的内存data,宽高去创建新的Mat后,新Mat保存的图像数据错行,显示不正常
答:保存的图像错行,通常是由于Mat中step信息丢失所造成。
一般用已有Mat去生成一个新Mat,并且要求内存复用时,可以直接赋值给新的Mat来简单实现,如 Mat1 = Mat2.
但在某些情况下,比如有些客户受限于架构,函数参数只能用C风格的指针传递,就只能用Mat中的data指针,rows,cols成员来重新恢复这个Mat。 这时候就需要注意step变量的设置,在默认情况下是AUTO_STEP配置,即每行数据没有填充数据。但是在很多种情况下,经过opencv处理后,会导致每行出现填充数据。如,
- soc模式下,我们的Mat考虑执行效率,在创建Mat内存时每行数据会做64字节对齐,以适配硬件加速的需求(仅在soc模式下)
- opencv的固有操作,如这个Mat是另一个Mat的子矩阵(即rect的选定区域),或者其他可能导致填充的操作。
因此,按照opencv定义,通用处理方式就是在生成新的Mat的时候必须指定step,如下所示:
cv::Mat image_mat = cv::imread(filename,IMREAD_COLOR,0);cv::Mat image_mat_temp(image_mat.rows,image_mat.cols,CV_8UC3,image_mat.data,image_mat.step[0]);cv::imwrite("sophgo1.jpg",image_mat_temp);7.在opencv VideoCapture 解码视频时提示: maybe grab ends normally, retry count = 513¶
上述问题是因为在VideoCapture存在超时检测,如果在一定时间未收到有效的packet则会输出以上log,此时如果视频源是网络码流可以用vlc拉流验证码流是否正常,如果是文件一般是文件播放到末尾需调用VidoeCapture.release后重新VideoCapture.open
8.SOC模式下,opencv在使用8UC1 Mat的时候报错,而当Mat格式为8UC3的时候,同样的程序完全工作正常。
这个问题碰到的客户比较多,这次专门设立一个FAQ便搜索。其核心内容在FAQ46 “Opencv中mat是如何分配设备内存和系统内存的”有过介绍,可以继续参考FAQ46
在soc模式下,默认创建的8UC1 Mat是不分配设备内存的。因此当需要用到硬件加速的时候,比如推理,bmcv操作等,就会导致各种内存异常错误。
解决方案可以参看FAQ26 “如何指定Mat对象基于system memory内存去创建使用”, 指定8UC1 Mat在创建的时候,内部使用ion分配器去分配内存。如下所示。
cv::Mat gray_mat;gray_mat.allocator = hal::getAllocator();gray_mat.create(h, w, CV_8UC1);9.调用 bmcv_image_vpp_convert_padding 接口时,报缩放比例超过32倍的错:“vpp not support: scaling ratio greater than 32”。
bm1684的vpp中硬件限制图片的缩放不能超过32倍。即应满足 dst_crop_w <= src_crop_w * 32, src_crop_w <= dst_crop_w * 32, dst_crop_h <= src_crop_h * 32 , src_crop_h <= dst_crop_h * 32。
此问题原因可能是:
- 输入 crop_rect 中的crop_w, crop_h 与 输出 padding_attr 中的dst_crop_w ,dst_crop_h 缩放比例超过了32倍。
- crop_rect,padding_attr 值的数量应与 output_num的数量一致。
10.调用 bmcv_image_vpp_basic 接口时,csc_type_t csc_type 和 csc_matrix_t* matrix该如何填?¶
bmcv中vpp在做csc 色彩转换时,默认提供了4组601系数和4组709系数, 如csc_type_t所示。
- csc_type可以填为CSC_MAX_ENUM, matrix填NULL,会默认配置 601 YCbCr与RGB互转系数。
- csc_type可以填csc_type_t中参数,如YCbCr2RGB_BT709,matrix填NULL,会按照所选类型配置对应系数。
- csc_type可以填CSC_USER_DEFINED_MATRIX,matrix填自定义系数。会按照自定义系数配置。
csc_matrix_t 中系数参考如下公式:
Y = csc_coe00 * R + csc_coe01 * G + csc_coe02 * B + csc_add0;
U = csc_coe10 * R + csc_coe11 * G + csc_coe12 * B + csc_add1;
V = csc_coe20 * R + csc_coe21 * G + csc_coe22 * B + csc_add2;
由于1684 vpp精度为10位,整数处理。
csc_coe 与 csc_add的计算方法为: csc_coe = round(浮点数 * 1024)后按整数取补码。
csc_coe取低13bit,即 csc_coe = csc_coe 0x1fff,csc_add取低21bit,即 csc_add = csc_add 0x1fffff。
举例如下:
floating-point coe matrix => fixed-point coe matrix
0.1826 0.6142 0.0620 16.0000 => 0x00bb 0x0275 0x003f 0x004000
|