前言
查看了相关文章然后一笔一笔打代码再调试成功出结果,
eguid的博客
不保证代码能够原封不动就能运行,
这里做一下记录。
ps:代码内容有改动,原版的可以看原作者的。
代码内容
package net.w2p.JCVStudio.zhiboStudy;
/**
* 前言:
* 鉴于很多同学反馈目前javacv采集摄像头存在几点问题
*
* 1、javacv采集摄像头帧率很低
*
* 2、javacv中的摄像头采集依赖opencv的capture采集器,获取的Mat没有及时释放,容易内存溢出
*
* 3、javacv封装的太死,调用摄像头不灵活,无法遍历摄像头设备列表
*
* 4、javacv打开摄像头太慢,一般要3秒才能打开摄像头设备
*
* 所以直接使用opencv采集摄像头设备是一个比较好的方案,并且采集效率上得到了很大的提高,不会像javacv里面一样摄像头掉帧比较严重。
* ————————————————
* 版权声明:本文为CSDN博主「本博客已停止维护!-eguid」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
* 原文链接:https://blog.csdn.net/eguid_1/article/details/58027720
* 一、实现的功能
*
*
* (1)opencv原生摄像头图像采集
*
* (2)opencv原生摄像头设备遍历
*
* (3)Mat转换为Frame
*
* (4)计算实时帧率
*
* (5)文字水印(显示实时帧率)
* **/
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point;
import org.bytedeco.opencv.opencv_core.Scalar;
import org.bytedeco.opencv.opencv_videoio.VideoCapture;
import javax.swing.*;
import java.text.DecimalFormat;
/***
* 第一课,遍历调用摄像头并且:
* 01 显示原始图像
* 02 将原始头像添加上水印文字
* 03 将原始图像加文字以后用推流器保存到本地。
*
* ***/
public class Lesson01 {
private static final Double FRAME_RATE = 25.0;
final Double imageTime = 0.04*1000;
long startTime = System.currentTimeMillis();
/**
* 无水印,无帧率计算实现:
* **/
public void study01(){
VideoCapture vc=null;
//遍历查找摄像头
int index=-1;
for(;index<2;index++){
vc=new VideoCapture(index);
if(vc.grab()){
//找到摄像头设备,退出遍历
System.err.println("当前摄像头:"+index);
break;
}
vc.close();//没找到设备,释放资源
}
//vc为null,并且设备没正常开启,说明没找到设备
if(vc!=null&&!vc.isOpened()){
System.err.println("无法找到摄像头,请检查是否存在摄像头设备");
return;
}
//使用java的JFrame显示图像
CanvasFrame cFrame = new CanvasFrame("做好自己!--eguid!http://www.eguid.cc/",CanvasFrame.getDefaultGamma()/2.2);
//javacv提供的转换器,方便mat转换为Frame
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
Mat mat=new Mat();
for(;;){
vc.retrieve(mat);//重新获取mat
if(vc.grab()){//是否采集到摄像头数据
if(vc.read(mat)){//读取一帧mat图像
// opencv_highgui.imshow("eguid", mat);该opencv方法windows下会无响应
cFrame.showImage(converter.convert(mat));
}
mat.release();//释放mat
}
try {
Thread.sleep(45);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/***
* 调用摄像头,添加水印文字。
* **/
public void study02(){
//做好自己!--eguid!http://www.eguid.cc
String msg="fps:";//水印文字
// 水印文字位置
Point point = new Point(10, 50);
// 颜色,使用黄色
Scalar scalar = new Scalar(0, 255, 255, 0);
DecimalFormat df=new DecimalFormat(".##");//数字格式化
VideoCapture vc=null;
//遍历查找摄像头
int index=-1;
for(;index<2;index++){
vc=new VideoCapture(index);
if(vc.grab()){
//找到摄像头设备,退出遍历
System.err.println("做好自己!--eguid温馨提示,获取本机当前摄像头序号:"+index);
break;
}
vc.close();//没找到设备,释放资源
}
//vc为null,并且设备没正常开启,说明没找到设备
if(vc!=null&&!vc.isOpened()){
System.err.println("无法找到摄像头,请检查是否存在摄像头设备");
return;
}
//使用java的JFrame显示图像
CanvasFrame cFrame = new CanvasFrame("做好自己!--eguid!http://www.eguid.cc",
CanvasFrame.getDefaultGamma()/2.2);
cFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
cFrame.setAlwaysOnTop(true);
//javacv提供的转换器,方便mat转换为Frame
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
Mat mat=new Mat();
double start=System.currentTimeMillis();
double end;
Frame ftmp=null;
for(int i=0;;i++){
ftmp=null;
vc.retrieve(mat);//重新获取mat
if(vc.grab()){//是否采集到摄像头数据
if(vc.read(mat)){//读取一帧mat图像
end=System.currentTimeMillis();
if(mat!=null){
opencv_imgproc.putText(mat,msg+df.format((1000.0/(end-start))),
point, opencv_imgproc.CV_FONT_VECTOR0, 1.2, scalar,
1, 20, false);
}
// opencv_highgui.imshow("eguid", mat);该opencv方法windows下会无响应
ftmp=converter.convert(mat);
cFrame.showImage(ftmp);
System.err.println(i);
start=end;
}
mat.release();//释放mat
}
if(ftmp!=null){
//--导出到视频中区。
}
if (!cFrame.isDisplayable()||!cFrame.isActive()||i>100) {//窗口是否关闭
System.out.println("窗口关闭啦,请做收尾工作");
// grabber.stop();//停止抓取
if(ftmp!=null){
}
System.exit(-1);//退出
return;
}
}
}
/***
* 添加水印并且导出为一个MP4文件。
*
* **/
public void study03() throws Exception {
//做好自己!--eguid!http://www.eguid.cc
String msg="fps:";//水印文字
// 水印文字位置
Point point = new Point(10, 50);
// 颜色,使用黄色
Scalar scalar = new Scalar(0, 255, 255, 0);
DecimalFormat df=new DecimalFormat(".##");//数字格式化
VideoCapture vc=null;
//遍历查找摄像头
int index=-1;
for(;index<2;index++){
vc=new VideoCapture(index);
if(vc.grab()){
//找到摄像头设备,退出遍历
System.err.println("做好自己!--eguid温馨提示,获取本机当前摄像头序号:"+index);
break;
}
vc.close();//没找到设备,释放资源
}
//vc为null,并且设备没正常开启,说明没找到设备
if(vc!=null&&!vc.isOpened()){
System.err.println("无法找到摄像头,请检查是否存在摄像头设备");
return;
}
//使用java的JFrame显示图像
CanvasFrame cFrame = new CanvasFrame("做好自己!--eguid!http://www.eguid.cc",
CanvasFrame.getDefaultGamma()/2.2);
cFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
cFrame.setAlwaysOnTop(true);
//javacv提供的转换器,方便mat转换为Frame
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
Mat mat=new Mat();
double start=System.currentTimeMillis();
double end;
Frame ftmp=null;
Java2DFrameConverter converter1 = new Java2DFrameConverter();
OpenCVFrameConverter.ToIplImage converter2 = new OpenCVFrameConverter.ToIplImage();
final String outputFilePath="/home/too-white/temp/001_study03.flv";
FFmpegFrameRecorder recorder = null;
for(int i=0;;i++){
ftmp=null;
vc.retrieve(mat);//重新获取mat
if(vc.grab()){//是否采集到摄像头数据
if(vc.read(mat)){//读取一帧mat图像
end=System.currentTimeMillis();
if(mat!=null){
opencv_imgproc.putText(mat,msg+df.format((1000.0/(end-start))),
point, opencv_imgproc.CV_FONT_VECTOR0, 1.2, scalar,
1, 20, false);
}
// opencv_highgui.imshow("eguid", mat);该opencv方法windows下会无响应
ftmp=converter.convert(mat);
// Frame rotatedFrame=converter.convert(grabbedImage);//不知道为什么这里不做转换就不能推到rtmp
if(recorder==null){
recorder=
new FFmpegFrameRecorder(outputFilePath,
ftmp.imageWidth,ftmp.imageHeight);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264,编码
// recorder.setFormat("flv");
recorder.setFormat("flv");//封装格式,如果是推送到rtmp就必须是flv封装格式
recorder.setPixelFormat(0);
int frameRate=25;
recorder.setFrameRate(frameRate);
try {
recorder.start();
startTime=System.currentTimeMillis();
}
catch (Exception ed){
ed.printStackTrace();
}
}
cFrame.showImage(ftmp);
/***计算帧的时间**/
Double imageFrameSpendTime=(1/recorder.getFrameRate())*1000;
long time = 1000*(System.currentTimeMillis() - startTime
+ imageFrameSpendTime.longValue()*i
);
if (time > recorder.getTimestamp()) {
System.out.println("时间>===record时间。");
recorder.setTimestamp(time);
}
recorder.record(ftmp);
System.err.println(i);
start=end;
}
mat.release();//释放mat
}
if(ftmp!=null){
//--导出到视频中区。
}
if (!cFrame.isDisplayable()||!cFrame.isActive()||i>100) {//窗口是否关闭
if(recorder!=null){
recorder.stop();
}
System.out.println("窗口关闭啦,请做收尾工作");
// grabber.stop();//停止抓取
if(ftmp!=null){
}
System.exit(-1);//退出
return;
}
}
}
public static void main(String[] args) throws Exception{
Lesson01 test=new Lesson01();
test.study03();
}
}