OpenCV4 Android 调用摄像头

2023-10-26

OpenCV4 调用摄像头黑屏问题

OpenCV 调用 Android 摄像头这一块,我之前研究了好几天,都是一片黑,毫无头绪。后来发现 OpenCV4 要想调用摄像头,必须继承自 OpenCV 的 CameraActivity !!!

CameraActivity.java 的源码如下,可以看出大部分代码都是为了 Android M(6.0)以上请求权限而生的,只有两个地方非常关键

  1. protected List<? extends CameraBridgeViewBase> getCameraViewList() { …… }
    子 Activity 在继承 CameraActivity 后,需要复写该函数,把 JavaCamera2View 或 JavaCameraView 送入 List 作为返回值。

  2. cameraBridgeViewBase.setCameraPermissionGranted()
    相机视图初始情况下是黑屏的,即不工作状态。只有当权限授予完毕,调用了 setCameraPermissionGranted 之后,OpenCV 才开始调用相机并把数据输出到 SurfaceView 上。

public class CameraActivity extends Activity {

    private static final int CAMERA_PERMISSION_REQUEST_CODE = 200;

    protected List<? extends CameraBridgeViewBase> getCameraViewList() {
        return new ArrayList<CameraBridgeViewBase>();
    }

    protected void onCameraPermissionGranted() {
        List<? extends CameraBridgeViewBase> cameraViews = getCameraViewList();
        if (cameraViews == null) {
            return;
        }
        for (CameraBridgeViewBase cameraBridgeViewBase: cameraViews) {
            if (cameraBridgeViewBase != null) {
                cameraBridgeViewBase.setCameraPermissionGranted();
            }
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        boolean havePermission = true;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(CAMERA) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
                havePermission = false;
            }
        }
        if (havePermission) {
            onCameraPermissionGranted();
        }
    }

    @Override
    @TargetApi(Build.VERSION_CODES.M)
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            onCameraPermissionGranted();
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

实现要领

  1. 首先,要继承 CameraActivity,之前已经说过了。这个基类会去申请权限,然后通知 javaCameraView 已获取到权限,可以正常使用。
  2. 复写父类的 getCameraViewList 方法,将 javaCameraView 回送回去,这样当权限已被赋予时,就可以通知到预览界面开始正常工作了。
  3. OpenCV 已经为我们实现了 Camera 和 Camera2 的函数,如果应用最低版本 minSdkVersion > 5.0,建议使用 JavaCamera2View 的相关函数,否则使用 JavaCameraView。
  4. 在 onResume 时判断 opencv 库是否加载完毕,然后启用预览视图。在 onPause 时由于界面被遮挡,此时应该暂停摄像头的预览以节省手机性能和电量损耗。
  5. 切换前后摄像头时,要先禁用,设置完后启用才会生效。
  6. Camera2 和 Camera 的绝大部分差异 OpenCV 均已经为我们屏蔽在类的内部了,唯一的差别就是两者实现的 CvCameraViewListener 监听器里的预览函数 onCameraFrame 的参数略有不同。从下面的源码可以看出 CvCameraViewListener2 的 inputFrame 由 Mat 类型改为了 CvCameraViewFrame 类型,它额外提供了一个转化为灰度图的接口。

CvCameraViewListener

public interface CvCameraViewListener {
   /**
     * This method is invoked when camera preview has started. After this method is invoked
     * the frames will start to be delivered to client via the onCameraFrame() callback.
     * @param width -  the width of the frames that will be delivered
     * @param height - the height of the frames that will be delivered
     */
    public void onCameraViewStarted(int width, int height);

    /**
     * This method is invoked when camera preview has been stopped for some reason.
     * No frames will be delivered via onCameraFrame() callback after this method is called.
     */
    public void onCameraViewStopped();

    /**
     * This method is invoked when delivery of the frame needs to be done.
     * The returned values - is a modified frame which needs to be displayed on the screen.
     * TODO: pass the parameters specifying the format of the frame (BPP, YUV or RGB and etc)
     */
    public Mat onCameraFrame(Mat inputFrame);
}

