Java原来可以这么玩!CV视频合成处理,视频前后拼接,画面合并

这篇具有很好参考价值的文章主要介绍了Java原来可以这么玩!CV视频合成处理,视频前后拼接,画面合并。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

本章内容教会你如何用java代码实现 两个视频的画面合并 或者前后拼接。原理是使用了javacv开源jar包,代码经过反复修改,已经实现我能想到的最优最快的实现,如果你有更好更快的实现,欢迎评论区留言!!!

先展示一下效果吧!!!

两个视频前后拼接

两个视频画面合并

JAVACV

简介

JavaCV是一款基于JavaCPP调用方式(JNI的一层封装),由多种开源计算机视觉库组成的包装库,封装了包含FFmpeg、OpenCV、tensorflow、caffe、tesseract、libdc1394、OpenKinect、videoInput和ARToolKitPlus等在内的计算机视觉领域的常用库和实用程序类。

JavaCV基于Apache License Version 2.0协议和GPLv2两种协议,JavaCV支持Windows、Linux、MacOS,Android、IOS在内的Java平台上调用这些接口。

JavaCV是一个基于Java语言的计算机视觉库,它提供了对多种计算机视觉库的接口和包装,使得Java开发者可以方便地使用计算机视觉技术。计算机视觉是人工智能领域的一个重要分支,它涉及到图像处理、视频分析、模式识别、机器学习等多个领域。应用场景需要使用到计算机视觉技术,例如人脸识别、目标检测、物体跟踪、手势识别等等。

JavaCV的特点

  • 跨平台性:JavaCV支持Windows、Linux、MacOS等多个操作系统,同时也支持Android、IOS等移动平台,使得Java开发者可以方便地在不同的平台上使用计算机视觉技术。
  • 丰富的接口和包装:JavaCV提供了对多种计算机视觉库的接口和包装,例如FFmpeg、OpenCV、tensorflow、caffe、tesseract等等。这些库都是计算机视觉领域的常用库和实用程序类,JavaCV的封装使得Java开发者可以方便地使用这些库的功能。
  • 易于使用:JavaCV的使用非常简单,只需要调用相应的接口即可实现相应的功能。同时,JavaCV还提供了丰富的示例代码和文档,方便开发者学习和使用。
  • 灵活扩展:JavaCV的设计非常灵活,可以方便地扩展新的接口和功能。同时,JavaCV还提供了开源的代码库和社区支持,方便开发者进行二次开发和交流。

JavaCV的使用场景

  • 图像处理:JavaCV提供了对图像处理的各种功能,例如图像转换、图像增强、图像分割等等。这些功能可以用于图像处理的各种应用场景,例如人脸识别、目标检测、图像识别等等。
  • 视频分析:JavaCV提供了对视频分析的各种功能,例如视频帧提取、视频流处理、视频目标跟踪等等。这些功能可以用于视频监控、视频分析、视频编辑等等应用场景。
  • 机器学习:JavaCV提供了对机器学习的各种功能,例如特征提取、分类器训练、模型评估等等。这些功能可以用于机器学习应用场景的各种任务,例如图像分类、目标检测、情感分析等等。
  • 3D重建:JavaCV提供了对3D重建的各种功能,例如3D点云处理、3D模型重建等等。这些功能可以用于3D扫描、3D建模、3D打印等等应用场景。
  • 其他应用:除了以上几个应用场景之外,JavaCV还可以用于其他各种计算机视觉应用场景,例如手势识别、物体识别、人脸识别等等。

添加jar依赖

   <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
		<dependency>
			<groupId>org.bytedeco</groupId>
			<artifactId>javacv-platform</artifactId>
			<version>1.5.9</version>
		</dependency>

完整代码展示

核心代码,单类实现,idea等编辑器内创建VideoMergeJoin类,复制粘贴下面代码,右键点击run运行主方法即可。

  • 其中 mergeVideo 方法是将两个帧数相同的的视频合并到一个画面中。
  • 其中 joinVideo 方法 是将两个视频进行前后拼接,第一个参数视频路径,拼接在前,第二个参数视频路径,拼接在后。
  • 修改 VIDEO_PATH1、VIDEO_PATH2 等需要合并和处理的视频文件路径
  • 修改MERGE_PATH、JOIN_PATH 视频合并或者拼接的生成文件路径


import org.bytedeco.javacv.*;
import org.bytedeco.javacv.Frame;

import java.awt.*;
import java.awt.image.BufferedImage;

/**
 * @author tarzan
 */
public class VideoMergeJoin {

    final static String VIDEO_PATH1 = "E:\\test.mp4";
    final static String VIDEO_PATH2 = "E:\\aivideo\\20231217-190828_with_snd.mp4";
    final static String MERGE_PATH= "E:\\test_merge.mp4";
    final static String JOIN_PATH= "E:\\test_join.mp4";

