使用Webcam实现摄像头的开启和关闭,并保存和复制图片

实现思路

  • 0,将webcam的jar文件传入项目中
    在这里插入图片描述

  • 1,显示摄像头的地方:创建一个画板,在画板上添加开启和关闭按钮

  • 2,设置开启和关闭功能:创建一个类实现动作监听器,进而实现监听动作按钮

  • 3,实现开启和关闭操作:创建一个类继承或实现线程,使得可以同步实现多线程

  • 4,保存拍照的图片:执行一次Webcam的打开、通过IO流传入文件夹中

显示摄像头的地方-画板类继承JFrame

  • 创建显示方法:设置标题、大小、居中、默认退出、可见(放在最后)
  • 添加按钮:创建按钮数组、遍历按钮数组(创建按钮对象把遍历后的按钮传入、设置按钮大小、添加动作监听器、把按钮添加到窗体)
  • 在主方法中创建对象调用显示方法

设置开启和关闭功能-实现动作监听器

  • 重写监听器的方法actionPerformed:获取动作监听器传过来的指令、对指令进行判断进行相应的操作
  • 创建画笔:创建画笔对象,通过画笔来画出图像、创建画笔的set对象,用来获得画板类传过来的画笔
  • 在画板类中创建监听器对象:将监听器对象传入按钮中、调用监听器对象中的set方法,将画板类的画笔传入

实现开启和关闭操作-继承Thread,实现多线程同步

  • 添加画笔
  • 添加webcam和画笔g的构造器:使得可以将将构造器中的webcam和画笔g传进来
  • 重写run方法:设置while循环,使webcam调用getImage获取图片信息、用画笔画出来
  • 创建Open和Close方法,对run方法中的while循环进行控制

保存拍照的图片

  • 创建方法actPicture用于进行拍照
  • 创建方法savePicture用于往文件中传照片
  • 在actPicture方法中调用savePicture方法,并传入拍的照片

复制图片-使用处理流:bufferedInputStream1和BufferedOutputStream

  • 1,定义被复制和复制后的路径
  • 2,创建处理流对象,将路径传入
  • 3,读取文件到byte类型的数组中
  • 4,当buff的值为-1时,停止复制
  • 5,判断当处理流不为空时关闭处理流

代码

窗体类

import javax.swing.*;
import java.awt.*;

/*怎么在一个界面添加监听器
1,创建继承了监听器的类对象
2,把这个对象传给按钮
 */
public class Viedio extends JFrame {
    //新建一个监听器对象
    VCLlistener vcLlistener = new VCLlistener();
    //创建显示方法
    public void initUI() {
        setTitle("摄像头");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setSize(1000, 800);

        setLayout(new FlowLayout());
        //添加按钮
        String[] s = {"开启", "关闭"};
        for (String str : s) {
            JButton jButton = new JButton(str);
            jButton.setPreferredSize(new Dimension(85, 35));
            //将监听器对象传入按钮中
            jButton.addActionListener(vcLlistener);
            add(jButton);
        }
        setVisible(true);
        vcLlistener.setG(getGraphics());
    }
    //在主方法中创建对象调用显示方法
    public static void main(String[] args) {
        new Viedio().initUI();

    }
}

接口类

import com.github.sarxos.webcam.Webcam;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

/*怎么创建监听器
1,创建一个类实现监听器接口
2,重写监听器的方法
3,在方法中编辑我们要实现的功能
 */
public class VCLlistener implements ActionListener {
    Graphics g;
    Webcam webcam;
    //创建画笔的set对象,用来获得画板类传过来的画笔
    public void setG(Graphics g) {
        this.g = g;
    }

    boolean tool = true;
    //重写监听器的方法actionPerformed
    @Override
    public void actionPerformed(ActionEvent e) {
        //获取动作监听器传过来的指令
        String str = e.getActionCommand();

        if (str.equals("开启")) {
            webcam = Webcam.getDefault();
            webcam.open();
            VideoThread videoThread = new VideoThread(webcam, g);
            videoThread.Open();
            videoThread.start();

        } else if (str.equals("关闭")) {
            VideoThread videoThread = new VideoThread(webcam, g);
            videoThread.Close();
            webcam.close();
        }
    }

}

线程类

import com.github.sarxos.webcam.Webcam;

import java.awt.*;
import java.awt.image.BufferedImage;

public class VideoThread extends Thread{
    boolean flag = true;
    Webcam webcam = null;
    Graphics g =null;
    //添加webcam和画笔g的构造器:使得可以将将构造器中的webcam和画笔g传进来
    public VideoThread(Webcam webcam, Graphics g) {
        this.webcam = webcam;
        this.g = g;
    }
    //创建Open和Close方法,对run方法中的while循环进行控制
    public void Open(){
        flag = true;
    }
    public void Close(){
        flag = false;
    }

