小言_互联网的博客

Java原来可以这么玩!CV视频合成处理,制作2宫格、4宫格、多宫格的视频

474人阅读  评论(0)

效果展示

图片合成效果,不再演示,主要演示视频合成效果,因为是视频合成的原理就是先将每一张帧图合成图片,再用合成的图片制作成视频。

视频左右翻转合成效果

javacv实现视频翻转,合成

 四宫格视频

更多视频展示链接

https://live.csdn.net/v/164980

注:原视频都来自于抖音。

添加jar依赖

Java spring boot项目或者maven项目的pom文件中添加以下依赖  


  
  1. <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
  2. <dependency>
  3. <groupId>org.bytedeco </groupId>
  4. <artifactId>javacv-platform </artifactId>
  5. <version>1.5.5 </version>
  6. </dependency>

代码展示

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


  
  1. import org.bytedeco.javacv.FFmpegFrameGrabber;
  2. import org.bytedeco.javacv.FFmpegFrameRecorder;
  3. import org.bytedeco.javacv.Frame;
  4. import org.bytedeco.javacv.Java2DFrameConverter;
  5. import javax.imageio.ImageIO;
  6. import java.awt.image.BufferedImage;
  7. import java.io.File;
  8. import java.io.IOException;
  9. public class VideoSynthesis {
  10. final static String videoFolderPath = "C:/Users/tarzan/Desktop/video/";
  11. final static String videoName = "video.mp4";
  12. final static String imageFolderPath = "C:/Users/tarzan/Desktop/image/";
  13. final static String imageName1 = "logo.jpg";
  14. final static String imageName2 = "newlogo.jpg";
  15. public static void main(String[] args) throws Exception {
  16. // mergeImage(imageFolderPath + imageName1, imageFolderPath + imageName2);
  17. mergeVideo(videoFolderPath + videoName);
  18. }
  19. //视频处理
  20. public static void mergeVideo(String filePath) {
  21. //抓取视频图像资源
  22. FFmpegFrameGrabber videoGrabber = new FFmpegFrameGrabber(filePath);
  23. //抓取视频图像资源
  24. FFmpegFrameGrabber audioGrabber = new FFmpegFrameGrabber(filePath);
  25. try {
  26. videoGrabber.start();
  27. audioGrabber.start();
  28. //imageWidth和imageHeight根据需要合成的大小进行计算,比如左右2宫格宽度需要乘以2,四宫格宽、高都要乘以2,依次类推
  29. FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(videoFolderPath + "合成" + videoName, videoGrabber.getImageWidth()* 2, videoGrabber.getImageHeight(), videoGrabber.getAudioChannels());
  30. recorder.start();
  31. //处理图像
  32. int videoSize = videoGrabber.getLengthInVideoFrames();
  33. for ( int i = 0; i < videoSize; i++) {
  34. Frame videoFrame = videoGrabber.grabImage();
  35. if (videoFrame != null && videoFrame.image != null) {
  36. System.out.println( "视频共" + videoSize + "帧,正处理第" + (i + 1) + "帧图片");
  37. Java2DFrameConverter converter = new Java2DFrameConverter();
  38. //获得原图帧
  39. BufferedImage bi = converter.getBufferedImage(videoFrame);
  40. //获得翻转图帧
  41. BufferedImage bi2= imageFlipLR(bi);
  42. //获得左右合成图帧
  43. BufferedImage bufImg=mergeImageLR(bi,bi2);
  44. // bufImg= mergeImageCenter(bufImg,bi);
  45. recorder.record(converter.convert(bufImg));
  46. }
  47. }
  48. //处理音频
  49. int audioSize = audioGrabber.getLengthInAudioFrames();
  50. for ( int i = 0; i < audioSize; i++) {
  51. Frame audioFrame = audioGrabber.grabSamples();
  52. if (audioFrame != null && audioFrame.samples != null) {
  53. recorder.recordSamples(audioFrame.sampleRate, audioFrame.audioChannels, audioFrame.samples);
  54. }
  55. }
  56. recorder.stop();
  57. recorder.release();
  58. videoGrabber.stop();
  59. audioGrabber.stop();
  60. } catch (Exception e) {
  61. e.printStackTrace();
  62. }
  63. }
  64. //合拼图片
  65. public static void mergeImage(String imgPath1, String imgPath2) {
  66. try {
  67. BufferedImage bi_1 = ImageIO.read( new File(imgPath1));
  68. BufferedImage bi_2 = ImageIO.read( new File(imgPath2));
  69. BufferedImage mergeImage = mergeImageLR(bi_1, bi_2);
  70. ImageIO.write(mergeImage, "png", new File(imageFolderPath + imageName1 + "merge" + imageName2));
  71. } catch (IOException e) {
  72. e.printStackTrace();
  73. }
  74. }
  75. //小图放到大图中间位置
  76. public static BufferedImage mergeImageCenter(BufferedImage big, BufferedImage small) {
  77. //new 一个新的图像
  78. int w = small.getWidth();
  79. int h = small.getHeight();
  80. int wd = small.getWidth()/ 2;
  81. int hd = small.getHeight()/ 2;
  82. //像素一个一个复制过来
  83. for ( int y = 0; y < h; y++) {
  84. for ( int x = 0; x < w; x++) {
  85. big.setRGB(x+wd, y+hd, small.getRGB(x, y));
  86. }
  87. }
  88. return big;
  89. }
  90. //左右翻转
  91. public static BufferedImage imageFlipLR(BufferedImage bi) {
  92. int h = bi.getHeight();
  93. int w = bi.getWidth();
  94. BufferedImage image = new BufferedImage(w, h, bi.getType());
  95. //像素一个一个复制过来
  96. for ( int y = 0; y < h; y++) {
  97. for ( int x = 0; x < w; x++) {
  98. image.setRGB(x, y, bi.getRGB(w-x- 1, y));
  99. }
  100. }
  101. return image;
  102. }
  103. //左右合并
  104. public static BufferedImage mergeImageLR(BufferedImage bi_1, BufferedImage bi_2) {
  105. //new 一个新的图像
  106. int w1 = bi_1.getWidth();
  107. int w2 = bi_2.getWidth();
  108. int h = bi_1.getHeight();
  109. int w = w1 + w2;
  110. BufferedImage bi = new BufferedImage(w, h, bi_1.getType());
  111. //像素一个一个复制过来
  112. for ( int y = 0; y < h; y++) {
  113. for ( int x = 0; x < w1; x++) {
  114. bi.setRGB(x, y, bi_1.getRGB(x, y));
  115. }
  116. for ( int x = 0; x < w2; x++) {
  117. bi.setRGB(w1 + x, y, bi_2.getRGB(x, y));
  118. }
  119. }
  120. return bi;
  121. }
  122. //上下合并
  123. public static BufferedImage mergeImageUD(BufferedImage bi_1, BufferedImage bi_2) {
  124. //new 一个新的图像
  125. int h1 = bi_1.getHeight();
  126. int h2 = bi_2.getHeight();
  127. int h = h1+h2;
  128. int w = bi_1.getWidth();
  129. BufferedImage bi = new BufferedImage(w, h, bi_1.getType());
  130. //像素一个一个复制过来
  131. for ( int x = 0; x < w; x++) {
  132. for ( int y = 0; y < h1; y++) {
  133. bi.setRGB(x, y, bi_1.getRGB(x, y));
  134. }
  135. for ( int y = 0; y< h2; y++) {
  136. bi.setRGB(x, h1+y, bi_2.getRGB(x, y));
  137. }
  138. }
  139. return bi;
  140. }
  141. }

由于视频中的每一帧需要合成处理,过程可能辉有点慢,像文章中的视频,原视频3.93MB,经过翻转处理、左右合成处理的方法,处理时间月20s左右。

控制台运行输出日志

代码里还写了上下合成、小图放在大图的中心位置等方法,方便你处理各种需求。 

 相关文章推荐

《震惊,java仅用30行代码就实现了视频转音频的批量转换》

特别说明:如需转载此篇文章,请先关注本人后,注明作者名称,和文章链接地址即可。


转载:https://blog.csdn.net/weixin_40986713/article/details/117330543
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场