Java使用OpenCV3.2實現(xiàn)視頻讀取與播放
Java使用OpenCV3.2實現(xiàn)視頻讀取與播放,供大家參考,具體內(nèi)容如下
OpenCV從3.x版本開始其JAVA語言的SDK支持視頻文件讀寫,這樣就極大的方便了廣大Java語言開發(fā)者學(xué)習(xí)與使用OpenCV,通過攝像頭或者視頻文件讀取幀的內(nèi)容與播放,完成視頻內(nèi)容分析與對象跟蹤等各種應(yīng)用開發(fā)任務(wù)??梢哉fOpenCV C++ SDK可以做到絕大多數(shù)事情,在OpenCV3.x版本上用Java都可以完成,這樣就為很多Java開發(fā)者學(xué)習(xí)OpenCV打開了方便之門。
實現(xiàn)思路
首先用OpenCV相關(guān)API讀取視頻流或者視頻文件的每一幀,然后通過Swing JComponent組件實現(xiàn)視頻每一幀的更新顯示,我模仿了C++的HIGHGUI里面創(chuàng)建窗口與顯示圖像接口,基于Swing實現(xiàn)了一個視頻播放窗口類,把讀取到的每一幀都傳給它就可以實現(xiàn)連續(xù)顯示即播放。每幀之間相隔100毫秒,我是通過Java線程Sleep方法實現(xiàn)。
運行效果 - USB攝像頭讀取每幀

運行效果 - 視頻文件讀取每幀

代碼實現(xiàn)
視頻文件讀取
package com.gloomyfish.video.demo;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.videoio.VideoCapture;
public class VideoDemo {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 打開攝像頭或者視頻文件
VideoCapture capture = new VideoCapture();
//capture.open(0);
capture.open("D:/vcprojects/images/768x576.avi");
if(!capture.isOpened()) {
System.out.println("could not load video data...");
return;
}
int frame_width = (int)capture.get(3);
int frame_height = (int)capture.get(4);
ImageGUI gui = new ImageGUI();
gui.createWin("OpenCV + Java視頻讀與播放演示", new Dimension(frame_width, frame_height));
Mat frame = new Mat();
while(true) {
boolean have = capture.read(frame);
Core.flip(frame, frame, 1);// Win上攝像頭
if(!have) break;
if(!frame.empty()) {
gui.imshow(conver2Image(frame));
gui.repaint();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static BufferedImage conver2Image(Mat mat) {
int width = mat.cols();
int height = mat.rows();
int dims = mat.channels();
int[] pixels = new int[width*height];
byte[] rgbdata = new byte[width*height*dims];
mat.get(0, 0, rgbdata);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
int index = 0;
int r=0, g=0, b=0;
for(int row=0; row<height; row++) {
for(int col=0; col<width; col++) {
if(dims == 3) {
index = row*width*dims + col*dims;
b = rgbdata[index]&0xff;
g = rgbdata[index+1]&0xff;
r = rgbdata[index+2]&0xff;
pixels[row*width+col] = ((255&0xff)<<24) | ((r&0xff)<<16) | ((g&0xff)<<8) | b&0xff;
}
if(dims == 1) {
index = row*width + col;
b = rgbdata[index]&0xff;
pixels[row*width+col] = ((255&0xff)<<24) | ((b&0xff)<<16) | ((b&0xff)<<8) | b&0xff;
}
}
}
setRGB( image, 0, 0, width, height, pixels);
return image;
}
/**
* A convenience method for setting ARGB pixels in an image. This tries to avoid the performance
* penalty of BufferedImage.setRGB unmanaging the image.
*/
public static void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
int type = image.getType();
if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
image.getRaster().setDataElements( x, y, width, height, pixels );
else
image.setRGB( x, y, width, height, pixels, 0, width );
}
}
視頻與圖像顯示窗口類
package com.gloomyfish.video.demo;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JComponent;
import javax.swing.JDialog;
public class ImageGUI extends JComponent {
/**
*
*/
private static final long serialVersionUID = 1L;
private BufferedImage image;
public ImageGUI() {
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
if(image == null) {
g2d.setPaint(Color.BLACK);
g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
} else {
g2d.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), null);
System.out.println("show frame...");
}
}
public void createWin(String title) {
JDialog ui = new JDialog();
ui.setTitle(title);
ui.getContentPane().setLayout(new BorderLayout());
ui.getContentPane().add(this, BorderLayout.CENTER);
ui.setSize(new Dimension(330, 240));
ui.setVisible(true);
}
public void createWin(String title, Dimension size) {
JDialog ui = new JDialog();
ui.setTitle(title);
ui.getContentPane().setLayout(new BorderLayout());
ui.getContentPane().add(this, BorderLayout.CENTER);
ui.setSize(size);
ui.setVisible(true);
}
public void imshow(BufferedImage image) {
this.image = image;
this.repaint();
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于Java如何正確地實現(xiàn)方法重載詳解
在一個類中,可以定義多個構(gòu)造方法,這叫做方法的重載!但是關(guān)于方法重載,具有有哪些要求和細(xì)節(jié)?在今天的這篇文章中,小編給大家詳細(xì)說說方法重載相關(guān)的內(nèi)容,需要的朋友可以參考下2023-05-05
使用feign服務(wù)調(diào)用添加Header參數(shù)
這篇文章主要介紹了使用feign服務(wù)調(diào)用添加Header參數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06

