• OpenCV + Kotlin 实现 USB 摄像头(相机)实时画面、拍照


    6e80e794bf08fe4ea465671dcdaf94af.jpeg

    pexels-regina-trissteria-13623557.jpg

    Part1一. 业务背景

    我们团队前段时间做了一款小型的智能硬件,它能够自动拍摄一些商品的图片,这些图片将会出现在电商 App 的详情页并进行展示。

    基于以上的背景,我们需要一个业务后台用于发送相应的拍照指令,还需要开发一款软件(上位机)用于接收拍照指令和操作硬件设备。

    Part2二. 原先的实现方式以及痛点

    早期为了快速实现功能,我们团队使用 JavaCV 调用 USB 摄像头(相机)进行实时画面的展示和拍照。这样的好处在于,能够快速实现产品经理提出的功能,并快速上线。当然,也会遇到一些问题。

    我列举几个遇到的问题:

    1. 软件体积过大

    2. 编译速度慢

    3. 软件运行时占用大量的内存

    4. 对于获取的实时画面,不利于在软件侧(客户端侧)调用机器学习或者深度学习的库,因为整个软件采用 Java/Kotlin 编写的。

    Part3三. 使用 OpenCV 进行重构

    基于上述的原因,我尝试用 OpenCV 替代 JavaCV 看看能否解决这些问题。

    13.1JNI 调用的设计

    由于我使用 OpenCV C++ 版本来进行开发,因此在开发之前需要先设计好应用层(我们的软件主要是采用 Java/Kotlin 编写的)如何跟 Native 层进行交互的一些的方法。比如:USB 摄像头(相机)的开启和关闭、拍照、相机相关参数的设置等等。

    为此,设计了一个专门用于图像处理的类 WImagesProcess(W 是项目的代号),它包含了上述的方法。

    1. object WImagesProcess {
    2.     init {
    3.         System.load("${FileUtil.loadPath}WImagesProcess.dll")
    4.     }
    5.     /**
    6.      * 算法的版本号
    7.      */
    8.     external fun getVersion():String
    9.     /**
    10.      * 获取 OpenCV 对应相机的 index id
    11.      * @param pidvid 相机的 pid、vid
    12.      */
    13.     external fun getCameraIndexIdFromPidVid(pidvid:String):Int
    14.     /**
    15.      * 开启俯拍相机
    16.      * @param index 相机的 index id
    17.      * @param cameraParaMap 相机相关的参数
    18.      * @param listener jni 层给 Java 层的回调
    19.      */
    20.     external fun startTopVideoCapture(index:Int, cameraParaMap:Map, listener: VideoCaptureListener)
    21.     /**
    22.      * 开启侧拍相机
    23.      * @param index 相机的 index id
    24.      * @param cameraParaMap 相机相关的参数
    25.      * @param listener jni 层给 Java 层的回调
    26.      */
    27.     external fun startRightVideoCapture(index:Int, cameraParaMap:Map, listener: VideoCaptureListener)
    28.     /**
    29.      * 调用对应的相机拍摄照片,使用时需要将 IntArray 转换成 BufferedImage
    30.      * @param cameraId  1:俯拍相机; 2:侧拍相机
    31.      */
    32.     external fun takePhoto(cameraId:Int): IntArray
    33.     /**
    34.      * 设置相机的曝光
    35.      * @param cameraId  1:俯拍相机; 2:侧拍相机
    36.      */
    37.     external fun exposure(cameraId: Int, value: Double):Double
    38.     /**
    39.      * 设置相机的亮度
    40.      * @param cameraId  1:俯拍相机; 2:侧拍相机
    41.      */
    42.     external fun brightness(cameraId: Int, value: Double):Double
    43.     /**
    44.      * 设置相机的焦距
    45.      * @param cameraId  1:俯拍相机; 2:侧拍相机
    46.      */
    47.     external fun focus(cameraId: Int, value: Double):Double
    48.     /**
    49.      * 关闭相机,释放相机的资源
    50.      * @param cameraId 1:俯拍相机; 2:侧拍相机
    51.      */
    52.     external fun closeVideoCapture(cameraId:Int)
    53. }

    其中,VideoCaptureListener 是监听 USB 摄像头(相机)行为的 Listener。

    1. interface VideoCaptureListener {
    2.     /**
    3.      * Native 层调用相机成功
    4.      */
    5.     fun onSuccess()
    6.     /**
    7.      * jni
  • 相关阅读:
    Java高阶数据结构之AVL树
    如何在Windows系统搭建VisualSVN服务并在公网远程访问【内网穿透】
    vue钩子函数以及例子
    chrome浏览器设置--disable-web-security解决跨域
    【Redis】set常用命令&集合间操作&内部编码&使用场景
    使用Python,Keras和TensorFlow训练第一个CNN
    SpringBoot SpringBoot 运维实用篇 4 日志 4.4 文件记录日志
    overflow真实使用场景-表格最右侧显示空白
    不说废话,推荐一款超实用免费配音软件~
    贪心算法选择不相交区间
  • 原文地址:https://blog.csdn.net/SLFq6OF5O7aH/article/details/127019961