Java 基于 OpenCV4.4 - 视频流处理教程 (六)

news/2024/7/21 5:22:15 标签: opencv, 图像处理

一、处理视频流

     Java版本的OpenCV提供了一个videoio包,以及一个特定的VideoCapture对象,它提供了多种方法来直接从连接的视频设备中读取矩阵对象。首先,你会看到如何从视频设备中获取一个特定大小的矩阵对象,然后将矩阵存入文件中。通过使用帧(frame),你将看到如何将之前学习到的预处理代码应用在实时获取到的图像中。

首先介绍do_still_captures函数。它的输入参数是一组需要抓取的帧、每帧间隔的时间以及从哪个camera_id读入图像。camera_id是连接到你机器的捕获设备索引。通常你会使用0,但是如果你还有其他外接设备的话,就要选择对应的camera_id。首先创建一个 VideoCapture对象,camera_id作为参数。然后创建一个空的矩阵对象,把它传入camera.read()函数来读取数据。这里的矩阵对象是你熟悉的标准OpenCV矩阵Mat,于是你也可以应用那些之前学过的变换。到目前为止,我们先把每一帧存储好,用时间戳作为文件名。完成后,你可以通过VideoCapture对象中的release函数来把相机设置回待机模式。

看看以下代码实现如下:

    static void do_still_captures(int frames, int lapse, int camera_id) {
        VideoCapture capture = new VideoCapture(camera_id);
        capture.set(Videoio.CAP_PROP_FRAME_WIDTH, 320);
        capture.set(Videoio.CAP_PROP_FRAME_HEIGHT, 240);
        Mat mat = new Mat();
        for (int i = 0; i < frames; i++) {
            if (capture.read(mat)) {
                String fileName = "D:\\ProgramFiles\\personDocument\\picture\\" + System.currentTimeMillis() + ".jpg";
                Imgcodecs.imwrite(fileName, mat);
                try {
                    Thread.sleep(lapse * 1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        capture.release();
    }

写个测试方法,调用新建的函数只需填入所需参数,接下来从ID为0的设备中读取10张图片,每间隔1秒拍摄1次。代码实现:

    @Test
    public void test21() throws Exception {
        URL url = ClassLoader.getSystemResource("lib/opencv_java440.dll");
        System.load(url.getPath());
        do_still_captures(10, 1, 0);
    }

当执行上面代码时,会调用笔记本摄像头进行拍照。效果如下:

二、实时处理

OpenCV的Java封装不包含将矩阵转为BufferedImage的明确方法,BufferedImage是Java的graphic包中处理图像的对象。假设你需要一个MatToBufferedImage函数来实时处理Java帧,通过把矩阵对象转换为BufferedImage,即可将它渲染为标准的Java GUI对象。让我们快速地写一个函数,将矩阵转换为标准的Java BufferedImage。代码实现:


    static BufferedImage MatToBufferedImage(Mat frame) {
        int type = 0;
        if (frame == null) return null;

        if (frame.channels() == 1)
            type = BufferedImage.TYPE_BYTE_GRAY;
        else if (frame.channels() == 3)
            type = BufferedImage.TYPE_3BYTE_BGR;

        BufferedImage image = new BufferedImage(frame.width(), frame.height(), type);
        WritableRaster raster = image.getRaster();
        DataBufferByte dataBufferByte = (DataBufferByte) raster.getDataBuffer();
        byte[] data = dataBufferByte.getData();
        frame.get(0, 0, data);
        return image;
    }

当你有了这段代码之后,事情就变得简单了起来。但你仍然需要另外一段代码:一个自定义的panel,它继承了Java的Panel类JPanel。这个自定义的panel,称为MatPanel,包含一个需要绘制的矩阵对象。MatPanel继承Java的JPanel类的方法是,在paint() 函数中直接调用你刚刚见过的函数:MatToBufferedImage。代码实现:

    class MatPanel extends JPanel {
        public Mat mat;

        public void paint(Graphics g) {
            g.drawImage(MatToBufferedImage(mat), 0, 0, this);

        }
    }

标准OpenCV包中缺少的代码已经被实现了,你可以直接创建JFrame来接收矩阵对象。最后一步是使用一段与do_still_captures函数类似的代码,但并不在几帧之后停下,你将会写一个无限循环来处理视频流。代码实现:

    @Test
    public void test22() throws Exception {
        URL url = ClassLoader.getSystemResource("lib/opencv_java440.dll");
        System.load(url.getPath());
//        do_still_captures(10, 1, 0);

        MatPanel matPanel = new MatPanel();
        JFrame jFrame = new JFrame();
        jFrame.getContentPane().add(matPanel);
        jFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        jFrame.setSize(320, 240);
        jFrame.setVisible(true);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        VideoCapture capture = new VideoCapture(0);
        capture.set(Videoio.CAP_PROP_FRAME_WIDTH, 320);
        capture.set(Videoio.CAP_PROP_FRAME_HEIGHT, 240);
        Mat mat = new Mat();
        while (true) {
            if (capture.read(mat)) {
                matPanel.mat = mat;
                matPanel.repaint();
            }
        }
    }

通过调用设备摄像头进行视频流的实时输出,效果图如下:

接下来我们通过 Canny 实时进行图像处理,。将Canny函数应用在视频读取的矩阵对象中。代码实现:


    @Test
    public void test23() throws Exception {
        URL url = ClassLoader.getSystemResource("lib/opencv_java440.dll");
        System.load(url.getPath());
//        do_still_captures(10, 1, 0);

        MatPanel matPanel = new MatPanel();
        JFrame jFrame = new JFrame();
        jFrame.getContentPane().add(matPanel);
        jFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        jFrame.setSize(320, 240);
        jFrame.setVisible(true);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        VideoCapture capture = new VideoCapture(0);
        capture.set(Videoio.CAP_PROP_FRAME_WIDTH, 320);
        capture.set(Videoio.CAP_PROP_FRAME_HEIGHT, 240);
        Mat mat = new Mat();
        while (true) {
            if (capture.read(mat)) {
                Imgproc.cvtColor(mat,mat,Imgproc.COLOR_RGB2GRAY);
                Mat targer = new Mat();
                Imgproc.Canny(mat,targer,100,150,3,true);
                matPanel.mat = targer;
                matPanel.repaint();
            }
        }
    }

实现效果: 

如有不当之处请多多指教,如对你有所帮助,请评论或点赞予以支持,谢谢! 


http://www.niftyadmin.cn/n/1537575.html

相关文章

12.定义并使用变量-复合类型

复合类型&#xff08;composite&#xff09;---类似于java中的数据---介绍用于存放多个值的变量。主要包括这几种&#xff1a;1)pl/sql记录2)pl/sql表3)嵌套表4)varray1.复合类型---pl/sql记录类似于高级语言中的结构体&#xff0c;需要注意的是&#xff0c;当引用pl/sql记录成…

bat编写进阶

http://www.computerhope.com/batch.htm转载于:https://www.cnblogs.com/fanweixiao/archive/2009/06/29/1513162.html

14.定义并使用变量-参照变量

参照变量---介绍参照变量是指用于存放数值指针的变量&#xff0c;通过使用参照变量&#xff0c;可以使得应用程序共享相同对象&#xff0c;从而降低占用的空间。在编写pl/sql程序时&#xff0c;可以使用游标变量(ref cursor)和对象类型变量&#xff08;ref obj_type)两种参照变…

fastdfs 文件系统教程之maven项目打jar包并本地项目引用

一、FastDFS文件系统的Java客户端 FastDFS文件系统Java客户端是指采用Java语言编写的一套程序&#xff0c;专门用来访问fastDFS文件系统&#xff0c;其实就是一个jar包。 1. 下载官方的源代码 从https://codeload.github.com/happyfish100/fastdfs-client-java/zip/master 上…

Docker 安装 FastDFS 文件系统

一、FastDFS 简介 FastDFS服务端有两个角色&#xff1a;跟踪器&#xff08;tracker&#xff09;和存储节点&#xff08;storage&#xff09;。跟踪器主要做调度工作&#xff0c;在访问上起负载均衡的作用。 存储节点存储文件&#xff0c;完成文件管理的所有功能&#xff1a;就…

利用Git版本控制管理你的项目

准备工作 项目创建完成后&#xff0c;将项目版本控制起来&#xff0c;今后每个版本的迭代会非常清楚&#xff0c;同时也有助于项目进行协同开发。 还有一个十分重要的问题是&#xff1a;项目上线后&#xff0c;线上的运行的程序的配置与线下进行测试的配置文件是不一样的(比如数…

Oracle中的判断结构

介绍在任何计算机语言&#xff08;c,java,pascal)都有各种控制语句&#xff08;条件语句、循环语句、顺序控制结构...&#xff09;在pl/sql中也存在这样的控制结构。1.条件分支语句pl/sql中提供了三种条件分支语句:if-then,if-then-else,if-then-elsif-else简单的条件判断if-th…

使用itext将HTML 生成PDF文件

1、使用itext将HTML模板生成PDF文件 HTML模板注意事项&#xff1a; 所有标签按语法正确闭合&#xff0c;否则会报错table用border设置表格如果下载到空白文件&#xff0c;看看整体XML的宽度width使用%来设置&#xff0c;itext解析% 2、项目需求 1.实现将html 内容&#xff08…