opencv-mobile 现已支持 milkv-duo/duo256m MIPI CSI 摄像头和vpss硬件加速

opencv-mobile 现已支持 milkv-duo/duo256m MIPI CSI 摄像头和vpss硬件加速

TL;DR

  • opencv-mobile highgui 模块实现基于 cvi-mmf 访问摄像头流
  • 在运行时自动动态加载 ae+awb+isp+cvi_bin 库实现 ISP 图像调节
  • 在运行时自动动态加载 vpss 库实现 crop + YUV2BGR 硬件加速
  • 无需修改代码,调用 cv::VideoCapture 便自动支持,支持设置分辨率
  • 关闭摄像头后,还能正常再打开摄像头,不必每次关摄像头后reboot(说的就是 ./CviIspTool.sh 64M
  • 因为只测试验证了 milkv-duo / milkv-duo-256m 搭配 GC2083 摄像头,白名单暂时只有这俩

下载新版本 opencv-mobile milkv-duo 预编译包

解压到项目目录中,cmake 中设置 OpenCV_DIR 路径,find_package 找到

project(testcam)
cmake_minimum_required(VERSION 3.5)

set(CMAKE_BUILD_TYPE release)

# opencv4 requires c++11
set(CMAKE_CXX_STANDARD 11)

set(OpenCV_DIR "${CMAKE_CURRENT_SOURCE_DIR}/opencv-mobile-4.8.1-milkv-duo/lib/cmake/opencv4")
find_package(OpenCV REQUIRED)

add_executable(testcam main.cpp)

target_link_libraries(testcam ${OpenCV_LIBS})

opencv-mobile

opencv-mobile 通过调整编译参数,删减部分opencv源码,来最小化编译的 opencv 库

提供了 opencv 常用的功能,如读写图片,处理,矩阵操作等等 版本与上游同步,无第三方依赖

在绝大多数情况下,以 1/10 的体积无痛替换官方 opencv,尤其适合对体积有特殊要求的移动端和嵌入式环境

milkv-duo / milkv-duo 256m

Milk-V Duo 是基于 CV1800B 芯片的超紧凑型嵌入式开发平台。Duo 256M 是以 SG2002 为主控制器设计的 Duo 的升级版,内存升级到 256M,支持标准的 Linux 系统和应用,可以满足大内存、大存储量的应用需求。Duo 256M 是以 SG2002 为主控制器设计的 Duo 的升级版,支持标准 Linux 系统和应用程序。

milkv 小板子真可爱

cvi-mmf

CVITEK所提供的多媒体软件架构(Multimedia Framework,简称MMF),用以缩短应用程序开发所需的时间。

此架构屏蔽了处理器端的复杂底层设计和差异,对应用程序提供统一且便捷的MMF Programming Interface编程接口。

一些实现细节和限制

运行时加载 cvi-mmf 动态库

为了减少编译耦合,opencv-mobile中采用运行时 dlopen/dlsym 方式加载 libsys libvpu libae libawb libisp libcvi_bin libsns_gc2083,即便编译时候缺库依然兼容可用

这种方式也能自动适配后期系统库升级

libsns_gc2083.so 在 mmf sdk 中并没有直接提供库,但可以从开发板上 /mnt/system/lib/libsns_gc2083.so 拷出来到本地做链接测试

吐嘈一下:cvi-mmf 的 so 库之间有相互依赖,还有 unresolved symbol,dlopen相当费劲。加载顺序的先后区别可能影响调用导致segfault(x

设备检测和白名单

优化代码在 milkv-duo / milkv-duo 256m 上做了验证测试

加载cvi-mmf库时,额外判断 /proc/device-tree/model 是否为 milkv-duo 设备

milkv-duo 和 milkv-duo-256m cvi-mmf 接口源码级兼容,但实际上 sns ini 配置文件却是不同的,如果用的不对会导致无法正常获取图像帧,报错

isp_err_chk:6343(): CSIBDG_A CH0 frm height less than setting(1080)

根据model信息区分两种型号,加载对应配置后恢复工作

分辨率自适应

摄像头原生分辨率是 1920x1080 30fps

  • 用户请求尺寸超出 1080p,自动保持比例降低尺寸到 1080p 范围内
  • 用户请求小于 1080p,会自动居中裁切并保持比例缩小到需要的分辨率

vb 内存池数量

虽然理论上1个内存块就可以一直复用,提供给NV21取帧,但是测试中发现当 vb 内存块太少时会发生 vb 内存耗尽的错误,导致一段时间后再也无法正常取帧

参照 cvi-mmf sample 代码开辟4个内存块用于存放NV21数据,不再发生vb耗尽问题

调用示例

  • cv::VideoCapture 打开摄像头,设置分辨率320x240
  • 每隔1秒获取1帧图像
  • 关闭摄像头
  • 最后把9张图拼接在一起保存

开头1帧因为isp还在统计图像信息,来不及ISP自动处理,所以是黑的

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

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

int main()
{
    cv::VideoCapture cap;
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 320);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 240);
    cap.open(0);

    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);

    cv::Mat bgr[9];
    for (int i = 0; i < 9; i++)
    {
        cap >> bgr[i];

        sleep(1);
    }

    cap.release();

    // combine into big image
    {
        cv::Mat out(h * 3, w * 3, CV_8UC3);
        bgr[0].copyTo(out(cv::Rect(0, 0, w, h)));
        bgr[1].copyTo(out(cv::Rect(w, 0, w, h)));
        bgr[2].copyTo(out(cv::Rect(w * 2, 0, w, h)));
        bgr[3].copyTo(out(cv::Rect(0, h, w, h)));
        bgr[4].copyTo(out(cv::Rect(w, h, w, h)));
        bgr[5].copyTo(out(cv::Rect(w * 2, h, w, h)));
        bgr[6].copyTo(out(cv::Rect(0, h * 2, w, h)));
        bgr[7].copyTo(out(cv::Rect(w, h * 2, w, h)));
        bgr[8].copyTo(out(cv::Rect(w * 2, h * 2, w, h)));

        cv::imwrite("out.jpg", out);
    }

    return 0;
}

