Windows系统使用javacv获取USB摄像头图像并保存_Zafir2022的博客-程序员ITS203_java获取摄像头数据

技术标签: Java  java  jar  camera  windows  eclipse  

目标:获取Windows系统笔记本自带摄像头,或者连接Windows系统的usb摄像头视频画面,并保存图像到电脑。

一、依赖库说明

源码git地址:bytedeco/javacv: Java interface to OpenCV, FFmpeg, and more (github.com)https://github.com/bytedeco/javacv

javacv jar包下载地址:Releases · bytedeco/javacv (github.com)https://github.com/bytedeco/javacv/releases

二、使用方法如下代码

类名:UvcCameraUtils

//package com.xx.xx
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.WindowConstants;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.bytedeco.javacv.VideoInputFrameGrabber;
import javax.swing.JOptionPane;
import org.bytedeco.javacv.FrameGrabber.Exception;

public class UvcCameraUtils {
    public static int frameIndex = 0;
    // video device name, "Integrated Webcam" 是电脑自带摄像头名,可在设备管理器--相机,查看名称
    private static final String videoDeviceName = "Integrated Webcam";
    
    /**只能打开电脑内置摄像头**/
    public static void showUvcCameraFrame() throws InterruptedException,         
        FrameGrabber.Exception {
        // 0表示摄像头id
        OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
        grabber.start();//开始获取摄像头数据
        CanvasFrame canvas = new CanvasFrame("电脑摄像头");//新建一个窗口
        canvas.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        canvas.setAlwaysOnTop(true);
        while (true) {
            if (!canvas.isDisplayable()) {//窗口是否关闭
                grabber.stop();//停止抓取
                grabber.close();
                System.exit(-1);//退出
            }

            Frame frame = grabber.grab();
            canvas.showImage(frame);//获取摄像头图像并放到窗口上显示, 这里的Frame frame=grabber.grab(); frame是一帧视频图像
            Thread.sleep(50);//50毫秒刷新一次图像
        }
    }
    
    /**根据名称显示摄像头视频画面**/
    public static void showUvcCameraFrame(boolean isSaveImage) throws FrameGrabber.Exception, InterruptedException {
        frameIndex = 0;
        int deviceIndex = -1;
        // 获取设备名称
        String[] deStrings = VideoInputFrameGrabber.getDeviceDescriptions();
        if (deStrings != null && deStrings.length > 0) {
            for (int i=0; i < deStrings.length; i++) {
                System.out.println("descriptions index=" + i + ", value=" + deStrings[i]);
                if (videoDeviceName.equals(deStrings[i])) {
                    deviceIndex = i;
                    break;
                }
            }
        }
        if (deviceIndex < 0) {
            JOptionPane.showMessageDialog(null, "<html><font size=8>" + "没有找到指定设备");
            return;
        }
        // 参数根据设备管理器中,Cameras下面,设备的摄像头排次,如果是第二个参数为1
        VideoInputFrameGrabber grabber = VideoInputFrameGrabber.createDefault(deviceIndex);
        // 摄像头画面宽高
        grabber.setImageWidth(360);
        grabber.setImageHeight(640);
        // 图像格式
        grabber.setFormat("YUY2");
        grabber.start();
        CanvasFrame canvasFrame = new CanvasFrame("摄像头:" + videoDeviceName);
        canvasFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        canvasFrame.setAlwaysOnTop(true);
        while (true) {
            if (!canvasFrame.isDisplayable()) {
                grabber.stop();
                grabber.close();
                System.exit(-1);
            }
            Frame frame = null;
            try {
                frame = grabber.grab();
            } catch (Exception e) {
                System.out.println("showUvcCameraFrame error=" + e.getMessage() + ", isSaveImage=" + isSaveImage);
            }
            if (frame != null) {
                canvasFrame.showImage(frame);
                // 在D盘保存两张图
                if (isSaveImage && frameIndex < 2) {
                    writeFrameToFile(frame, "index_" + frameIndex);
                    frameIndex++;
                }
            }
            Thread.sleep(30);
        }
    }

    public static void writeFrameToFile(Frame frame, String fileNamePrefix) {
        writeFrameToFile("D:\\", frame, fileNamePrefix);
    }
    
    public static void writeFrameToFile(String filePatn, Frame frame, String fileNamePrefix) {
        if (filePatn == null || "".equals(filePatn)) {
            return;
        } else if (!isFileExist(filePatn)) {
            File file = new File(filePatn);
            file.mkdirs();
        }
        File targetFile = new File(filePatn + File.separator + fileNamePrefix + ".jpg");
        String imgSuffix = "jpg";
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage srcBi = converter.getBufferedImage(frame);
        int owidth = srcBi.getWidth();
        int oheight = srcBi.getHeight();
        int width = owidth;
        int height = oheight;
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        Image image = srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        bi.getGraphics().drawImage(image, 0, 0, null);
        try {
            ImageIO.write(bi, imgSuffix, targetFile);
        } catch (IOException e) {
            System.out.println("writeFrameToFile image write error=" + e.getMessage() 
            + ", frame=" + frame + ", fileNamePrefix=" + fileNamePrefix);
            e.printStackTrace();
        }
        if (converter != null) {
            converter.close();
        }
    }

    /**从帧数据中获取Image对象**/
    public static Image getImageFromFrame(Frame frame) {
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage srcBi = converter.getBufferedImage(frame);
        int owidth = srcBi.getWidth();
        int oheight = srcBi.getHeight();
        // 对截取的帧进行等比例缩放
        int width = owidth;
        int height = oheight;// (int) (((double) width / owidth) * oheight);
        Image image = srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        if (converter != null) {
            converter.close();
        }
        return image;
    }
    