CvCameraViewListener2

public interface CvCameraViewListener2 {
   /**
     * This method is invoked when camera preview has started. After this method is invoked
     * the frames will start to be delivered to client via the onCameraFrame() callback.
     * @param width -  the width of the frames that will be delivered
     * @param height - the height of the frames that will be delivered
     */
    public void onCameraViewStarted(int width, int height);

    /**
     * This method is invoked when camera preview has been stopped for some reason.
     * No frames will be delivered via onCameraFrame() callback after this method is called.
     */
    public void onCameraViewStopped();

    /**
     * This method is invoked when delivery of the frame needs to be done.
     * The returned values - is a modified frame which needs to be displayed on the screen.
     * TODO: pass the parameters specifying the format of the frame (BPP, YUV or RGB and etc)
     */
    public Mat onCameraFrame(CvCameraViewFrame inputFrame);
};

/**
 * This class interface is abstract representation of single frame from camera for onCameraFrame callback
 * Attention: Do not use objects, that represents this interface out of onCameraFrame callback!
 */
public interface CvCameraViewFrame {

    /**
     * This method returns RGBA Mat with frame
     */
    public Mat rgba();

    /**
     * This method returns single channel gray scale Mat with frame
     */
    public Mat gray();
};

示例程序

下面使用 Camera2 来实现拍照功能( 注意:Camera2 只能用于 Android 5.0 以上的手机 )

Java代码

public class OpencvCameraActivity extends CameraActivity {

    private static final String TAG = "OpencvCam";

	private JavaCamera2View javaCameraView;
    private Button switchCameraBtn;
    private int cameraId = JavaCamera2View.CAMERA_ID_ANY;
    
    private CameraBridgeViewBase.CvCameraViewListener2 cvCameraViewListener2 = new CameraBridgeViewBase.CvCameraViewListener2() {
        @Override
        public void onCameraViewStarted(int width, int height) {
            Log.i(TAG, "onCameraViewStarted width=" + width + ", height=" + height);
        }

        @Override
        public void onCameraViewStopped() {
            Log.i(TAG, "onCameraViewStopped");
        }

        @Override
        public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
            return inputFrame.rgba();
    	}
	}

    private BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            Log.i(TAG, "onManagerConnected status=" + status + ", javaCameraView=" + javaCameraView);
            switch (status) {
                case LoaderCallbackInterface.SUCCESS: {
                    if (javaCameraView != null) {
                        javaCameraView.setCvCameraViewListener(cvCameraViewListener2);
                        // 禁用帧率显示
                        javaCameraView.disableFpsMeter();
                        javaCameraView.enableView();
                    }
                }
                break;
                default:
                    super.onManagerConnected(status);
                    break;
            }
        }
    };

	//复写父类的 getCameraViewList 方法,把 javaCameraView 送到父 Activity,一旦权限被授予之后,javaCameraView 的 setCameraPermissionGranted 就会自动被调用。
    @Override
    protected List<? extends CameraBridgeViewBase> getCameraViewList() {
        Log.i(TAG, "getCameraViewList");
        List<CameraBridgeViewBase> list = new ArrayList<>();
        list.add(javaCameraView);
        return list;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
       findView();
        setListener();
    }

    private void findView() {
        javaCameraView = findViewById(R.id.javaCameraView);
        switchCameraBtn = findViewById(R.id.switchCameraBtn);
    }

    private void setListener() {
        switchCameraBtn.setOnClickListener(view -> {
            switch (cameraId) {
                case JavaCamera2View.CAMERA_ID_ANY:
                case JavaCamera2View.CAMERA_ID_BACK:
                    cameraId = JavaCamera2View.CAMERA_ID_FRONT;
                    break;
                case JavaCamera2View.CAMERA_ID_FRONT:
                    cameraId = JavaCamera2View.CAMERA_ID_BACK;
                    break;
            }
            Log.i(TAG, "cameraId : " + cameraId);
            //切换前后摄像头,要先禁用,设置完再启用才会生效
            javaCameraView.disableView();
            javaCameraView.setCameraIndex(cameraId);
            javaCameraView.enableView();
        });
    }

    @Override
    public void onPause() {
        Log.i(TAG, "onPause");
        super.onPause();
        if (javaCameraView != null) {
            javaCameraView.disableView();
        }
    }

    @Override
    public void onResume() {
        Log.i(TAG, "onResume");
        super.onResume();
        if (OpenCVLoader.initDebug()) {
            Log.i(TAG, "initDebug true");
            baseLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        } else {
            Log.i(TAG, "initDebug false");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, baseLoaderCallback);
        }
    }
}

