前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >通过ChatGPT使用JavaCV

通过ChatGPT使用JavaCV

原创
作者头像
编程思维
发布2024-06-24 17:21:14
750
发布2024-06-24 17:21:14

最近我在自己的服务器里基于Pandora搭建了ChatGPT页面,以后只需要accessToken或者key就可以使用,不再需要再去官网玩了,省下了不少时间。

兴致勃勃的了不起,开启了ChatGPT学习(tiaojiao)之路。

这次打算基于它来进行JavaCV开发,我负责胡思乱想,ChatGPT负责实现。看看它能够给我们带来什么惊喜

JavaCV

JavaCV是对OpenCV的一种接口封装,说白了就是使用Java调用C,以往这方面,我们都是使用C++来做的,但是自从有了JavaCV之后,Java也丰富了关于这方面的玩法。具体对JavaCV感兴趣的,可以自己baidu查查。

废话少说了,直接开始tiaojiao

第一步当然就是引入Maven依赖了,这一步有手就行,不用问了。

一个是JavaCV依赖,一个是lombok依赖,因为打算使用@Slf4j

代码语言:javascript
复制
<!-- javacv相关依赖,一个就够了 -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.5.6</version>
</dependency>
 <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <version>1.18.12</version>
 </dependency>

ChatGPT回答:

重点分析:

  1. 导入相关库:代码开头使用import语句导入了所需的JavaCV和OpenCV库。
  2. 创建OpenCVFrameGrabber对象:通过创建OpenCVFrameGrabber对象,我们指定要使用的摄像头设备。在示例中,使用的是默认的摄像头设备,表示为0
  3. 启动摄像头:调用grabber.start()方法来启动摄像头,准备开始捕获图像帧。
  4. 捕获和处理图像帧:使用一个无限循环,在每次迭代中调用grabber.grab()方法来捕获一帧图像。返回的帧对象可以被转换为Mat对象,以便进行进一步的图像处理和计算机视觉任务。
  5. 图像处理和计算机视觉任务:在获取到每一帧图像后,你可以在注释部分中对图像进行处理。这是一个重要的部分,你可以在这里应用各种图像处理算法或进行计算机视觉任务,例如人脸检测、目标追踪、图像分割等。你可以使用JavaCV提供的函数和类来执行这些任务。
  6. 显示图像:使用OpenCV的imshow函数显示图像,通过传递窗口名称和Mat对象来显示捕获的图像帧。waitKey函数用于等待键盘输入,其中参数表示等待时间(以毫秒为单位)。这样可以以一定的速率显示连续的图像帧。

从重点分析中我们可以看出,获取摄像头的关键在于OpenCVFrameGrabber对象,本机摄像头一般是0。而展示画面则是使用openCV的imshow方法。

在这里你会发现,ChatGPT虽然只给了调用摄像头的代码,但是关于后续能够进行的操作,它通过注释告诉了我们,可以再哪一步进行处理。

添加分辨率

接下来,我们根据ChatGPT联系上下文的功能,为OpenCVFrameGrabber对象添加分辨率来丰富这项功能。

学过Java的都知道,Java有一部分内容是Swing,接下来我们让它对此功能添加JFrame框,让我们通过JFrame来看到拉去的摄像头。

使用Swing

而JavaCV对此包装了一个CanvasFrame类来展示画面

对此,ChatGPT使用CanvasFrame来创建一个窗口并设置其尺寸。在每次循环中,调用frame.showImage(mat)来显示从摄像头捕获到的图像帧。使用CanvasFrame可以简化图像显示,因为CanvasFrame提供了内置的绘图画布。它还提供了一些附加功能,如调整窗口大小、关闭事件处理等

增加水印

并且,我们还可以通过JavaCV来给视频画面添加一些水印,比如当前时间。

使用opencv_core.Point对象指定水印的位置

由于需要对Frame对象进行操作,所以我们需要使用OpenCVFrameConverter对象,它能帮助我们把Frame对象转成OpenCV的IplImage对象,它是OpenCV中的图像数据结构,包含着图像像素和相关元数据,很多人脸识别的功能都是基于它来实现的。

简单加入水印,最后的结果就是下图的这样。

资源释放

最后,学过IO的都知道,最重要的一步就是资源的释放

我们这次的代码中使用了OpenCVFrameGrabberCanvasFrame对象,最后的肯定就是对它们两个对象进行资源的释放。

代码语言:javascript
复制
log.info("输出结束");
if (null!= previewCanvas) {
    previewCanvas.dispose();
}
if (null!=grabber) {
    try {
        grabber.close();
    } catch (Exception exception) {
        log.error("close grabber error", exception);
    }
}

