视频帧处理util


import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 视频帧处理
 *         <dependency>
 *             <groupId>org.bytedeco</groupId>
 *             <artifactId>javacv-platform</artifactId>
 *             <version>1.3.1</version>
 *         </dependency>
 */
public class BytedecoJavacv {
    protected static String ffmpegApp;

    public BytedecoJavacv(String ffmpegApp){
        BytedecoJavacv.ffmpegApp = ffmpegApp;
    }
    /****
     * 获取指定时间内的图片
     * @param videoFilename:视频路径
     * @param thumbFilename:图片保存路径
     * @param width:图片长
     * @param height:图片宽
     * @param hour:指定时
     * @param min:指定分
     * @param sec:指定秒
     * @throws IOException
     * @throws InterruptedException
     */
    public static void getThumbWindows(String videoFilename, String thumbFilename, int width, int height, int hour, int min, float sec) throws IOException,InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder(ffmpegApp, "-y",
                "-i", videoFilename, "-vframes", "1", "-ss", hour + ":" + min
                + ":" + sec, "-f", "mjpeg", "-s", width + "*" + height,
                "-an", thumbFilename);
        Process process = processBuilder.start();
        InputStream stderr = process.getErrorStream();
        InputStreamReader isr = new InputStreamReader(stderr);
        BufferedReader br = new BufferedReader(isr);
        String line;
        while ((line = br.readLine()) != null);
        process.waitFor();
        if(br != null){
            br.close();
        }
        if(isr != null) {
            isr.close();
        }
        if(stderr != null) {
            stderr.close();
        }
    }

    /**
     *
     * @param inFile
     * @param outFile
     * @param startTime
     * @return
     */
    public static boolean getThumbLinux(String inFile, String outFile,String startTime) {
        String command = "ffmpeg -i " + inFile
                + " -y -f image2 -ss "+startTime+" -t 00:00:01 -s 480x450 "
                + outFile;
        try {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(command);
            InputStream stderr = proc.getErrorStream();
            InputStreamReader isr = new InputStreamReader(stderr);
            BufferedReader br = new BufferedReader(isr);
            String line = null;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (Throwable t) {
            t.printStackTrace();
            return false;
        }
        return true;
    }


    /**
     * 获取指定视频的帧并保存为图片至指定目录
     * @throws Exception
     */
    public static String randomGrabberFFmpegImage(String filePath, String targerFilePath, String targetFileName)
            throws Exception {
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
        ff.start();

        int ffLength = ff.getLengthInFrames();
        Frame f;
        int i = 0;
        while (i < ffLength) {
            f = ff.grabImage();
            if ((i > 5) && (f.image != null)) {
                doExecuteFrame(f, targerFilePath, targetFileName);
                break;
            }
            i++;
        }
        String length ="" ;
        long lengthInTime = ff.getLengthInTime()/1000000;
        int hour = (int) (lengthInTime/3600);
        int minute = (int) (lengthInTime%3600)/60;
        int second = (int) (lengthInTime-hour*3600-minute*60);
        length = minute+":"+second;
        ff.stop();
        return length;
    }

    public static void doExecuteFrame(Frame f, String targerFilePath, String targetFileName) {
        if (null == f || null == f.image) {
            return;
        }

        Java2DFrameConverter converter = new Java2DFrameConverter();
        String imageMat = "jpg";
        String FileName = targerFilePath + File.separator + targetFileName;
        BufferedImage bi = converter.getBufferedImage(f);
        File output = new File(FileName);
        try {
            ImageIO.write(bi, imageMat, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static List<Integer> random(int baseNum, int length) {
        List<Integer> list = new ArrayList<>(length);
        while (list.size() < length) {
            Integer next = (int) (Math.random() * baseNum);
            if (list.contains(next)) {
                continue;
            }
            list.add(next);
        }
        Collections.sort(list);
        return list;
    }

    /**
     * 获取视频时长
     * @param source
     * @return
     */
    private String ReadVideoTime(File source) {
//        Encoder encoder = new Encoder();
//        String length = "";
//        try {
//            MultimediaInfo m = encoder.getInfo(source);
//            long ls = m.getDuration()/1000;
//            int hour = (int) (ls/3600);
//            int minute = (int) (ls%3600)/60;
//            int second = (int) (ls-hour*3600-minute*60);
//            length = hour+"'"+minute+"''"+second+"'''";
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return length;
        return null;
    }

    /**
     * 获取视频大小
     * @param source
     * @return
     */
    private String ReadVideoSize(File source) {
        FileChannel fc= null;
        String size = "";
        try {
            @SuppressWarnings("resource")
            FileInputStream fis = new FileInputStream(source);
            fc= fis.getChannel();
            BigDecimal fileSize = new BigDecimal(fc.size());
            size = fileSize.divide(new BigDecimal(1048576), 2, RoundingMode.HALF_UP) + "MB";
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null!=fc){
                try{
                    fc.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }
        return size;
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、问题的提出 做运动分析检测,需要有一定的素材视频,但是素材视频的编码OpenCV不能识别,无法对指定的视频做实验,怎么素材视频通用化使得OpenCV能正常识别? 二、解决的方法 (1)素材视频总是有配套的播放器来播放,那么使用这个播放器查看总数,和总播放时长,计算出率为25,表示一秒钟播放25图像。 (2)用这个配套的播放器对素材视频进行逐步进抓图,这个操作很辛苦,一秒钟25,那么抓25是一秒,素材视频30秒就要抓750,很辛苦。 (3)抓完后,发现一图1.4M,以位图格式保存,那么30秒就要达到1G的存储空间,怎么办?没办法,不知道怎么去获取解码器和安装解码器,就只能这么忍受。察看到逐步进抓图的存储是按序列编排文件名,那么要修改好使得每个文件名都是以规则“文件名”+“序列”的形式存在。 (4)编写根据序列图生成率25的视频的代码 三、问题的解决: (1)解决一个字符串合并的问题: 由于字符串参数有个赋值格式化设置函数叫做Format,要实现多类型参数的字符串化,可以参照如下示例: float f = 0.0; char sz[128]; int n = 1; CString str; str.Format("%f%s%d",f,sz,n); (2)采用MJPG的编码格式依次将这些图像序列写入到视频中保存起来,采用MJPG的编码格式是因为操作系统自带了Media player播放器,这种编码格式属于无压缩的,Media player可以识别播放。 (3)实现方式是使用MFC对话框窗体的按钮事件来进行视频的逐写图,由于数多,那么在写入器循环做写这个动作的时候,整个程序是假死在那里直到写入器的写入操作终结。
你可以使用JavaCV来处理视频,并使用多线程来提高处理效率。下面是一个简单的示例代码: ```java import org.bytedeco.javacv.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class VideoProcessing { public static void main(String[] args) { // 设置要处理视频文件路径 String videoFilePath = "path/to/video.mp4"; // 创建视频抓取器 FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoFilePath); try { // 开启抓取器 grabber.start(); // 获取视频率和数 double frameRate = grabber.getFrameRate(); int frameCount = grabber.getLengthInFrames(); // 计算每个线程需要处理int threads = Runtime.getRuntime().availableProcessors(); int framesPerThread = (int) Math.ceil((double) frameCount / threads); // 创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(threads); // 启动多个线程进行视频处理 for (int i = 0; i < threads; i++) { int startFrame = i * framesPerThread; int endFrame = Math.min(startFrame + framesPerThread, frameCount); executorService.execute(new VideoProcessor(grabber, startFrame, endFrame)); } // 关闭线程池 executorService.shutdown(); // 等待所有线程完成处理 while (!executorService.isTerminated()) { Thread.sleep(1000); } } catch (Exception e) { e.printStackTrace(); } finally { try { // 关闭抓取器 grabber.stop(); grabber.release(); } catch (FrameGrabber.Exception e) { e.printStackTrace(); } } } // 视频处理线程 static class VideoProcessor implements Runnable { private FFmpegFrameGrabber grabber; private int startFrame; private int endFrame; public VideoProcessor(FFmpegFrameGrabber grabber, int startFrame, int endFrame) { this.grabber = grabber; this.startFrame = startFrame; this.endFrame = endFrame; } @Override public void run() { try { // 定位到起始 grabber.setFrameNumber(startFrame); // 处理每一 for (int i = startFrame; i < endFrame; i++) { Frame frame = grabber.grabImage(); // 在这里进行处理操作 // 例如,将保存为图像文件 String filename = "frame_" + i + ".jpg"; Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage image = converter.convert(frame); ImageIO.write(image, "jpg", new File(filename)); } } catch (Exception e) { e.printStackTrace(); } } } } ``` 注意,这只是一个简单的示例,你可以根据具体需求添加更多的视频处理逻辑。通过使用多线程,你可以同时处理多个视频,从而提高处理速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值