Page 1 of 1

我在使用opencv-mobile进行拍照时遇到异常

Posted: 2025-08-05 8:37
by chen
我在Luckfox Pico Ultra W上用qt程序调用opencv-mobile进行拍照时,当多次拍摄后会出现select /dev/video11 timeout异常问题。
一、系统信息

Code: Select all

inux luckfox 5.10.160 #2 Thu May 15 20:31:40 CST 2025 armv7l GNU/Linux
Luckfox Pico Ultra W
二、拍摄信息
摄像头为sc3336,opencv-mobile版本为opencv-mobile-4.12.0-luckfox-pico
1、拍照时所用库cmake内容为:

Code: Select all

project(ColorComparison)
cmake_minimum_required(VERSION 3.5)
set(CMAKE_CXX_STANDARD 11)

SET(CMAKE_C_COMPILER "/home/lab307/luckfox-pico/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc")
SET(CMAKE_CXX_COMPILER "/home/lab307/luckfox-pico/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-g++")


set(OpenCV_DIR ${CMAKE_CURRENT_SOURCE_DIR}/opencv-mobile-4.12.0-luckfox-pico/lib/cmake/opencv4)

# 查找OpenCV(仅库内部使用)

find_package(OpenCV REQUIRED)
link_directories(${OpenCV_INCLUDE_DIRS})

# 编译动态库

add_library(PictureCap SHARED
    ../src/PictureCap.cpp
)

# 私有链接OpenCV(不暴露给使用者)

target_include_directories(PictureCap
    PRIVATE
        ${OpenCV_INCLUDE_DIRS}
        ${CMAKE_CURRENT_SOURCE_DIR}/../include
)

target_link_libraries(PictureCap PRIVATE ${OpenCV_LIBS})

# 设置动态库输出名称(可选)

set_target_properties(PictureCap PROPERTIES OUTPUT_NAME "PictureCap")
2、拍照的程序为:

Code: Select all

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <unistd.h>   // sleep()