布局文件

布局文件很简单,核心就是这个 JavaCamera2View 视图

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <org.opencv.android.JavaCamera2View
        android:id="@+id/javaCameraView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:show_fps="true"
        app:camera_id="any" />

    <Button
        android:id="@+id/switchCameraBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="切换摄像头"
        app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

全屏预览

虽然使用了上述方法,但相机的预览视图还是只占了屏幕的一小丢丢,而且还是头朝左的。

此时需要修改 OpenCV 的源码里 CameraBridgeViewBase.java 中的 deliverAndDrawFrame 方法,对图像进行旋转缩放。

/**
 * 获取屏幕旋转角度
 */
private int rotationToDegree() {
    WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    int rotation = windowManager.getDefaultDisplay().getRotation();
    int degrees = 0;
    switch(rotation) {
        case Surface.ROTATION_0:
            if(mCameraIndex == CAMERA_ID_FRONT) {
                degrees = -90;
            } else {
                degrees = 90;
            }
            break;
        case Surface.ROTATION_90:
            break;
        case Surface.ROTATION_180:
            break;
        case Surface.ROTATION_270:
            if(mCameraIndex == CAMERA_ID_ANY || mCameraIndex == CAMERA_ID_BACK) {
                degrees = 180;
            }
            break;
    }
    return degrees;
}
/**
 * 计算得到屏幕宽高比
 */
