读书笔记-第一课

前言

查看了相关文章然后一笔一笔打代码再调试成功出结果,
eguid的博客
不保证代码能够原封不动就能运行,
这里做一下记录。
ps:代码内容有改动,原版的可以看原作者的。

代码内容

package net.w2p.JCVStudio.zhiboStudy;

/**
 * 前言:
 * 鉴于很多同学反馈目前javacv采集摄像头存在几点问题
 *
 * 1、javacv采集摄像头帧率很低
 *
 * 2、javacv中的摄像头采集依赖opencv的capture采集器,获取的Mat没有及时释放,容易内存溢出
 *
 * 3、javacv封装的太死,调用摄像头不灵活,无法遍历摄像头设备列表
 *
 * 4、javacv打开摄像头太慢,一般要3秒才能打开摄像头设备
 *
 * 所以直接使用opencv采集摄像头设备是一个比较好的方案,并且采集效率上得到了很大的提高,不会像javacv里面一样摄像头掉帧比较严重。
 * ————————————————
 * 版权声明:本文为CSDN博主「本博客已停止维护!-eguid」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
 * 原文链接:https://blog.csdn.net/eguid_1/article/details/58027720
 * 一、实现的功能
 *
 *
 * (1)opencv原生摄像头图像采集
 *
 * (2)opencv原生摄像头设备遍历
 *
 * (3)Mat转换为Frame
 *
 * (4)计算实时帧率
 *
 * (5)文字水印(显示实时帧率)
 * **/

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.bytedeco.opencv.opencv_videoio.VideoCapture;

import javax.swing.*;
import java.text.DecimalFormat;

/***
 * 第一课,遍历调用摄像头并且:
 * 01 显示原始图像
 * 02 将原始头像添加上水印文字
 * 03 将原始图像加文字以后用推流器保存到本地。
 *
 * ***/
public class Lesson01 {

    private static final Double FRAME_RATE = 25.0;
    final Double imageTime = 0.04*1000;
    long startTime = System.currentTimeMillis();