int PictureCap()
{
    cv::VideoCapture cap;
    cv::Mat tmp;
    cv::Mat bgr;

    int result = -1;
    
    //const int target_width = 2304;
    //const int target_height = 1296;
    
    try{
        const int target_width = 1920;
        const int target_height = 1080;
    
        cap.set(cv::CAP_PROP_FRAME_WIDTH, target_width);
        cap.set(cv::CAP_PROP_FRAME_HEIGHT, target_height);
    
        cap.open(0);
        
        if(!cap.isOpened()){
            fprintf(stderr, "ERROR:Camera open failed!");
            result = 1;
            return result;
        }
    
        const int w = cap.get(cv::CAP_PROP_FRAME_WIDTH);
        const int h = cap.get(cv::CAP_PROP_FRAME_HEIGHT);
        fprintf(stderr, "%d x %d\n", w, h);
    
        //跳过无效帧
        for(int i = 0;i < 5;i++){
            cap >> tmp;
            usleep(100000);//100ms
        }
    
        sleep(1);
    
        bool captureSuccess = false;
        int number = 0;
        const int MAX_NUMBERS = 10;
        
        while(number++ < MAX_NUMBERS){
            cap >> bgr;
        
            if(!bgr.empty() ){
                captureSuccess = true;
                break;
            }
            sleep(1);//1s
        }
        
        cap.release();
        
        if(captureSuccess){
            if(cv::imwrite("/userdata/local/out.jpg", bgr)){
                fprintf(stderr, "Capture success! Capture number:%d   ",number);
                result = 0;
            }else{
                fprintf(stderr, "ERROR:Image save failed!");
                result = 3;
            }
        }else{
            fprintf(stderr, "ERROR:Capture timout! Capture number:%d",number);
            result = 2;
        }
    }
    catch(const cv::Exception& e){
        fprintf(stderr, "OpenCV:Exception:%d",e.what());
    }
    catch(const std::exception& e){
        fprintf(stderr, "Std:Exception:%d",e.what());
    }
    catch(...){
        fprintf(stderr, "Unknow exception occurred!");
    }
    
    return result;
三、调试信息
拍摄正常时输出信息为:

Code: Select all

 devpath = /dev/video11
   driver = rkisp_v7
   card = rkisp_mainpath
   bus_info = platform:rkisp-vir0
   version = 20500
   capabilities = 84201000
   device_caps = 4201000
   fmt = UYVY 4:2:2  59565955
   fmt = Y/CbCr 4:2:2  3631564e
   fmt = Y/CrCb 4:2:2  3136564e
   fmt = Y/CrCb 4:2:0  3132564e
       size = 32 x 32  ~  2304 x 1296  (+8 +8)
   fmt = Y/CbCr 4:2:0  3231564e
   fmt = Y/CrCb 4:2:0 (N-C)  31324d4e
   fmt = Y/CbCr 4:2:0 (N-C)  32314d4e
XCORE:K:rk_aiq_uapi_sysctl_preInit_devBufCnt: dev_ent:rkraw_rx, buf_cnt:2
XCORE:K:rk_aiq_uapi_sysctl_preInit_scene: main_scene: normal, sub_scene: day
IPCSERVER:K:cid[0] Process path:/tmp/UNIX.domain0, sockfd:28
XCORE:K:cid[0] rk_aiq_uapi_sysctl_init success. iq:/oem/usr/share/iqfiles/sc3336_CMK-OT2119-PC1_30IRC-F16.json
XCORE:K:cid[0] rk_aiq_uapi_sysctl_prepare success. mode:0
/dev/video11 does not support changing fps
CAMHW:K:cid[0] start success. isGroup:0, isOnline:1, isMultiIsp:0, init_ens:0x1bfc0ffc4739
XCORE:K:cid[0] rk_aiq_uapi_sysctl_start success.
CAMHW:K:camId:0, notify_isp_stream_status on
1920 x 1080
CAMHW:K:camId:0, notify_isp_stream_status off
XCORE:K:cid[0] rk_aiq_uapi_sysctl_stop success.
MessageParser process loop exit!
IPCSERVER:K:cid[0] Deinit success
XCORE:K:cid[0] rk_aiq_uapi_sysctl_deinit_locked success.
mpp[3306]: mpp_buffer: mpi_buf_id = 173, dma_buf_fd = 17

mpp[3306]: mpp: mClientFd 19 open ok attr.chan_id 0
异常时的调试信息为:

Code: Select all

   devpath = /dev/video11
   driver = rkisp_v7
   card = rkisp_mainpath
   bus_info = platform:rkisp-vir0
   version = 20500
   capabilities = 84201000
   device_caps = 4201000
   fmt = UYVY 4:2:2  59565955
   fmt = Y/CbCr 4:2:2  3631564e
   fmt = Y/CrCb 4:2:2  3136564e
   fmt = Y/CrCb 4:2:0  3132564e
       size = 32 x 32  ~  2304 x 1296  (+8 +8)
   fmt = Y/CbCr 4:2:0  3231564e
   fmt = Y/CrCb 4:2:0 (N-C)  31324d4e
   fmt = Y/CbCr 4:2:0 (N-C)  32314d4e
XCORE:K:rk_aiq_uapi_sysctl_preInit_devBufCnt: dev_ent:rkraw_rx, buf_cnt:2
XCORE:K:rk_aiq_uapi_sysctl_preInit_scene: main_scene: normal, sub_scene: day
IPCSERVER:K:cid[0] Process path:/tmp/UNIX.domain0, sockfd:27
XCORE:K:cid[0] rk_aiq_uapi_sysctl_init success. iq:/oem/usr/share/iqfiles/sc3336_CMK-OT2119-PC1_30IRC-F16.json
XCORE:K:cid[0] rk_aiq_uapi_sysctl_prepare success. mode:0
/dev/video11 does not support changing fps
CAMHW:K:cid[0] start success. isGroup:0, isOnline:1, isMultiIsp:0, init_ens:0x1bfc0ffc4739
XCORE:K:cid[0] rk_aiq_uapi_sysctl_start success.
CAMHW:K:camId:0, notify_isp_stream_status on
1920 x 1080
select /dev/video11 timeout
select /dev/video11 timeout
select /dev/video11 timeout
select /dev/video11 timeout
select /dev/video11 timeout
select /dev/video11 timeout
CAMHW:K:camId:0, notify_isp_stream_status off
XCORE:K:cid[0] rk_aiq_uapi_sysctl_stop success.
MessageParser process loop exit!
IPCSERVER:K:cid[0] Deinit success
XCORE:K:cid[0] rk_aiq_uapi_sysctl_deinit_locked success.
mpp[3306]: mpp_buffer: mpi_buf_id = 173, dma_buf_fd = 15

mpp[3306]: mpp: mClientFd 17 open ok attr.chan_id 0

fopen /userdata/local/out.jpg failed
在出现select /dev/video11 timeout后系统的cpu占用将会到达100 %并持续一段时间(可能是在生成core dump),此后进行的所有命令行操作都会使cpu占用达到100% 并且无法进行文件的修改和删除,我个人初步怀疑是拍照后的内存并没有完全释放,导致每次拍照时都会使可用内存减少,因为在这种情况下我运行图像识别算法时会提示内存不足:

Code: Select all

--> [Manager] Initializing RKNN context and memory...
E RKNN: failed to allocate fd, ret: -1, errno: 12, errstr: Cannot allocate memory
E RKNN: failed to allocate model memory!, size: 28849856, flags: #2
rknn_init 失败! ret=-1
但是在这种情况下查询可用内存还是比较充足的(另:top命令用不了):

Code: Select all

[root@luckfox root]# top
'vt102': unknown terminal type.
[root@luckfox root]# top
'vt102': unknown terminal type.
[root@luckfox root]# free -h
               total        used        free      shared  buff/cache   available
Mem:           171Mi        48Mi        36Mi       0.0Ki        85Mi       115Mi
Swap:             0B          0B          0B
我尝试降低拍摄分辨率,但是在更多次的拍摄后也会出现该情况,想知道应该怎么解决这种问题。

Re: 我在使用opencv-mobile进行拍照时遇到异常

Posted: 2025-08-07 2:36
by Crocodile
您好 我们不参与 opencv-mobile 的维护,同时二次开发内容不在技术支持范围内,您的问题我们仅提供参考建议。

从opencv-mobile 的源码上看出现 select /dev/video11 timeout 就是没有等待到设备变成可读状态获取图像流
内存上 opencv-mobile 测试重复取图会导致 free 命令中的 shared 字段(进程间共享内存)每次增加4kb,这个是因为 /tmp/message 使用的是共享内存日志增加导致的,应该不是导致多次拍照后失败的原因。建议使用grep -i cma /proc/meminfo 查看一下 CMA 是否有成功释放,CMA是特用于摄像头和RKNN的。
同时也存在单核CPU占用过高导致无法调度执行摄像头取流的可能,QT 本身的资源占用对于单核CPU较大

Re: 我在使用opencv-mobile进行拍照时遇到异常

Posted: 2025-08-11 1:30
by chen
Crocodile wrote: 2025-08-07 2:36 您好 我们不参与 opencv-mobile 的维护,同时二次开发内容不在技术支持范围内,您的问题我们仅提供参考建议。

从opencv-mobile 的源码上看出现 select /dev/video11 timeout 就是没有等待到设备变成可读状态获取图像流
内存上 opencv-mobile 测试重复取图会导致 free 命令中的 shared 字段(进程间共享内存)每次增加4kb,这个是因为 /tmp/message 使用的是共享内存日志增加导致的,应该不是导致多次拍照后失败的原因。建议使用grep -i cma /proc/meminfo 查看一下 CMA 是否有成功释放,CMA是特用于摄像头和RKNN的。
同时也存在单核CPU占用过高导致无法调度执行摄像头取流的可能,QT 本身的资源占用对于单核CPU较大
感谢回复,我经过测试发现在使用opencv-mobile时CmaAllocated会在每次拍照后都会进行增加3000kb左右并且不会减少,请问有什么方法可以释放它们,或者有没有不使用opencv-mobile进行拍照的方案来替换现有的 opencv-mobile拍照?

Re: 我在使用opencv-mobile进行拍照时遇到异常

Posted: 2025-08-26 3:01
by Crocodile
opencv-mobile 的资源释放问题只能通过分析源码解决,我们的了解有限,其他捕获图片的方案可以使用simple_vi_bind_venc_jpeg命令去捕获图像并编码为jpeg