Study notes - the first lesson

Foreword

View related articles and a sum of the code and then hit the successful commissioning of the results,
eguid the blog
does not guarantee the code to be able to run intact,
here to do some recording.
ps: there are changes to the content of the code, you can see the original author of the original.

Code Contents

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();
    }

}
Published 401 original articles · won praise 256 · Views 2.71 million +

Guess you like

Origin blog.csdn.net/cdnight/article/details/103886680