opencv+javacv+eclipse+windows 从视频到——灰度直方图
最近在做storm的项目,由于storm不能很好的支持C++,所以决定用java来实现下从视频到关键帧再到灰度直方图的操作。于是接触到opencv,查了相关资料和别人的一些帖子进一步了解到可以通过javacv在eclipse部署之后方可实现。
相关的javacv的不是操作,相关的资料也有不少,这里不再具体讲解安装和部署的过程,只把中间注意的问题列一下:
1.因为opencv和javacv都需要jar包的引入,所以版本的选择很重要,我选的是javacv1.0 +opencv2.4.9,其实开始下载的是比较新的版本opencv3.0,一直出现util的错误,后来就改为2.4.9了。
2.解压安装包时,尽量放在C盘的根目录,否则有时候会编译出错,当然这一步不是必须的。
3.jar包的引入,一定要与系统的位数对应,例32位操作系统就使用x86的相关jar。
4.相关环境变量的配置,这里不再复述,否则会出现java.library.path类似的错误。
在部署好环境之后,可以先用一段代码进行测试:
public static void main(String[] args) {
//读取图像
IplImage srcImg=cvLoadImage("data/SouthEast.jpg");//这里改成自己的路径
if (srcImg !=null) {
cvNamedWindow("test");
cvShowImage("test",srcImg);
cvWaitKey(0);
cvReleaseImage(srcImg);
cvDestroyWindow("test");
}
测试成功后,可以进行视频的提取帧操作了,这里我是按照每3秒提取一帧(基本思路是先获取输入视频流的帧率,每次跳过3秒所包含的帧率即可),代码如下:
CvCapture capture = opencv_highgui.cvCreateFileCapture("C:/Users/hp03/Desktop/www.ygdy8.com.rmvb");
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span> //每秒帧率
<span style="white-space:pre"> </span> int fps = (int) opencv_highgui.cvGetCaptureProperty(capture, opencv_highgui.CV_CAP_PROP_FPS);
<span style="white-space:pre"> </span> while (true) { //读取关键帧 <span style="white-space:pre"> </span>
<span style="white-space:pre"> </span> frame = opencv_highgui.cvQueryFrame(capture); <span style="white-space:pre"> </span>
<span style="white-space:pre"> </span> //得到灰度值
<span style="white-space:pre"> </span> getGray(frame.getBufferedImage());
<span style="white-space:pre"> </span> int count=fps*3;
<span style="white-space:pre"> </span> while(count > 0 ){ //每3秒取一帧
<span style="white-space:pre"> </span> frame = opencv_highgui.cvQueryFrame(capture);
<span style="white-space:pre"> </span> count--;
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span> if (null == frame)
<span style="white-space:pre"> </span> break;
<span style="white-space:pre"> </span> } <span style="white-space:pre"> </span>
为了得到灰度值但javacv的文档又太少,则看了下opencv的源码,自己实现下gray值的提取,其实很简单:
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
final int color = image.getRGB(i, j);
final int r = (color >> 16) & 0xff;
final int g = (color >> 8) & 0xff;
final int b = color & 0xff;
int gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);;
要把图片灰度值统计成直方图,也就是放到数组统计即可,以上就是整个思路讲解。
最后,附上整体的代码如下:
public class Test{
public static void main(String[] args) {
// System.out.println(System.getProperty("java.library.path"));
Real t = new Real();
t.run();
}
public void run() { //视频转化为帧、秒
CvCapture capture = opencv_highgui.cvCreateFileCapture("C:/Users/hp03/Desktop/www.ygdy8.com.rmvb");
System.out.println("读取视频成功!!!!!");
//每秒帧率
int fps = (int) opencv_highgui.cvGetCaptureProperty(capture, opencv_highgui.CV_CAP_PROP_FPS);
System.out.println("帧率:"+fps+"没三秒取一帧");
IplImage frame = null;
int count = 0;
while (true) { //读取关键帧
frame = opencv_highgui.cvQueryFrame(capture);
//得到灰度值
getGray(frame.getBufferedImage());
count=fps*3;
while(count > 0 ){ //每3秒取一帧
frame = opencv_highgui.cvQueryFrame(capture);
count--;
}
if (null == frame)
break;
}
}
public void getGray(BufferedImage image){
int[] Hist = new int[256];
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
final int color = image.getRGB(i, j);
final int r = (color >> 16) & 0xff;
final int g = (color >> 8) & 0xff;
final int b = color & 0xff;
int gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);;
//System.out.println(i + " : " + j + " " + gray);
// histogram(Hist,gray);
Hist[gray]++;
}
}
System.out.print("[");
for (int i = 0; i < Hist.length; i++) {
System.out.print(Hist[i]+" ");
}
System.out.println("]");
System.out.println("");
}