讀書筆記-第一課

前言

查看了相關文章然後一筆一筆打代碼再調試成功出結果,
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();
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章