javacv windows下視訊提取幀再轉化為灰度直方圖
阿新 • • 發佈:2019-01-30
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秒所包含的幀率即可),程式碼如下:
為了得到灰度值但javacv的文件又太少,則看了下opencv的原始碼,自己實現下gray值的提取,其實很簡單: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>
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("");
}