    public static void main(String[] args) throws Exception {
        long start=System.currentTimeMillis();
        mergeVideo(VIDEO_PATH1,VIDEO_PATH2,MERGE_PATH);
      // joinVideo(VIDEO_PATH1,VIDEO_PATH2,JOIN_PATH);
        System.out.println("耗时 "+(System.currentTimeMillis()-start)+" ms");
    }

    public static void joinVideo(String videoPath1,String videoPath2, String outPath) throws Exception {
        // 初始化视频源
        FFmpegFrameGrabber grabber1 = new FFmpegFrameGrabber(videoPath1);
        FFmpegFrameGrabber grabber2 = new FFmpegFrameGrabber(videoPath2);
        grabber1.start();
        grabber2.start();
        // 初始化目标视频
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outPath, grabber1.getImageWidth(), grabber1.getImageHeight(),grabber1.getAudioChannels());
        recorder.setVideoCodec(grabber1.getVideoCodec());
        recorder.setVideoBitrate(grabber1.getVideoBitrate());
        recorder.setAudioCodec(grabber1.getAudioCodec());
        recorder.setAudioBitrate(grabber1.getAudioBitrate());
        // 录制视频
        recorder.start();
        while (true){
            Frame frame= grabber1.grab();
            if (frame == null) {
                break;
            }
            recorder.record(frame);
        }
        while (true){
            Frame frame= grabber2.grab();
            if (frame == null) {
                break;
            }
            recorder.record(frame);
        }
        // 释放资源
        grabber1.stop();
        grabber2.stop();
        recorder.stop();
    }

    public static void mergeVideo(String videoPath1,String videoPath2, String outPath) throws Exception {
        // 初始化视频源
        FFmpegFrameGrabber grabber1 = new FFmpegFrameGrabber(videoPath1);
        FFmpegFrameGrabber grabber2 = new FFmpegFrameGrabber(videoPath2);
        grabber1.start();
        grabber2.start();
        // 检查帧率是否一样
        if (grabber1.getFrameRate() != grabber2.getFrameRate()) {
            throw new Exception("Video frame rates are not the same!");
        }
        // 初始化目标视频
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outPath, (grabber1.getImageWidth()+grabber2.getImageWidth()), grabber1.getImageHeight(),grabber1.getAudioChannels());
        recorder.setVideoCodec(grabber1.getVideoCodec());
        recorder.setVideoBitrate(grabber1.getVideoBitrate());
        recorder.setAudioCodec(grabber1.getAudioCodec());
        recorder.setAudioBitrate(grabber1.getAudioBitrate());
        // 录制视频
        recorder.start();
        int i=1;
        int videoSize = grabber1.getLengthInVideoFrames();
        while (true){
            Frame frame1= grabber1.grab();
            if (frame1 == null) {
                break;
            }
            if (frame1.image != null) {
                // 将两个帧合并为一个画面
                Frame frame2=grabber2.grabImage();
                System.out.println("视频共" + videoSize + "帧,正处理第" + i  + "帧图片 ");
                // 创建一个新的 BufferedImage 用于合并画面
                BufferedImage combinedImage = new BufferedImage(grabber1.getImageWidth()+grabber2.getImageWidth(), grabber1.getImageHeight(), BufferedImage.TYPE_3BYTE_BGR);
                Graphics2D g2d = combinedImage.createGraphics();
                // 在合并画面上绘制两个视频帧
                g2d.drawImage(Java2DFrameUtils.toBufferedImage(frame1), 0, 0, null);
                g2d.drawImage(Java2DFrameUtils.toBufferedImage(frame2), grabber1.getImageWidth(), 0, null);
                g2d.dispose();
                // ImageIO.write(combinedImage,"png",new File("E:\\images1\\combinedImage"+i+".png"));
                // 将合并后的 BufferedImage 转换为帧并录制到目标视频中
                recorder.record(Java2DFrameUtils.toFrame(combinedImage));
                i++;
            }
            if (frame1.samples != null) {
                recorder.recordSamples(frame1.sampleRate, frame1.audioChannels, frame1.samples);
            }
        }
        // 释放资源
        grabber1.stop();
        grabber2.stop();
        recorder.stop();
    }

}


控制台运行输出日志
java两个视频重叠播放怎么弄,粉丝专栏,java,音视频,开发语言文章来源地址https://www.toymoban.com/news/detail-811599.html

  • 两个 15s- 458帧的视频,合并画面 耗时 26s
  • 两个 15s- 458帧的视频,前后拼接 耗时 6.6s