    /**文件是否存在**/
    public static boolean isFileExist(String pathname) {
        File file = new File(pathname);
        return isFileExist(file);
    }
    
    /**文件是否存在**/
    public static boolean isFileExist(File file) {
        if (null != file) {
            if (file.exists()) {
                return true;
            }
        }
        return false;
    }
}

2022年11月1日------------------------------------------------------------------------------------------------------------

添加需要的jar包资源:javawindows桌面程序,显示usb相机预览需要的库-桌面系统文档类资源-CSDN文库

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zzhceo/article/details/124381189

智能推荐

GNU C++ 智能指针13- 解析__shared_ptr类1_kupeThinkPoem的博客-程序员ITS203

目录一、关键点解析1、_ConvertibleConcept2、__glibcxx_function_requires3、is_void二、源码分析一、关键点解析1、_ConvertibleConcept template &lt;class _From, class _To&gt; struct _ConvertibleConcept { void __constraints() { _To __y _IsUnused = __x; ...

微服务之RPC_enzoy的博客-程序员ITS203_rpc服务

RPC 简介什么是RPC?RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。为什么要使用RPC

禁止分享的文字-鼠标事件-e.preventDefault();_十年4646454sdg5sagsa的博客-程序员ITS203

&lt;body&gt; 我是一段不愿意分享的文字 &lt;script&gt; // 1. contextmenu 我们可以禁用右键菜单 document.addEventListener('contextmenu', function(e) { e.preventDefault(); })...

springboot2.0之websocket_记昨日书丶的博客-程序员ITS203

添加依赖&lt;dependency&gt; &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt; &lt;artifactId&gt;spring-boot-starter-websocket&lt;/artifactId&gt;&lt;/dependency&gt;添加MyWebSocket类package com...

链接克隆、完整克隆 vmware 快照和克隆_weixin_30387339的博客-程序员ITS203

多重快照功能简介:快照的含义:对某一个特定文件系统在某一个特定时间内的一个具有只读属性的镜像。当你需要重复的返回到某一系统状态,又不想创建多个虚拟机的时候,就可以使用快照功能。其实,快照并不是VMware Workstation 5的新功能。早在VMware Workstation 4的时代,就已经支持快照功能了。但是VMware Workstation 4只能生成一个快照,也就是说,VMwar...

2021爱智先行者—人体存在感传感器_灵感桌面的博客-程序员ITS203

【本文正在参与"2021爱智先行者-征文大赛"活动】https://mp.weixin.qq.com/s/I2s99dZpbP0QpMiKFneYJA上次说了在 智能灯光开关 的我说了在憋大招,那肯定不会只有这点东西,那么今天我们就来继续!之前 智能灯光开关和光照传感器 已经简单的完成了一个小场景的设备搭建,但是这么好玩的点子怎么就只做这么简单的东西呢?那当然不行了啊,得搞事情!搞大事情!之前的场景仅仅具备检查有没有关灯,并且远程关灯的功能,家里有没有其他人在家,是没办法感知到的,还是不够智能。摄像头

随便推点

卡片式设计的最佳实践分享_cleven_zhao的博客-程序员ITS203

2017-02-17 三达不留点gpj CocoaChina卡片本质上是一个简单的信息容器,信息量有限,但设计干净整洁。现如今,在保证界面具有优秀可用性的同时,卡片式的设计甚至成为了平衡界面美学的默认做法。作为最初由Pinterest和Facebook这样的终端服务引入的一种新的设计方案,今天卡片式设计的影响力正在多个行业蔓延开来。如果设计合理,卡片式的

使用java poi包流式导出包含大量数据的excel文件_dotphoenix的博客-程序员ITS203_poi流式导出

原标题:Resolve OutOfMemoryError With Excel Export in the Apache POI Stream API原始链接: https://dzone.com/articles/resolve-outofmemoryerror-with-excelexport-export-eWhenever we try to export a

oracle全量增量_Oracle增量和全量备份方案_weixin_40001805的博客-程序员ITS203

Oracle生产备份方案crontab 配置周末全量备份,其他日期增量备份,清除15天以前文件0 5 * * * find /app/oracle11g/product/11.2.0/archdir/ecudb/* -mtime +6 |xargs rm -fr#rmanbackup30 4 * * 6 sh /backup/feikong/scripts/rman_backup_0.sh30...

win10 子系统ubuntu 20.04 LTS 更换阿里云源_宇亲的博客-程序员ITS203_wsl 20.04如何设定从阿里云下载

更换apt源:(先备份一下)进入源文件夹根目录cd /etc/apt/备份原来的源文件(sources.list),备份名称(sources.list.bak)sudo cp sources.list sources.list.bak编辑源文件sudo vim sources.list清除原有的,替换以下源deb http://mirrors.aliyun.com/ubuntu/ focal main restricteddeb http://mirrors.aliyun.com

grunt api 文档_dayanwu2842的博客-程序员ITS203

Grunt docsGrunt和 Grunt 插件是通过 npm 安装并管理的,npm是 Node.js 的包管理器。安装 grunt-clinpm install grunt-cli -g注意,安装grunt-cli并不等于安装了 Grunt!Grunt CLI的任务很简单:调用与Gruntfile在同一目录中 Grunt。这样带来的好处是,允许你在同一个系统上同时安装多个版...

推荐文章

热门文章

相关标签