    //重写run方法:设置while循环,使webcam调用getImage获取图片信息、用画笔画出来
    @Override
    public void run() {
        while (flag){
            BufferedImage image = webcam.getImage();
            g.drawImage(image, 50, 50, null);
        }
    }
}

保存照片

 //拍照并保存
    public void actPicture() {
        Webcam webcam = Webcam.getDefault();
//        if (webcam != null) {
        webcam.open();
        // 等待相机准备好
        try {
            Thread.sleep(1000); // 等待1秒钟以确保相机已准备好
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        BufferedImage image = webcam.getImage();
        g.drawImage(image, 400, 400, null);

        savePicture(image);

        //        }else {
//            System.out.println("未检测到摄像头");
//        }
    }

    //拍照 存到文件夹中
    public void savePicture(BufferedImage bi) {

        try {
            //创建文件对象:保存图片要通过文件来保存,最好不用BufferOutputStream,因为是要将图像保存到文件夹中,而不是字符流
            File output = new File("D:\\photo\\output.png");
            //用图像IO流去调用write方法写出到文件中
            ImageIO.write(bi, "png", output);
            System.out.println("保存成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

在这里插入图片描述
复制图片-最后调用copyPictere方法即可

   //复制图片
    //1,定义被复制和复制后的路径
    String path = "D:\\photo\\output.png";
    String path1 = "D:\\photo1\\output.png";
    BufferedOutputStream bufferedOutputStream;
    BufferedInputStream bufferedInputStream1;

    public void copyPictere() {
        try {
            //2,创建处理流对象,将路径传入
            bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(path1));
            bufferedInputStream1 = new BufferedInputStream(new FileInputStream(path));
            //3,读取文件到byte类型的数组中
            byte[] buff = new byte[1024];
            int readLen = 0;
            //4,当buff的值为-1时,停止复制
            while ((readLen = bufferedInputStream1.read(buff)) != -1) {
                bufferedOutputStream.write(buff, 0, readLen);
            }
            System.out.println("复制完毕");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //5,判断当处理流不为空时关闭处理流
                if (bufferedInputStream1 != null) {
                    bufferedInputStream1.close();
                }
                if (bufferedOutputStream != null) {
                    bufferedOutputStream.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/661170.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

豪赌?远见?浙江东方的量子冒险

今年4月16日,量子通信概念异动,浙江东方(600120)拉升涨停。 量子和浙江东方,要把这两个词联系起来似乎并不太容易。 浙江东方,即浙江东方金融控股集团股份有限公司,系浙江省国资委下属浙江省国…

华发股份:加强业务协同 新政下项目热销

“5.17”楼市政策出台后,各地密集落地执行。5月27—28日,上海、广州、深圳三个一线城市跟进落地“517”新政。上海发布《关于优化本市房地产市场平稳健康发展政策措施的通知》,共计9条调整政策,涵盖外地户籍、人才、单身、婚否、企…

SpringBootWeb 篇-深入了解会话技术与会话跟踪三种技术(Cookie 会话跟踪、Session 会话跟踪与 JWT 令牌会话跟踪)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 会话技术 2.0 会话跟踪 2.1 会话跟踪 - Cookie 2.1.1 客户端获取 Cookie 的流程 2.1.2 Cookie 会话跟踪的特点 2.2 会话跟踪 - Session 2.2.1 客户端获取 SESSION…

【Linux 网络编程】网络的基础知识详解!

文章目录 1. 计算机网络背景2. 认识 "协议" 1. 计算机网络背景 网络互联: 多台计算机连接在一起, 完成数据共享; 🍎局域网(LAN----Local Area Network): 计算机数量更多了, 通过交换机和路由器连接。 🍎 广域网WAN: 将…

猫狗分类识别模型建立②模型建立

一、导入依赖库 pip install opencv-python pip install numpy pip install tensorflow pip install keras 二、模型建立 pip install opencv-python pip install numpy pip install tensorflow pip install kerasimport os import xml.etree.ElementTree as ETimpor…

Python Selenium 详解:实现高效的UI自动化测试

落日余辉,深情不及久伴。大家好,在当今软件开发的世界中,自动化测试已经成为保障软件质量和快速迭代的重要环节。而在自动化测试的领域中,UI自动化测试是不可或缺的一部分,它可以帮助测试团队快速验证用户界面的正确性…

【RAG论文】文档树:如何提升长上下文、非连续文档、跨文档主题时的检索效果

RAPTOR Recursive Abstractive Processing for Tree-Organized RetrievalICLR 2024 Stanfordhttps://arxiv.org/pdf/2401.18059 RAPTOR(Recursive Abstractive Processing for Tree-Organized Retrieval)是一种创建新的检索增强型语言模型,它…

使用NuScenes数据集生成ROS Bag文件:深度学习与机器人操作的桥梁

在自动驾驶、机器人导航及环境感知的研究中,高质量的数据集是推动算法发展的关键。NuScenes数据集作为一项开源的多模态自动驾驶数据集,提供了丰富的雷达、激光雷达(LiDAR)、摄像头等多种传感器数据,是进行多传感器融合…

【PostgreSQL17新特性之-事务级别超时参数transaction_timeout】

PostgreSQL数据库里有多个和会话相关的参数,PostgreSQL17-beta1版本新增了一个transaction_timeout参数,来限制事务的持续时间。 当前的一些和会话相关的超时参数如下 -----------------------------------------------------------------------------…

OrangePi Kunpeng Pro 开发板测评 | AI 边缘计算 大模型部署

0 前言 此次很幸运能够参与 OrangePi Kunpeng Pro 开发板的测评,感谢 CSDN 给予这次机会。 香橙派联合华为发布了基于昇腾的 OrangePi Kunpeng Pro 开发板,具备 8TOPS 的 AI 算力,能覆盖生态开发板者的主流应用场景,具备完善的配…

el-pagination在删除非第一页的最后一条数据遇到的问题

文章目录 前言一、问题展示二、解决方案三、源码解析1、elementui2、elementplus 总结 前言 这个问题是element-ui中的问题,可以从源码中看出来,虽然页码更新了,active也是对的,但是未调用current-change的方法,这里就…

C#多线程同步lock、Mutex

C#使用多线程可以通过System.Threading命名空间下的Thread类来实现 lock和Mutex用于实现线程同步的机制&#xff1a; 上代码&#xff1a; class People{public People(int idd){id idd;}public int id;public int age;}class TestHelper{public TestHelper() { }List<Peo…

鸿蒙开发接口图形图像:【WebGL】

WebGL WebGL提供图形绘制的能力&#xff0c;包括对当前绘制图形的位置、颜色等进行处理。 WebGL标准图形API&#xff0c;对应OpenGL ES 2.0特性集。 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md…

4月平板电脑行业线上销售数据分析

由于全球科技发展趋势&#xff0c;如AI技术的应用&#xff0c;以及厂商新品发布计划&#xff1b;同时&#xff0c;平板电脑作为个人电脑的延伸产品&#xff0c;其便携性和生产力相较于手机具有明显优势&#xff0c;这也为行业的进一步发展提供了动力。 据鲸参谋数据统计&#…

开一个抖音小店可以经营几个类目?经营几个类目最合适?

大家好&#xff0c;我是喷火龙。 抖音小店的商品类目和商品数量是没有限制的&#xff0c;只要是在营业执照的经营范围之内的类目都能入驻抖音小店&#xff0c;但是选择的主营类目不能超过三个。 有些商家可能会想&#xff0c;自己经营多个类目&#xff0c;做多种商品种类&…

C++STL容器系列(三)list的详细用法和底层实现

目录 一&#xff1a;介绍二&#xff1a;list的创建和方法创建list方法 三&#xff1a;list的具体用法3.1 push_back、pop_back、push_front、pop_front3.2 insert() 和 erase()3.3 splice 函数 四&#xff1a;list容器底层实现4.1 list 容器节点结构5.2 list容器迭代器的底层实…

算法的时间复杂度(详解)

前言&#xff1a; 算法(Algorithm):就是定义良好的计算过程&#xff0c;他取一个或一组的值为输入&#xff0c;并产生出一个或一组值作为 输出。简单来说算法就是一系列的计算步骤&#xff0c;用来将输入数据转化成输出结果 一、算法效率 1.1 如何衡量一个算法的好坏 如何衡…

一篇文章搞懂二叉树

文章目录 DP 树叶的度树的度节点的层次节点的祖先节点的子孙双亲节点或父节点 树的表示孩子兄弟表示法双亲表示法树和非树树的应用 二叉树满二叉树完全二叉树推论二叉树的存储以数组的方式以链表的方式堆(Heap)堆的分类大根堆和小根堆的作用 二叉树的遍历DFS和BFS DP 动态规划…

【CALayer-时钟练习-CADisplayLink Objective-C语言】

一、我们接着来看,这个CADisplayLink啊, 1.刚才我们说那个时间呢,差上1秒钟的样子,然后呢,我们现在呢,用这个叫做CADisplayLink的东西,来解决,用这个类,来解决啊, 我们说,NSTimer,是跑到这儿了以后,一秒钟以后, 它才会执行,这个timeChange方法,真正的时间,不…

同比和环比

1、概述 同比和环比是两种常见的数据分析方法&#xff0c;用于衡量数据在不同时间段的变化情况。通过同比和环比的计算&#xff0c;可以更清晰地了解数据在不同时间段的增长或下降情况&#xff0c;从而为决策提供依据。 2、同比 同比&#xff08;Year-on-Year, YoY&#xff09…