private float calcScale(int widthSource, int heightSource, int widthTarget, int heightTarget) {
    if(widthTarget <= heightTarget) {
        return (float) heightTarget / (float) heightSource;
    } else {
        return (float) widthTarget / (float) widthSource;
    }
}
/**
  * This method shall be called by the subclasses when they have valid
  * object and want it to be delivered to external client (via callback) and
  * then displayed on the screen.
  * @param frame - the current frame to be delivered
  */
 protected void deliverAndDrawFrame(CvCameraViewFrame frame) {
     Mat modified;

     if (mListener != null) {
         modified = mListener.onCameraFrame(frame);
     } else {
         modified = frame.rgba();
     }

     boolean bmpValid = true;
     if (modified != null) {
         try {
             Utils.matToBitmap(modified, mCacheBitmap);
         } catch(Exception e) {
             Log.e(TAG, "Mat type: " + modified);
             Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
             Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
             bmpValid = false;
         }
     }

     if (bmpValid && mCacheBitmap != null) {
         Canvas canvas = getHolder().lockCanvas();
         if (canvas != null) {
             canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
             if (BuildConfig.DEBUG) Log.d(TAG, "mStretch value: " + mScale);

             //TODO 额外添加,让预览框达到全屏效果
             int degrees = rotationToDegree();
             Matrix matrix = new Matrix();
             matrix.postRotate(degrees);
             Bitmap outputBitmap = Bitmap.createBitmap(mCacheBitmap, 0, 0, mCacheBitmap.getWidth(), mCacheBitmap.getHeight(), matrix, true);

             if (outputBitmap.getWidth() <= canvas.getWidth()) {
                 mScale = calcScale(outputBitmap.getWidth(), outputBitmap.getHeight(), canvas.getWidth(), canvas.getHeight());
             } else {
                 mScale = calcScale(canvas.getWidth(), canvas.getHeight(), outputBitmap.getWidth(), outputBitmap.getHeight());
             }

             if (mScale != 0) {
                 canvas.scale(mScale, mScale, 0, 0);
             }
             Log.d(TAG, "mStretch value: " + mScale);

             canvas.drawBitmap(outputBitmap, 0, 0, null);

             /*
             if (mScale != 0) {
                 canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
                      new Rect((int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2),
                      (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2),
                      (int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2 + mScale*mCacheBitmap.getWidth()),
                      (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2 + mScale*mCacheBitmap.getHeight())), null);
             } else {
                  canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
                      new Rect((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,
                      (canvas.getHeight() - mCacheBitmap.getHeight()) / 2,
                      (canvas.getWidth() - mCacheBitmap.getWidth()) / 2 + mCacheBitmap.getWidth(),
                      (canvas.getHeight() - mCacheBitmap.getHeight()) / 2 + mCacheBitmap.getHeight()), null);
             }
             */

             if (mFpsMeter != null) {
                 mFpsMeter.measure();
                 mFpsMeter.draw(canvas, 20, 30);
             }
             getHolder().unlockCanvasAndPost(canvas);
         }
     }
 }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV4 Android 调用摄像头 的相关文章

  • openshift搭建Istio

    本文档覆盖了官方文档的Setup的所有章节 一 安装Istio 本次安装的Istio版本为1 7 0 环境为openshift 4 3 注 不建议使用openshift 1 11 即kubernetes 3 11 安装istio 可能会出现
  • HBase简介(很好的梳理资料)

    http jiajun iteye com blog 899632 一 简介 history started by chad walters and jim 2006 11 G release paper on BigTable 2007
  • 腾讯云如何修改域名DNS服务器

    当你在腾讯云购买域名后 如果 DNS 服务器不正确 要把域名 DNS 修改为提示的 DNS 地址 解析后才生效 下面老魏说下操作步骤 一 通过以下步骤查看 DNS 服务器是否正确 登录腾讯云控制台 选择 云产品 gt 域名与网站 gt 云解
  • 短视频seo矩阵系统源码开发与部署全解析

    在这个数字化快速发展的时代 短视频已经成为人们获取娱乐 学习 商业信息的主要途径之一 对于企业来说 利用短视频矩阵进行高效且精准的营销推广 无疑是一个重要的战略方向 本文将详细介绍如何进行短视频矩阵源码的开发与部署 一 开发篇 短视频矩阵源
  • linux 常用语句 grep、awk、sed

    复习资料 一 find grep 管道符 1 find 路径 name 文件名 查找文件 2 grep sex true 文本包含sex true 的行显示出来 3 grep sex true grep o age 18 对grep sex
  • 【Kettle】将【MySQL表按字段同步、更新】【脚本运行】

    前提数据 转换 1 表输入设置 2 插入 更新设置 作业 模块设置 SQL设置 手动输入脚本内容 每次运行都会运行此脚本
  • 十、工业相机与SCARA机械臂的坐标系标定

    注 感谢固高长江研究院徐工程师的技术讲解 以及matlab程序 机器人系统程序的提供 在工业现场当中 相机拍摄到的图像有一个相机坐标系 而机器人自身也有一个机器人自身的坐标系 两者互相独立 当我们通过相机进行对物体进行拍摄 通过模式识别得到
  • pygame 学习记录

    话不多说上代码 import pygame import sys pygame init size width height 900 700 speed 2 1 bg 255 255 255 RGB screen pygame displa
  • 文件上传的各种绕过方式

    1 前端绕过 更改前端的过滤方法进行绕过 1 通过浏览器插件来删除检查后援js代码 然后上传webshell 2 上传文件时把后缀名改成png格式 上传时在通过抓包工具把后缀名改回来 3 更改Content Tybe为image jpeg
  • C#连接sqlServer数据库详解

    C 是如何跟SQL Server进行连接的 在C NET程序设计中 离不开ADO NET ADO NET是 NET连接数据库的重要组件 使用其可以很方便地访问数据库 ADO NET还可以访问Oracle数据库 Access数据库 SQL S
  • Echarts dataZoom x轴横坐标缩放

    https echarts apache org zh option html dataZoom Echarts dataZoom x轴横坐标缩放 把 dataZoom 房子 option下的第一级 和 xAxis yAxis series
  • SpringBoot 启动成功监听

    CommandLineRunner 接口 启动成功后的回调 接口代码 package org springframework boot FunctionalInterface public interface CommandLineRunn
  • MySQL优化(二):MySQL 索引深入解读

    目录 一 索引是什么 1 索引定义 2 索引类型 3 索引的创建 4 索引的删除 二 索引存储模型 2 1 二分查找 2 2 二叉查找树 2 3 平衡二叉树 2 4 多路平衡查找树 B Tree 2 5 加强版多路平衡查找树 B Tree
  • 【统计模拟及其R实现】分层抽样法 / 条件期望法 习题答案(超详细)

    课本 统计模拟及其R实现 肖枝红 朱强 武汉大学出版社 参考资料 方差缩减技术 条件期望法 目录 1 分层抽样法 2 条件期望法 1 分层抽样法 题目1 如何通过分层抽样法得到
  • [人工智能-深度学习-51]:循环神经网络 - RNN基本原理详解

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 121387285 目录 第1章 详解前
  • gmapping 分析

    转载 这一篇先讲我对gmapping源码的理解 难免有错 欢迎指正 相互学习 原博客 https blog csdn net roadseek zw article details 53316177 博客主页 https blog csdn
  • [k8s部署踩过的坑]

    系统环境 系统版本 docker版本 role ip地址 CentOS8 4 2105 Linux version 4 18 0 348 xx Red Hat 8 5 0 4 20 10 12 k8s master 192 168 100
  • 冒泡排序详解

    一 冒泡排序简介 常用排序算法 冒泡排序 Bubble Sort 是一种常见的排序算法 相对来说比较简单 冒泡排序重复地走访需要排序的元素列表 依次比较两个相邻的元素 如果顺序 如从大到小或从小到大 错误就交换它们的位置 重复地进行直到没有
  • python海龟漂亮图案代码大全_带有海龟图案的Python花

    我在高中的编程课上和海龟图形一起工作 这个项目是按照老师演示的一些指导原则和功能制作一朵花 我在一个小时内就完成了 现在我正试图用更多的海龟一次画出多朵花 但我不能让海龟们使用新定义的函数 老师也没有时间和我一对一地讨论我该怎么做 所以 经