到此,一份拉取摄像头的功能就结束了。

代码分享
代码语言:javascript
复制
package com.gateway.link.cv.local;

import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.IplImage;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Scalar;

import javax.swing.*;
import java.text.SimpleDateFormat;
import java.util.Date;

import static org.bytedeco.opencv.global.opencv_core.cvFlip;

/**
 * 本地调用笔记本摄像头代码
 */
@Slf4j
public class localVideo {

    /**
     * 输出帧率
     */
    private static final double frameRate = 30;
    /**
     * 摄像头视频的宽
     */
    private static final int cameraImageWidth = 1280;

    /**
     * 摄像头视频的高
     */
    private static final int cameraImageHeight = 720;

    /**
     * 转换器
     */
    private static final OpenCVFrameConverter.ToIplImage openCVConverter = new OpenCVFrameConverter.ToIplImage();



    public static void main(String[] args) throws Exception
    {
        long startTime = System.currentTimeMillis();

        // 设置ffmepg日志级别
        avutil.av_log_set_level(avutil.AV_LOG_INFO);
        FFmpegLogCallback.set();
        //获取本地摄像头,一般是0
        OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
        // 摄像头有可能有多个分辨率,这里指定
        // 可以指定宽高,也可以不指定反而调用grabber.getImageWidth去获取,
        grabber.setImageWidth(1280);
        grabber.setImageHeight(720);

        // 开启抓取器
        grabber.start();

        //创建一个Frame窗口
        CanvasFrame previewCanvas = new CanvasFrame("摄像头预览", CanvasFrame.getDefaultGamma() / grabber.getGamma());
        previewCanvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        previewCanvas.setAlwaysOnTop(true);


        log.info("初始化完成,耗时[{}]毫秒,帧率[{}],图像宽度[{}],图像高度[{}]",
                System.currentTimeMillis()-startTime,
                frameRate,
                cameraImageWidth,
                cameraImageHeight);

        // 添加水印时用到的时间工具
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //控制视频拉取时间,也可以while(true)永久播放
        long endTime = System.currentTimeMillis() + 1000L * 1000;

        // 两帧输出之间的间隔时间,默认是1000除以帧率
        int interVal = getInterval();

        // 水印在图片上的位置
        org.bytedeco.opencv.opencv_core.Point point = new org.bytedeco.opencv.opencv_core.Point(15, 35);

        Frame captureFrame;
        IplImage img;
        Mat mat;

        // 超过指定时间就结束循环
        while (System.currentTimeMillis()<endTime) {
            // 取一帧
            captureFrame = grabber.grab();

            if (null==captureFrame) {
                log.error("帧对象为空");
                break;
            }

            // 将帧对象转为IplImage对象
            img = openCVConverter.convert(captureFrame);

            // 镜像翻转
            cvFlip(img, img, 1);

            // IplImage转mat
            mat = new Mat(img);

            // 在图片上添加水印,水印内容是当前时间,位置是左上角
            opencv_imgproc.putText(mat,
                    simpleDateFormat.format(new Date()),
                    point,
                    opencv_imgproc.CV_FONT_VECTOR0,
                    0.8,
                    new Scalar(0, 200, 255, 0),
                    1,
                    0,
                    false);

            // 输出
            previewCanvas.showImage(openCVConverter.convert(mat));
            // 适当间隔,让肉眼感受不到闪屏即可
            if(interVal>0) {
                Thread.sleep(interVal);
            }
        }

        log.info("输出结束");
        if (null!= previewCanvas) {
            previewCanvas.dispose();
        }
        if (null!=grabber) {
            try {
                grabber.close();
            } catch (Exception exception) {
                log.error("close grabber error", exception);
            }
        }
    }


    /**
     * 两帧之间的间隔时间
     * @return
     */
    protected static int getInterval() {
        // 假设一秒钟30帧,那么两帧间隔就是(1000/30)毫秒
        return (int)(1000/ frameRate );
    }

}

关于代码细节,简单的修改了一下,复制粘贴就可以直接使用。

结束语

这次的学习到此告一段落,下一次,我打算通过JavaCV来做到人脸部位的识别,也是基于ChatGPT来实现。

觉得有用可以关注我

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JavaCV
  • 添加分辨率
  • 使用Swing
  • 增加水印
  • 资源释放
  • 代码分享
  • 结束语
相关产品与服务
人脸识别
腾讯云神图·人脸识别(Face Recognition)基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、比对、搜索、验证、五官定位、活体检测等多种功能,为开发者和企业提供高性能高可用的人脸识别服务。 可应用于在线娱乐、在线身份认证等多种应用场景,充分满足各行业客户的人脸属性识别及用户身份确认等需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档