最近项目都在跟摄像头打交道,对录制视频流以及抓取图片这一块做了详细的研究,由于目前的摄像头支持可见光以及红外光,之前录制可见光直播流可以见博客使用ffmpeg录制直播流,这两天由于需要对红外光通道进行图像抓取,后面用人像识别算法来识别,所以本文介绍一下如何抓取视频流图像。
方法一:使用javacv进行图像抓取
项目依赖
<dependency>
<groupId>org
.bytedeco
</groupId
>
<artifactId>javacv
</artifactId
>
<version>1.5.1</version
>
</dependency
>
<dependency>
<groupId>org
.bytedeco
</groupId
>
<artifactId>ffmpeg
-platform
</artifactId
>
<version>4.1.3-1.5.1</version
>
</dependency
>
上代码,复制即可使用(方法参数自己稍作修改)
public void frameRecordImage(String inputFile
, String outputFile
, String imgMat
, String frameRate
,String imageName
) throws Exception
{
avutil
.av_log_set_level(avutil
.AV_LOG_FATAL
);
MyFFmpegFrameGrabber grabber
= new MyFFmpegFrameGrabber(inputFile
);
grabber
.setOption("rtsp_transport", "tcp");
grabber
.setImageWidth(640);
grabber
.setImageHeight(360);
grabber
.setTimeout(3000);
grabber
.setFrameRate(frameRate
);
grabber
.setVideoBitrate(3000000);
Java2DFrameConverter converter
= new Java2DFrameConverter();
recordByFrame(grabber
, converter
, outputFile
, imgMat
, imageName
);
}
private void recordByFrame(MyFFmpegFrameGrabber grabber
, Java2DFrameConverter converter
, String
outputFile
, String imgMat
,String imageName
) throws Exception
{
try {
log
.info("the code {} grab start");
grabber
.start();
imageByframe(grabber
, converter
, outputFile
, imgMat
, imageName
);
grabber
.stop();
log
.info("the code {} grab stop");
} finally {
if (grabber
!= null
) {
grabber
.stop();
log
.info("the code {} grab stop");
}
}
}
private void imageByframe(MyFFmpegFrameGrabber grabber
, Java2DFrameConverter converter
, String outputFile
, String
imgMat
,String imageName
) throws IOException
{
Frame frame
= grabber
.grabImage();
BufferedImage bi
= converter
.convert(frame
);
outputFile
= outputFile
+ SLASH
+ imageName
+ Field
.DOT
+ imgMat
;
ImageIO
.write(bi
, imgMat
, new File(outputFile
));
}
public static void main(String
[] args
) {
RecordUtil recordUtil
= new RecordUtil();
recordUtil
.frameRecordImage("rtmp流地址", "图片输出路径", "图片后缀", "帧率", "图片名");
}
方法二:使用ffmpeg进行图像抓取
首先在服务器安装ffmpeg工具,见文章Linux安装ffmpeg详细教程(超细)上代码,复制即可用
public void grabImage(String videoFilename
, String imageName
, String outFile
, int width
,
int height
, int hour
, int min
, float sec
, Device device
, long eventTime
) throws IOException
, InterruptedException
{
createFile(outFile
);
ProcessBuilder processBuilder
= getProcessBuilder(videoFilename
, imageName
, outFile
, width
, height
, hour
, min
, sec
);
log
.info("抓取红外图片... start");
Process process
= processBuilder
.start();
InputStream stderr
= process
.getErrorStream();
InputStreamReader isr
= new InputStreamReader(stderr
);
BufferedReader br
= new BufferedReader(isr
);
while (br
.readLine() != null
) ;
process
.waitFor();
log
.info("抓取红外图片... end");
outFile
= outFile
+ SLASH
+ imageName
;
addEventHWImage(device
, eventTime
, outFile
);
if (br
!= null
)
br
.close();
if (isr
!= null
)
isr
.close();
if (stderr
!= null
)
stderr
.close();
}
@NotNull
private ProcessBuilder
getProcessBuilder(String videoFilename
, String imageName
, String outFile
, int width
, int height
, int hour
, int min
, float sec
) {
String rtmpTool
= "ffmpeg";
return new ProcessBuilder(rtmpTool
, "-y",
"-i", videoFilename
, "-vframes", "1", "-ss", hour
+ ":" + min
+ ":" + sec
, "-f", "mjpeg", "-s", width
+ "*" + height
,
"-an", outFile
.concat(File
.separator
).concat(imageName
));
}
public static void main(String
[] args
) {
recordUtil
.grabImage(liveInfraRed
, eventTime
+ PNG_LAST
, VIDEO_URL
+ device
.getDeviceId(), 1920, 1080, 0, 0, 0, device
, eventTime
);
}
两种方法自行选择 网上找到一个开放的rtmp流地址供大家测试:rtmp://58.200.131.2:1935/livetv/hunantv