随机推荐

  • Cesium:入门教程(二)之数据源加载

    前言 成功运行 helloworld 的例子后 下面对控件 数据源等进一步说明 鼠标 左键单击和拖拽 沿着地球表面平移 调整相机位置 右键单击和拖拽 相机放大缩小 调整相机距离 滚轮 相机放大缩小 调整相机距离 中间按下和拖拽 围绕地球表面
  • Git命令介绍

    1 最小配置 在使用Git之前需要配置User信息 包括user name和user email git config global user name your name git config global user email your
  • openGL之API学习(八十二)glShaderSource

    替换着色器中的代码 任何以前的代码都会被完全替换掉 一次可以上传多段代码进行替换 并不进行代码的扫描和解析 替换完后是否需要重新进行编译和链接呢 因为着色器代码需要编译 连接 最后生成可执行文件才能被CPU GPU调度执行 所以替换完后还是
  • EasyImage简单图床 - 快速搭建私人图床云盘同时远程访问

    文章目录 1 前言 2 EasyImage网站搭建 2 1 EasyImage下载和安装 2 2 EasyImage网页测试 2 3 cpolar的安装和注册 3 本地网页发布 3 1 Cpolar云端设置 3 2 Cpolar内网穿透本地
  • Maven插件之Dependency:analyze

    前言 完成新功能的开发后 在发包前组长告诉我要检查maven工程的依赖 并告诉我相关指令 此文记录一下使用方式 正文 简介 Maven官网之Dependency插件 Dependency插件提供了操纵artifact的能力 可以复制以及拆包
  • Loadrunner手写接口性能脚本

    Loadrunner手写接口性能脚本 文章目录 概述 脚本录制出现的问题 手写loadrunner脚本 概述 使用Loadrunner进行性能测试分为三步 1 创建 编辑脚本 2 运行负载测试 3 分析测试结果 脚本录制出现的问题 1 录制
  • mybatis如何防止SQL注入?

    sql注入发生的时间 sql注入发生的阶段在sql预编译阶段 当编译完成的sql不会产生sql注入 一 采用jdbc操作数据时候 String sql update ft proposal set id id PreparedStateme
  • 【rust/egui】(十一)使用rfd选择文件并使用serde_json进行序列化

    说在前面 rust新手 egui没啥找到啥教程 这里自己记录下学习过程 环境 windows11 22H2 rust版本 rustc 1 71 1 egui版本 0 22 0 eframe版本 0 22 0 上一篇 这里 rfd Rusty
  • 学习笔记之以太网帧结构

    在TCP IP中 以太网的IP数据报文的封装格式由RFC 894定义 IEEE802 3网络的IP数据报文封装由RFC 1042定义 当今最常使用的封装格式是RFC894定义的格式 通常称为Ethernet II或者Ethernet DIX
  • openGL之API学习(一零零)glProgramParameter

    给着色器程序传递参数 void glProgramParameteri GLuint program GLenum pname GLint value program Specifies the name of a program obje
  • python 散点图_

    Python中绘制散点图常用的函数是 matplotlib pyplot scatter 它的主要参数如下 matplotlib pyplot scatter x y s None c None marker None cmap None
  • 【SpringBoot】1、SpringBoot整合JWT实现Token验证

    这里写目录标题 1 单点登录 1 1 单系统登录 1 1 1 单系统登录流程 使用Session实现单系统登录 1 2 多系统 单点 登录 1 2 1 单点登录实现方案 1 2 1 1 Session跨域 1 2 1 2 Spring Se
  • python迭代器和可迭代对象

    1 迭代器 vs 可迭代对象 python中两个迭代的概念 一个叫做迭代器 Iterator 一个叫做可迭代对象 Iterable 我们可以从collections模块中导入 from collections abc import Iter
  • 树模型集成学习(Tree Embedding)

    树模型集成学习 集成学习主要有两个思想 分别是bagging和boosting 树模型的集成模型都是使用树作为基模型 最常用的cart树 常见的集成模型有RandomForest GBDT Xgboost Lightgbm Catboost
  • Win10+Ubuntu16.04双系统重装win10后ubuntu引导失败UEFI启动方式下GRUB消失

    参考博客 http blog csdn net zrf2112 article details 71042782 参考文章 https wiki deepin org index php title E4 BF AE E5 A4 8D E5
  • 获取misc device/cdev 设备private data

    在driver module开发过程中 probe时定义一个device driver相关的数据结构 其它函数中需要用到这个结构 比如write read mmap等操作 MISCDEVICE 在misc device open时 将mis
  • Acwing 1270. 数列区间最大值

    include
  • java 百度ocr文字识别_最简单调用百度OCR接口实现文字识别技术

    Java 纯文本查看 复制代码package baiduocr import java util HashMap import org json JSONObject import com baidu aip ocr AipOcr publ
  • npm install生成的package-lock.json文件有什么作用?

    一 package json node modules package lock json是什么 package json里面定义的是版本范围 比如 1 0 0 具体跑npm install的时候安的什么版本 要解析后才能决定 这里面定义的
  • OpenCV4 Android 调用摄像头

    OpenCV4 调用摄像头黑屏问题 OpenCV 调用 Android 摄像头这一块 我之前研究了好几天 都是一片黑 毫无头绪 后来发现 OpenCV4 要想调用摄像头 必须继承自 OpenCV 的 CameraActivity Camer