    /**
     * 无水印,无帧率计算实现:
     * **/
    public void study01(){
        VideoCapture vc=null;
        //遍历查找摄像头
        int index=-1;
        for(;index<2;index++){
            vc=new VideoCapture(index);
            if(vc.grab()){
                //找到摄像头设备,退出遍历
                System.err.println("当前摄像头:"+index);
                break;
            }
            vc.close();//没找到设备,释放资源
        }
        //vc为null,并且设备没正常开启,说明没找到设备
        if(vc!=null&&!vc.isOpened()){
            System.err.println("无法找到摄像头,请检查是否存在摄像头设备");
            return;
        }
        //使用java的JFrame显示图像
        CanvasFrame cFrame = new CanvasFrame("做好自己!--eguid!http://www.eguid.cc/",CanvasFrame.getDefaultGamma()/2.2);
        //javacv提供的转换器,方便mat转换为Frame
        OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
        Mat mat=new Mat();
        for(;;){
            vc.retrieve(mat);//重新获取mat
            if(vc.grab()){//是否采集到摄像头数据
                if(vc.read(mat)){//读取一帧mat图像
//          opencv_highgui.imshow("eguid", mat);该opencv方法windows下会无响应
                    cFrame.showImage(converter.convert(mat));
                }
                mat.release();//释放mat
            }

            try {
                Thread.sleep(45);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }



    /***
     * 调用摄像头,添加水印文字。
     * **/
    public void study02(){
        //做好自己!--eguid!http://www.eguid.cc
        String msg="fps:";//水印文字
        // 水印文字位置
        Point point = new Point(10, 50);
        // 颜色,使用黄色
        Scalar scalar = new Scalar(0, 255, 255, 0);
        DecimalFormat df=new DecimalFormat(".##");//数字格式化
        VideoCapture vc=null;
        //遍历查找摄像头
        int index=-1;
        for(;index<2;index++){
            vc=new VideoCapture(index);
            if(vc.grab()){
                //找到摄像头设备,退出遍历
                System.err.println("做好自己!--eguid温馨提示,获取本机当前摄像头序号:"+index);
                break;
            }
            vc.close();//没找到设备,释放资源
        }
        //vc为null,并且设备没正常开启,说明没找到设备
        if(vc!=null&&!vc.isOpened()){
            System.err.println("无法找到摄像头,请检查是否存在摄像头设备");
            return;
        }
        //使用java的JFrame显示图像
        CanvasFrame cFrame = new CanvasFrame("做好自己!--eguid!http://www.eguid.cc",
                CanvasFrame.getDefaultGamma()/2.2);
        cFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        cFrame.setAlwaysOnTop(true);

        //javacv提供的转换器,方便mat转换为Frame
        OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
        Mat mat=new Mat();
        double start=System.currentTimeMillis();
        double end;
        Frame ftmp=null;



        for(int i=0;;i++){
            ftmp=null;
            vc.retrieve(mat);//重新获取mat
            if(vc.grab()){//是否采集到摄像头数据
                if(vc.read(mat)){//读取一帧mat图像
                    end=System.currentTimeMillis();
                    if(mat!=null){
                        opencv_imgproc.putText(mat,msg+df.format((1000.0/(end-start))),
                                point, opencv_imgproc.CV_FONT_VECTOR0, 1.2, scalar,
                                1, 20, false);
                    }
//          opencv_highgui.imshow("eguid", mat);该opencv方法windows下会无响应
                    ftmp=converter.convert(mat);
                    cFrame.showImage(ftmp);
                    System.err.println(i);
                    start=end;
                }
                mat.release();//释放mat
            }
            if(ftmp!=null){
                //--导出到视频中区。
            }
            if (!cFrame.isDisplayable()||!cFrame.isActive()||i>100) {//窗口是否关闭
                System.out.println("窗口关闭啦,请做收尾工作");
//                grabber.stop();//停止抓取
                if(ftmp!=null){

                }
                System.exit(-1);//退出
                return;
            }
        }
    }

    /***
     * 添加水印并且导出为一个MP4文件。
     *
     * **/
    public void study03() throws Exception {
        //做好自己!--eguid!http://www.eguid.cc
        String msg="fps:";//水印文字
        // 水印文字位置
        Point point = new Point(10, 50);
        // 颜色,使用黄色
        Scalar scalar = new Scalar(0, 255, 255, 0);
        DecimalFormat df=new DecimalFormat(".##");//数字格式化
        VideoCapture vc=null;
        //遍历查找摄像头
        int index=-1;
        for(;index<2;index++){
            vc=new VideoCapture(index);
            if(vc.grab()){
                //找到摄像头设备,退出遍历
                System.err.println("做好自己!--eguid温馨提示,获取本机当前摄像头序号:"+index);
                break;
            }
            vc.close();//没找到设备,释放资源
        }
        //vc为null,并且设备没正常开启,说明没找到设备
        if(vc!=null&&!vc.isOpened()){
            System.err.println("无法找到摄像头,请检查是否存在摄像头设备");
            return;
        }
        //使用java的JFrame显示图像
        CanvasFrame cFrame = new CanvasFrame("做好自己!--eguid!http://www.eguid.cc",
                CanvasFrame.getDefaultGamma()/2.2);
        cFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        cFrame.setAlwaysOnTop(true);

        //javacv提供的转换器,方便mat转换为Frame
        OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
        Mat mat=new Mat();
        double start=System.currentTimeMillis();
        double end;
        Frame ftmp=null;


        Java2DFrameConverter converter1 = new Java2DFrameConverter();
        OpenCVFrameConverter.ToIplImage converter2 = new OpenCVFrameConverter.ToIplImage();

        final String outputFilePath="/home/too-white/temp/001_study03.flv";
        FFmpegFrameRecorder recorder = null;

        for(int i=0;;i++){
            ftmp=null;
            vc.retrieve(mat);//重新获取mat
            if(vc.grab()){//是否采集到摄像头数据
                if(vc.read(mat)){//读取一帧mat图像
                    end=System.currentTimeMillis();
                    if(mat!=null){
                        opencv_imgproc.putText(mat,msg+df.format((1000.0/(end-start))),
                                point, opencv_imgproc.CV_FONT_VECTOR0, 1.2, scalar,
                                1, 20, false);
                    }
//          opencv_highgui.imshow("eguid", mat);该opencv方法windows下会无响应
                    ftmp=converter.convert(mat);
//                    Frame rotatedFrame=converter.convert(grabbedImage);//不知道为什么这里不做转换就不能推到rtmp
                    if(recorder==null){


                        recorder=
                                new FFmpegFrameRecorder(outputFilePath,
                                        ftmp.imageWidth,ftmp.imageHeight);
                        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264,编码
//                        recorder.setFormat("flv");
                        recorder.setFormat("flv");//封装格式,如果是推送到rtmp就必须是flv封装格式
                        recorder.setPixelFormat(0);
                        int frameRate=25;
                        recorder.setFrameRate(frameRate);
                        try {
                            recorder.start();
                            startTime=System.currentTimeMillis();
                        }
                        catch (Exception ed){
                            ed.printStackTrace();
                        }

                    }

                    cFrame.showImage(ftmp);

                    /***计算帧的时间**/
                    Double imageFrameSpendTime=(1/recorder.getFrameRate())*1000;
                    long time = 1000*(System.currentTimeMillis() - startTime
                            + imageFrameSpendTime.longValue()*i
                    );
                    if (time > recorder.getTimestamp()) {
                        System.out.println("时间>===record时间。");
                        recorder.setTimestamp(time);
                    }

                    recorder.record(ftmp);
                    System.err.println(i);
                    start=end;
                }
                mat.release();//释放mat
            }
            if(ftmp!=null){
                //--导出到视频中区。
            }
            if (!cFrame.isDisplayable()||!cFrame.isActive()||i>100) {//窗口是否关闭
                if(recorder!=null){
                    recorder.stop();
                }
                System.out.println("窗口关闭啦,请做收尾工作");
//                grabber.stop();//停止抓取
                if(ftmp!=null){

                }
                System.exit(-1);//退出
                return;
            }
        }
    }

    public static void main(String[] args) throws Exception{
        Lesson01 test=new Lesson01();
        test.study03();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值