当前位置: 首页 > article >正文

关于视频抽帧调用虹软人脸识别的BufferedImage读取优化策略

背景说明:

1、在使用 FfmpegFrameGrabber 调用本地视频文件,逐帧读取视频内容

FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(file);
// 不读取音频,否则frame.image = null
grabber.setAudioStream(-1);
grabber.start();

2、遍历所有帧

while(true){
    // 抓取目标帧
    Frame frame = grabber.grabFrame();
    if(frame == null){
        break;
    }
    if(frame.image == null){
      continue;
    }
}

3、frame转BufferedImage

在大部分的网站搜索中,通常使用Java2DFrameConverter 函数进行frame提取转换,

但占用过多CPU

import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.enums.ImageFormat;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;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.ByteArrayOutputStream;
import java.nio.ByteBuffer;

Java2DFrameConverter jfc = new Java2DFrameConverter();
BufferedImage bufferedImage = jfc.getBufferedImage(frame);
ImageInfo imageInfo = ImageFactory.bufferedImage2ImageInfo(bufferedImage);

4、采用读取Frame.image直接获取

ImageInfo imageInfo = new ImageInfo();
imageInfo.setWidth(frame.imageWidth);
imageInfo.setHeight(frame.imageHeight);
imageInfo.setImageFormat(ImageFormat.CP_PAF_RGB24);
imageInfo.setImageData(convertByteArray((ByteBuffer)frame.image[0]));
private  byte[] convertByteArray(ByteBuffer buffer)   {
    int length = buffer.remaining();
    // 创建目标 byte[] 数组
    byte[] result = new byte[length];
    int offset = 0;
    // 复制每个 DirectByteBuffer 的内容到 byte[] 数组
    buffer.get(result, offset, length);
    buffer.rewind(); // 重置缓冲区位置
    return result;
}

部分参数的变动需要参考读取帧Frame对象的内容做适当调整

参考 Java2DFrameConverter 的 getBufferedImageType()

public static int getBufferedImageType(Frame frame) {
        int type = 0;
        if (frame.imageChannels == 1) {
            if (frame.imageDepth != 8 && frame.imageDepth != -8) {
                if (frame.imageDepth == 16) {
                    type = 11;
                }
            } else {
                type = 10;
            }
        } else if (frame.imageChannels == 3) {
            if (frame.imageDepth == 8 || frame.imageDepth == -8) {
                type = 5;
            }
        } else if (frame.imageChannels == 4 && (frame.imageDepth == 8 || frame.imageDepth == -8)) {
            type = 6;
        }

        return type;
    }


http://www.kler.cn/a/553897.html

相关文章:

  • 基于微信小程序的民宿短租系统设计与实现(ssm论文源码调试讲解)
  • 如何在Ubuntu服务器上快速安装GNOME桌面环境
  • ​44页PDF | 天津大学深度解读DeepSeek:原理与效应(附下载)
  • 解决DeepSeek服务器繁忙问题的实用指南
  • UE5.3 C++ 通过Spline样条实现三维连线,自己UV贴图。
  • Linux-----进程(多任务)
  • Pycharm中查找与替换
  • 介绍cherrypick
  • FFmpeg 源码编译安装
  • Zookeeper(58)如何在Zookeeper中实现分布式锁?
  • 《剑指数据库:MySQL安装布阵全解》
  • 1.buuctf [BJDCTF2020]EasySearch
  • 【c++】c++内存管理
  • 老游戏回顾:d2
  • 数据库连接管理--Java连接数据库的几种方式
  • python concurrent.futures
  • 【2025最新计算机毕业设计】基于SSM的社区老人服务平台 可定制开发【提供源码+答辩PPT+文档+项目部署】
  • 【LLAMA】羊驼从LLAMA1到LLAMA3梳理
  • SpringBoot+uniApp日历备忘录小程序系统 附带详细运行指导视频
  • [Android]文件描述符的binder传送