美文网首页程序员
计算视频卡顿率

计算视频卡顿率

作者: 啊哈_0042 | 来源:发表于2021-08-01 15:08 被阅读0次

    技术栈:

    FFmpe,appium,OBS,opencv

    思路:

    1. 通过自动化录制的测试视频
    2. 利用FFmpe选择兴趣区域进行截取
    3. 拿到兴趣区域进行视频前10s,中间10s,后10s 视频
    4. 把三段10s的视频进行每50ms一张图片
    5. 通过opencv进行图片的分析
      主要依据人的视线规则是相同的图片持续200ms,就是认为是卡顿的。我根据这个规则,通过opencv比较步骤四的图片。第n个图片对比n+1的图片比较像素相似度。然后相似度在多少范围内持续了4张图片(50ms*4=200ms)就认为这段视频是卡段的

    计算出卡顿率

    上代码

    通过自动化录制的测试视频这个就不写了,大致就是通过OBS启动虚拟摄像头
    然后学生端显示老师的摄像头就是虚拟摄像头投射的测试视频

    通过利用FFmpe选择兴趣区域进行截取

    注:crop:ow[:oh[:x[:y:[:keep_aspect]]]]


    crop的使用
    ffmpe -i D:\Users\admin\Desktop\test\丰金莉分享的视频.mp4 -vf crop=327:184:641:200 D:\Users\admin\Desktop\test\test1.mp4
    

    拿到兴趣区域进行视频前10s,中间10s,后10s 视频\

    ffmpe -ss 00:00:00 -i D:\Users\admin\Desktop\test\test1.mp4 -vcodec copy -acodec copy -t 00:00:10 D:\Users\admin\Desktop\test\before10.mp4
    

    把三段10s的视频进行每50ms一张图片

    ffmpe -i D:\\Users\\admin\\Desktop\\test\\before10.mp4 -f image2 -vf fps=fps=20 D:\\Users\\admin\\Desktop\\test\\before\\%d.png
    

    通过opencv进行图片的分析

    package com.abcnull.tools;
    
    import java.awt.HeadlessException;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.UnsupportedEncodingException;
    import java.text.DecimalFormat;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.imageio.ImageIO;
    
    import org.opencv.core.Core;
    import org.opencv.core.CvType;
    import org.opencv.core.Mat;
    import org.opencv.core.MatOfByte;
    import org.opencv.core.MatOfPoint;
    import org.opencv.core.Rect;
    import org.opencv.core.Scalar;
    import org.opencv.imgcodecs.Imgcodecs;
    import org.opencv.imgproc.Imgproc;
    import org.opencv.utils.Converters;
    
    public class ImageCompare {
    
        private boolean compareResult = false;
        private String mark = "_compareResult";
        /**
         * 比较两张图片,如不同则将不同处标记并输出到新的图片中
         * @param imagePath1 图片1的路径
         * @param imagePath2 图片2的路径
         */
        public Integer CompareAndMarkDiff(String imagePath1, String imagePath2)
        {
            Mat mat1 = readMat(imagePath1);
            Mat mat2 = readMat(imagePath2);
            mat1 = Imgcodecs.imdecode(mat1, Imgcodecs.IMREAD_UNCHANGED);
            mat2 = Imgcodecs.imdecode(mat2, Imgcodecs.IMREAD_UNCHANGED);
            /*Mat mat1 = Imgcodecs.imread(imagePath1, Imgcodecs.IMREAD_UNCHANGED);
            Mat mat2 = Imgcodecs.imread(imagePath2, Imgcodecs.IMREAD_UNCHANGED);*/
            if(mat1.cols() == 0 || mat2.cols() == 0 || mat1.rows() == 0 || mat2.rows() == 0)
            {
                System.out.println("图片文件路径异常,获取的图片大小为0,无法读取");
                return 0;
            }
            if(mat1.cols() != mat2.cols() || mat1.rows() != mat2.rows())
            {
                System.out.println("两张图片大小不同,无法比较");
                return 0;
            }
            mat1.convertTo(mat1, CvType.CV_8UC1);
            mat2.convertTo(mat2, CvType.CV_8UC1);
            Mat mat1_gray = new Mat();
            Imgproc.cvtColor(mat1, mat1_gray, Imgproc.COLOR_BGR2GRAY);
            Mat mat2_gray = new Mat();
            Imgproc.cvtColor(mat2, mat2_gray, Imgproc.COLOR_BGR2GRAY);
            mat1_gray.convertTo(mat1_gray, CvType.CV_32F);
            mat2_gray.convertTo(mat2_gray, CvType.CV_32F);
            double result = Imgproc.compareHist(mat1_gray, mat2_gray, Imgproc.CV_COMP_CORREL);
            if(result == 1)
            {
                System.out.println("两个图片完全相同");
                compareResult = true;//此处结果为1则为完全相同
                return 100;
            }
            int a= new Double(result*100).intValue();;
            System.out.println("相似度数值为:"+a+"%");
    //        Mat mat_result = new Mat();
    //        //计算两个灰度图的绝对差值,并输出到一个Mat对象中
    //        Core.absdiff(mat1_gray, mat2_gray, mat_result);
    //        //将灰度图按照阈值进行绝对值化
    //        mat_result.convertTo(mat_result, CvType.CV_8UC1);
    //        List<MatOfPoint> mat2_list = new ArrayList<MatOfPoint>();
    //        Mat mat2_hi = new Mat();
    //        //寻找轮廓图
    //        Imgproc.findContours(mat_result, mat2_list, mat2_hi, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
    //        Mat mat_result1 = mat1;
    //        Mat mat_result2 = mat2;
            //使用红色标记不同点
            //System.out.println(mat2_list.size());
    //        for (MatOfPoint matOfPoint : mat2_list)
    //        {
    //            Rect rect = Imgproc.boundingRect(matOfPoint);
    //            Imgproc.rectangle(mat_result1, rect.tl(), rect.br(), new Scalar(0, 0, 255),2);
    //            Imgproc.rectangle(mat_result2, rect.tl(), rect.br(), new Scalar(0, 0, 255),2);
    //        }
    //        String fileName1 = getFileName(imagePath1);
    //        String targetPath1 = getParentDir(imagePath2)+File.separator+fileName1.replace(".", mark+".");
    //        String fileName2 = getFileName(imagePath2);
    //        String targetPath2 = getParentDir(imagePath2)+File.separator+fileName2.replace(".", mark+".");
    //        System.out.println(targetPath1);
    //        System.out.println(targetPath2);
            //图片一的带标记的输出文件;
    //        Imgcodecs.imwrite(targetPath1, mat_result1);
            //图片二的带标记的输出文件;
    //        Imgcodecs.imwrite(targetPath2, mat_result2);
            //writeImage(mat_result1, targetPath1);
            //writeImage(mat_result2, targetPath2);
            return a;
        }
    
        private void writeImage(Mat mat, String outPutFile)
        {
            MatOfByte matOfByte = new MatOfByte();
            Imgcodecs.imencode(".png", mat, matOfByte);
            byte[] byteArray = matOfByte.toArray();
            BufferedImage bufImage = null;
            try {
                InputStream in = new ByteArrayInputStream(byteArray);
                bufImage = ImageIO.read(in);
                ImageIO.write(bufImage, "png", new File(outPutFile));
            } catch (IOException | HeadlessException e)
            {
                e.printStackTrace();
            }
        }
    
        private String getFileName(String filePath)
        {
            File f = new File(filePath);
            return f.getName();
        }
    
        private String getParentDir(String filePath)
        {
            File f = new File(filePath);
            return f.getParent();
        }
    
        private Mat readMat(String filePath)
        {
            try {
                File file = new File(filePath);
                FileInputStream inputStream = new FileInputStream(filePath);
                byte[] byt = new byte[(int) file.length()];
                int read = inputStream.read(byt);
                List<Byte> bs = convert(byt);
                Mat mat1 = Converters.vector_char_to_Mat(bs);
                return mat1;
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return new Mat();
        }
    
        private List<Byte> convert(byte[] byt)
        {
            List<Byte> bs = new ArrayList<Byte>();
            for (int i = 0; i < byt.length; i++)
            {
                bs.add(i, byt[i]);
            }
            return bs;
        }
    
        public static void main(String[] args) {
            List<Integer> list=new ArrayList<>();
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
            ImageCompare imageCompare=new ImageCompare();
            for (int i = 1; i < 200; i++) {
                System.out.println("out"+i+".png"+"比"+"out"+(i+1)+".png"+"结果:");
                int similarity = imageCompare.CompareAndMarkDiff("D:\\Users\\admin\\Desktop\\test\\before\\" + i + ".png", "D:\\Users\\admin\\Desktop\\test\\before\\" + (i + 1) + ".png");
                System.out.println(similarity);
                list.add(similarity);
            }
            list.add(0);
            System.out.println(list.toString());
            int sum=1;
            List<Integer> num100=new ArrayList<>();
            for(Integer num :list){
                if(98>num){
                    if(sum>4){
                        num100.add(sum);
                        System.out.println("sum="+sum);
                    }
                    sum =1;
                }else {
                    sum+=1;
                }
            }
            int sum1=0;
            for (int i = 0; i < num100.size(); i++) {
                sum1=num100.get(i)+sum1;
            }
    
            System.out.println(sum1);
            System.out.println(sum1*50);
            System.out.println(num100.size()*200);
            int aa=sum1*50;
            int bb=num100.size()*200;
            int cc=aa-bb;
            int dd=aa/100;
            System.out.println("卡顿率为:"+dd+"%");
        }
    }
    
    
    

    相关文章

      网友评论

        本文标题:计算视频卡顿率

        本文链接:https://www.haomeiwen.com/subject/hjfjvltx.html