关于视频抽帧调用虹软人脸识别的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;
    }
相关推荐
IC_1577961147629 分钟前
国产立体声音频数模转换器(DAC):CJC4344
音视频
ZFSS3 小时前
PixVerse 视频生成 API 实战教程
人工智能·ai·ai作画·音视频·ai编程
byte轻骑兵3 小时前
【LE Audio】CAP精讲[4]: Acceptor合规指南,从程序到协同全流程落地
人工智能·音视频·le audio·音视频控制
YWamy3 小时前
音视频SDK全解析:从技术演进到核心开发要点前瞻
音视频
Mr数据杨5 小时前
【CanMV K210】音频实验 I2S 数字麦克风与 FFT 频谱可视化
人工智能·音视频·硬件开发·canmv k210
2601_958352905 小时前
手撕环境噪音:双麦降噪模块AN-93上板实测,降噪36dB是真是假?
人工智能·音视频·嵌入式·降噪
木斯佳7 小时前
HarmonyOS 实战(源码教学篇):从一次语音识别率排查,讲透音频采集、PCM 与 ASR 同源校验
音视频·语音识别·harmonyos
AI创界者7 小时前
【2026前沿】LTX 2.3 深度实战:结合 Gemma 4完全体 打造电影级文生视频/图生视频全流程
人工智能·音视频
不爱学英文的码字机器7 小时前
被 AE 的关键帧折磨过的人,应该试试这个用 React 写视频的路子
前端·react.js·音视频
zhangfeng11337 小时前
Remotion 渲染视频脚本 ,自动化编辑视频 Node.js 层面是“单线程 JS”,但在实际渲染时是“高度并行”的。
node.js·自动化·音视频