终端信息输出

ISP Vipipe(0) Allocate pa(0x8bf30000) va(0x0x3fe8214000) size(291120)
awbInit ver 6.8@2021500
0 R:1400 B:3100 CT:2850
1 R:1500 B:2500 CT:3900
2 R:2300 B:1600 CT:6500
Golden 1024 1024 1024
WB Quadratic:0
isWdr:0
ViPipe:0,===GC2083 1080P 30fps 10bit LINE Init OK!===
binName = /mnt/cfg/param/cvi_sdr_bin
********************************************************************************
cvi_bin_isp message
gerritId:      36403          commitId:      c69c5863e
md5:           cab880835a2ad5184de5ed7762404b84
sensorNum      1
sensorName0    2083

PQBIN message
gerritId:      80171          commitId:      5c9d8fc5d
md5:           ba5a510e093ad42db6788e6c2d13169e
sensorNum      3
sensorName0    2053

author:        wanqiang.he    desc:          思博慧CV1812H_GC2083_RGB_mode_V1.0.0
createTime:    2023-08-04 16:48:08version:       V1.1
tool Version:       v3.0.5.24           mode:
********************************************************************************
sensorName(0) mismatch, mwSns:2083 != pqBinSns:2053
320 x 240
0 R:1165 B:3087 CT:2688
1 R:1464 B:2327 CT:3937
2 R:1974 B:1613 CT:7225
Golden 1464 1024 2327
wdrLEOnly:1
ISP Vipipe(0) Free pa(0x8bf30000) va(0x0x3fe8214000)
gc2083_standby

拉取到本地查看结果图片

快去star下嘛…

1 Like