Java使用OpenCV3.2實(shí)現(xiàn)視頻讀取與播放
Java使用OpenCV3.2實(shí)現(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打開了方便之門。
實(shí)現(xiàn)思路
首先用OpenCV相關(guān)API讀取視頻流或者視頻文件的每一幀,然后通過Swing JComponent組件實(shí)現(xiàn)視頻每一幀的更新顯示,我模仿了C++的HIGHGUI里面創(chuàng)建窗口與顯示圖像接口,基于Swing實(shí)現(xiàn)了一個(gè)視頻播放窗口類,把讀取到的每一幀都傳給它就可以實(shí)現(xiàn)連續(xù)顯示即播放。每幀之間相隔100毫秒,我是通過Java線程Sleep方法實(shí)現(xiàn)。
運(yùn)行效果 - USB攝像頭讀取每幀
運(yùn)行效果 - 視頻文件讀取每幀
代碼實(shí)現(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如何正確地實(shí)現(xiàn)方法重載詳解
在一個(gè)類中,可以定義多個(gè)構(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ù)的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06win10下定時(shí)運(yùn)行與開機(jī)自啟動(dòng)jar包的方法記錄
這篇文章主要給大家介紹了關(guān)于win10下定時(shí)運(yùn)行與開機(jī)自啟動(dòng)jar包的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11搭建一個(gè)基礎(chǔ)的Resty項(xiàng)目框架
這篇文章主要為大家介紹了如何搭建一個(gè)基礎(chǔ)的Resty項(xiàng)目框架示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03