博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于OpenCv和swing的图片/视频展示Java实现
阅读量:6224 次
发布时间:2019-06-21

本文共 6365 字,大约阅读时间需要 21 分钟。

基于OpenCv和swing实现图片/视频的展示

图片的展示

swing展示图片,多为操作BufferedImage,这里要关注的核心是将Mat转为BufferedImage。

代码如下:

public Image toBufferedImage(Mat matrix) {        int type = BufferedImage.TYPE_BYTE_GRAY;        if (matrix.channels() > 1) {            type = BufferedImage.TYPE_3BYTE_BGR;        }        int bufferSize = matrix.channels() * matrix.cols() * matrix.rows();        byte[] buffer = new byte[bufferSize];        matrix.get(0,0,buffer); // get all the pixels        BufferedImage image = new BufferedImage(matrix.cols(),matrix.rows(),type);        final byte[] targetPixels = ((DataBufferByte)image.getRaster().getDataBuffer()).getData();        System.arraycopy(buffer,0,targetPixels,0,buffer.length);        return image;    }

comment 1:OpenCV Mat --> BufferedImage AWT , 创建一个byte array用以保存mat 矩阵的像素信息。数组大小为通道数和图片宽/高之积。其中,Mat.get()将所有的元素导入byte数组。最终,图片的光栅信息通过 getDataBuffer()和getDate()组成接收数组,并通过System.arraycopy方法完成填充。实现最终的类型与数据的转移。

comment 2:图片/视频,最终展示的都为BufferedImage,并在JFrame中展示,这里可将toBufferedImage与swing组件配置以展示的部分抽取为类ImageReader。如下:

import org.opencv.core.Mat;import javax.swing.*;import java.awt.*;import java.awt.image.BufferedImage;import java.awt.image.DataBufferByte;/** * @Author: nya * @Description: 图片展示类 * @Date: Created in 10:55 2018/9/21 * @Modify by: */public class ImageViewer {    private JLabel imageView;    public void show(Mat image,String windowName) {        setSystemLookAndFeel();        JFrame frame = createJFrame(windowName);        Image loadedImage = toBufferedImage(image);        imageView.setIcon(new ImageIcon(loadedImage));        frame.pack();        frame.setLocationRelativeTo(null);        frame.setVisible(true);    }    private JFrame createJFrame(String windowName) {        JFrame frame = new JFrame(windowName);        imageView = new JLabel();        final JScrollPane imageScrollPane = new JScrollPane(imageView);        imageScrollPane.setPreferredSize(new Dimension(640,480));        frame.add(imageScrollPane,BorderLayout.CENTER);        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);        return frame;    }    private void setSystemLookAndFeel() {        try {            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());        } catch (ClassNotFoundException e) {            e.printStackTrace();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (UnsupportedLookAndFeelException e) {            e.printStackTrace();        }    }    public Image toBufferedImage(Mat matrix) {        int type = BufferedImage.TYPE_BYTE_GRAY;        if (matrix.channels() > 1) {            type = BufferedImage.TYPE_3BYTE_BGR;        }        int bufferSize = matrix.channels() * matrix.cols() * matrix.rows();        byte[] buffer = new byte[bufferSize];        matrix.get(0,0,buffer); // get all the pixels        BufferedImage image = new BufferedImage(matrix.cols(),matrix.rows(),type);        final byte[] targetPixels = ((DataBufferByte)image.getRaster().getDataBuffer()).getData();        System.arraycopy(buffer,0,targetPixels,0,buffer.length);        return image;    }}

image Mat operate code:

String path = "src/main/java/com/opencv/simpleopencvsample/sample/1.jpg";         Mat openFile = null;        try {
       // openFile just is path to mat openFile = openFile(path); Mat clone = openFile.clone(); System.out.println(openFile); Imgproc.resize(openFile,clone,new Size(640,480)); System.out.println(clone); ImageViewer imageViewer = new ImageViewer(); imageViewer.show(clone,"Loaded image"); } catch (Exception e) { e.printStackTrace(); } finally { // comment : never forget to release the matrix if (openFile != null ) { openFile.release(); } } System.out.println(openFile);

视频的展示

有了图片展示为蓝本,视频的操作关键在于VideoCapture类的使用,展示部分不过是捕获视频的每一帧转为Mat,基于swing循环顺序展示即可。获取mat推荐采用read(),此方法为grab()/retrieve()的结合体。

为适应视频处理的JFrame宽高,此处自定义设置,主要采用toBufferedImage方法。

VideoCapture -> Mat -> display code:

import org.opencv.core.Core;import org.opencv.core.Mat;import org.opencv.videoio.VideoCapture;import org.opencv.videoio.Videoio;import javax.swing.*;import java.awt.*;/** * @Author: nya * @Description: 视频捕获相关操作类VideoCapture使用 * @Date: Created in 13:50 2018/9/21 * @Modify by: */public class VideoCaptureSample {    static {        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);    }    private JFrame frame;    private JLabel imageLabel;    public static void main(String[] args) {        VideoCaptureSample sample = new VideoCaptureSample();        sample.initGUI();        sample.runMainLoop(args);    }    private void initGUI(){        frame = new JFrame("Camera Input Example");        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        frame.setSize(555,970);        imageLabel = new JLabel();        frame.add(imageLabel);        frame.setVisible(true);    }    private void runMainLoop(String[] args) {        ImageViewer viewer = new ImageViewer();        Mat webcamMatImage = new Mat();        Image tempImage;        VideoCapture capture = new VideoCapture("src/main/java/com/opencv/simpleopencvsample/sample/1.mp4");        capture.set(Videoio.CAP_PROP_FRAME_WIDTH,550);        capture.set(Videoio.CAP_PROP_FRAME_HEIGHT,960);        if (capture.isOpened()) {            while (true) {                capture.read(webcamMatImage);                if (!webcamMatImage.empty()) {                    tempImage = viewer.toBufferedImage(webcamMatImage);                    ImageIcon imageIcon = new ImageIcon(tempImage,"Captured video");                    imageLabel.setIcon(imageIcon);                    frame.pack();                } else {                    System.out.println(" --- Frame not captured -- Break !");                    break;                }            }        } else {            System.out.println("Couldn't open capture.");        }    }}

常见异常 VideoCapture-isOpened返回false

  实际测试中,存在视频路径正常,isOpened()一直返回false的问题。

  这是因为视频处理类VideoCapture位于opencv_videoio模块,使用该类时需在运行时加载预先构建的opencv_ffmpeg * .dll / so。该模块如果加载成功,ffmpeg可用于解码/编码视频;否则,使用其它API。在排除路径问题后,仍然无法读取视频则多为此情况。

  解决方法很简单,将动态库dll/so导入 管理员/root 权限下配置的java.library.path路径下即可。

转载于:https://www.cnblogs.com/nyatom/p/9686794.html

你可能感兴趣的文章
《触摸屏游戏设计》——导读
查看>>
《OpenGL超级宝典(第5版)》——第1章,第1.2节3D图形技术和术语
查看>>
如何让你的机器学习玩超级玛丽
查看>>
阿里NASA计划“亮剑”:谢崇进和他追求的科学极限
查看>>
docker 基本命令 (CentOs7 Docker 17.03.1-ce)
查看>>
Apache Spark源码走读(八)Graphx实现剖析&spark repl实现详解
查看>>
PostgreSQL 10.0 preview sharding增强 - 支持分布式事务
查看>>
DDD领域驱动设计 - 设计文档模板
查看>>
架构师速成7.3-devops为什么很重要
查看>>
数据库事务
查看>>
使用API网关建立多场景测试环境
查看>>
妹子们选择程序媛作为职业是一种怎样的体验?
查看>>
PgSQL · 源码分析 · PG优化器物理查询优化
查看>>
玩转云镜像制作之packer篇
查看>>
程序员面试金典算法题
查看>>
[sharepoint]Rest api相关知识(转)
查看>>
Cocos2d-x3.2单点触摸
查看>>
MongoDB-3.2 oplog删除策略优化
查看>>
从Linux移植到FreeBSD
查看>>
Android应用生死轮回的那些事儿(2) - PackageManager
查看>>