到了这里,关于Java原来可以这么玩!CV视频合成处理,视频前后拼接,画面合并的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 央视的《AI我中华》宣传视频,原来这么简单?

    前段时间,央视的《爱我中华》AI宣传短片火爆全网,有一个穿越转场效果非常惊艳! 今天就先来详细讲解,如何利用Stable Diffusion制作这样的穿越转场视频。 用到的扩展插件就是大名鼎鼎的Deforum,其实很早以前很火的“瞬息全宇宙”视频也是用它来完成的。 需要AI绘画素材

    2024年04月26日
    浏览(25)
  • 原来可以这么玩?Jmeter接口性能测试工具玩转测试Redis数据库(超详细)

    Jmeter作为当前非常受欢迎的接口测试和性能测试的工具,在企业中得到非常广泛的使用,而redis作为缓存数据库,也在企业中得到普遍使用,那如何使用jmeter来测试redis数据库呢? 今天我们就来讲一讲怎么使用jmeter来调用redis。 Jmeter准备 由于jmeter本身并没有带有redis的测试入

    2024年02月13日
    浏览(43)
  • 不直播拍视频,一样可以变现,原来是做了这个!

    我是电商珠珠 随着直播带货的流行,部分大学也开始紧随其后,相继增设网络营销与直播电商这项课程。 以上这些技能,部分人并不知道怎么搞,一是不想麻烦,没那么多时间精力,二是做不起来,自身没有那些才艺,吸引不到粉丝。 既然直播带货不行,那么就另谋他法。

    2024年02月08日
    浏览(33)
  • opencv 将多帧图像合成为视频 cv2.VideoWriter()

    将文件夹下有时间戳或者有序的 *.jpg 图像合成为一个 mp4 格式的视频。 附加:加进度条看合成进度。 以上示例合成视频为 mp4 格式,如需合成其它视频格式,可修改 cv2.VideoWriter_fourcc() 参数。请自行查询相关参数。

    2024年02月11日
    浏览(32)
  • 可以提高DeepFaceLab(DeepFake)合成最终视频速度的方法

    DeepFaceLab相关文章 一:《简单介绍DeepFaceLab(DeepFake)的使用以及容易被忽略的事项》 二:《继续聊聊DeepFaceLab(DeepFake)不断演进的2.0版本》 三:《如何翻译DeepFaceLab(DeepFake)的交互式合成器》 四:《想要提高DeepFaceLab(DeepFake)质量的注意事项和技巧(一)》 五:《想要

    2024年02月03日
    浏览(27)
  • 记录--原来前端部署这么简单

    有个朋友说前端技能大家大部分都会,就是部署项目这一块经验都比较稀缺,一直很想学一下。所以在这里写一篇简单的从零开始部署前端项目的全过程,感兴趣的掘友们或者想自己搭建项目部署的可以看一下这篇。 首先我们需要进行环境搭建主要就是 服务器 和 nginx配置

    2024年02月05日
    浏览(42)
  • KMP算法原理原来这么简单

    我觉得这句话说的很好: kmp算法关键在于:在当前对文本串和模式串检索的过程中,若出现了不匹配,如何充分利用已经匹配的部分,来继续接下来的检索。 暴力解法就是两层for循环,每次都一对一的匹配,如果匹配错误就文本串开始位置加1,继续下一次 前缀表的作用就是

    2023年04月21日
    浏览(34)
  • 物联网网关,原来是这么回事,感谢!

    《高并发系统实战派》-- 你值得拥有 物联网网关是连接物联网设备和互联网的重要桥梁,它负责将物联网设备采集到的数据进行处理、存储和转发,使其能够与云端或其他设备进行通信。物联网网关的作用是实现物联网设备与云端的无缝连接和数据交换。 不要物联网网关行

    2024年02月08日
    浏览(38)
  • 原来服务器这么有用-Docker安装

    在此之前青阳通过各种方式介绍过自己通过服务器搭建的一些玩法,也写过一些教程,但是那些教程,现在回头来看,都是有些杂乱了,统一性不强。我就准备重新整理一下之前写的文章,并且准备重新开一个专题来写自己折腾的内容,专题的名字就叫-原来服务器这么有用。

    2024年02月04日
    浏览(52)
  • 原来.NET写的Linux桌面这么好看?

    本文将讲解如何使用 Blazor 运行跨平台应用,应用到的技术有以下几点 Blazor Masa Blazor Photino.Blazor Ubuntu 用于验证跨平台性,并且是否提高开发效率,Blazor和Photino一块使用的技术称为 Blazor Hybrid , Blazor是一种使用.NET和C#构建客户端Web应用程序的新兴技术。它允许开发者在浏览器

    2024年02月05日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包