1.读取图片属性
1 2 3 4 5 6 7 8 9 10 11 |
String path = new File("src/bg.jpg").getAbsolutePath(); Mat mat = org.opencv.imgcodecs.Imgcodecs.imread(path); System.out.println("图片颜色通道数:" + mat.channels()); System.out.println("图片色深:" + mat.depth()); // CV_8U=0,CV_8S=1,CV_16U=2,CV_16S=3,CV_32S=4,CV_32F=5,CV_64F=6 System.out.println("图片宽:" + mat.rows()); System.out.println("图片高:" + mat.cols()); System.out.println("图片size:" + mat.size()); System.out.println("图片总像素:" + mat.total()); System.out.println("图片像素:\n" + mat.dump()); |
1 2 3 4 5 6 7 |
ArrayList<Mat> channels = new ArrayList<Mat>(); Core.split(mat, channels); System.out.println("\nBlue蓝色通道矩阵:\n" + channels.get(0).dump()); System.out.println("绿色通道矩阵Green:\n" + channels.get(1).dump()); System.out.println("红色通道矩阵Red:\n" + channels.get(2).dump()); |
2.在swing中展示图片
Swing是一个用于开发Java应用程序用户界面的开发工具包,是由纯Java实现的。
1)Imgcodecs
Imgcodecs类位于org.opencv.imgcodecs包下,java版opencv中只有这一个图片编码类。其中最常用的是imread、imwrite 2个方法。
1 2 3 4 5 6 7 8 9 |
String path = new File("src/img.jpg").getAbsolutePath(); Mat mat = Imgcodecs.imread(path); // 加载图片文件为Mat数据 // tmp 目标图片文件 // source Mat原数据 // rate 参数 Imgcodecs.imwrite(tmp, source, rate); // 将Mat数据写入图片文件 |
2)图片显示窗体示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
import java.awt.FlowLayout; import java.awt.image.BufferedImage; import java.io.File; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JSlider; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.opencv.core.Mat; import org.opencv.core.MatOfInt; import org.opencv.imgcodecs.Imgcodecs; /** * 加载OpenCV的Mat展示图片 * @author www.gaohaiyan.com */ public class OpenCVFrame extends JFrame { /** 手动选择的质量滑块 */ JSlider qualityBar; /** 图片显示容器 */ JLabel label; /** 原始图片数据 */ private Mat source; /** 根据目标质量创建的临时图片 */ String tmp; /** * 创建窗体 * @param mat 图片的mat数据体 */ public OpenCVFrame(Mat mat) { this.source = mat; this.tmp = new File("src/tmp.jpg").getAbsolutePath(); BufferedImage img = mat2Img(mat); int width = img.getWidth(); int height = img.getHeight(); label = new JLabel(); label.setBounds(0, 0, width, height); // 相对容器 int x, int y, int width, int height label.setIcon(new ImageIcon(img)); int w = 300; w = width > w ? width : w; int h = 300; h = height > h ? height : h; getContentPane().add(label); setTitle("加载图片"); setBounds(300, 300, w + 100, h + 100); // 相对屏幕 int x, int y, int width, int height setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new FlowLayout(FlowLayout.CENTER)); qualityBar = new javax.swing.JSlider(0, 100); qualityBar.setPaintTicks(true); qualityBar.setSnapToTicks(true); qualityBar.setValue(100); qualityBar.setVisible(false); qualityBar.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { updateImg(); } }); add(qualityBar); } public void setQualityBarVisible(boolean b) { qualityBar.setVisible(b); } private void updateImg() { int quality = qualityBar.getValue(); // 取值0-100 MatOfInt rate = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, quality); Imgcodecs.imwrite(tmp, source, rate); // 将Mat数据写入jpg图片文件 //MatOfInt rpng = new MatOfInt(Imgcodecs.IMWRITE_PNG_COMPRESSION, quality / 10 - 1); // 取值0-9 //Imgcodecs.imwrite(tmp, source, rpng); // 将Mat图片写入png文件 Mat mat = Imgcodecs.imread(tmp); BufferedImage img = mat2Img(mat); label.setIcon(new ImageIcon(img)); } /** * 将opencv的Mat数据转为swing使用的Buff图像 * @param mat 原始图像mat数据 * @return swing使用图像数据 */ private BufferedImage mat2Img(Mat mat) { int rows = mat.rows(); // 行 int cols = mat.cols(); // 列 int elemSize = (int) mat.elemSize(); // 每个元素大小,单位字节 byte[] data = new byte[cols * rows * elemSize]; // 目标图像数据 int type = BufferedImage.TYPE_BYTE_GRAY; mat.get(0, 0, data); // 将mat数据放入数组 if (3 == mat.channels()) { double[] ds = mat.get(0, 0); if (ds[0] != ds[1] || ds[1] != ds[2]) { // 有些灰度图是BGR相同,非单通道图 type = BufferedImage.TYPE_3BYTE_BGR; byte b; for (int i = 0; i < data.length; i = i + 3) { // BGR 2 RGB。交换红蓝通道 b = data[i]; data[i] = data[i + 2]; data[i + 2] = b; } } } BufferedImage img = new BufferedImage(cols, rows, type); // 宽高,图像类型 img.getRaster().setDataElements(0, 0, cols, rows, data); // 加载图像数据 return img; } } |
3)加载图片显示,刷新图片品质
1 2 3 4 5 6 7 8 |
String path = new File("src/img.jpg").getAbsolutePath(); Mat mat = Imgcodecs.imread(path); // 加载图片文件为Mat数据 OpenCVFrame window = new OpenCVFrame(mat); window.setQualityBarVisible(true); window.setVisible(true); |
3.读取摄像头
java版OpenCV内置了摄像头控制类VideoCapture。
1)动态监视
这里先升级一下上面的OpenCVFrame类,添加一个updateMat方法。方法接收一个Mat,然后调用mat2Img方法将之转为Buff图像,并最终显示在窗体上。
1 2 3 4 5 6 |
public void updateMat(Mat mat) { BufferedImage img = mat2Img(mat); label.setIcon(new ImageIcon(img)); } |
然后,为其定义一个boolean类型的全局变量isClosed;并添加一个窗体关闭事件。
1 2 3 4 5 6 7 8 9 |
addWindowListener(new WindowAdapter(){ @Override public void windowClosing(WindowEvent e) { isClosed = true; super.windowClosing(e); } }); |
下面是调用摄像头代码,读取影像展示在窗体。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
VideoCapture camera = new VideoCapture(); boolean open = camera.open(0); // 第一个摄像头(可能是唯一的) if(open){ Mat mat = new Mat(); try{ camera.read(mat); // 读取画面到mat中 OpenCVFrame frame = new OpenCVFrame(mat); frame.setVisible(true); while(true){ if(frame.isClosed){ break; } camera.read(mat); frame.updateMat(mat); // 即时刷新,动态展示 } } catch(Exception e){ e.printStackTrace(); } } camera.release(); // 释放资源,进程结束 |
2)录像
从v3.1开始内置的视频保存类VideoWriter。视频文件的编码可以参考 http://www.fourcc.org/codecs.php 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
VideoCapture camera = new VideoCapture(); boolean open = camera.open(0); // 第一个摄像头(可能是唯一的) if(open){ Mat mat = new Mat(); try{ camera.read(mat); // 读取画面到mat中 OpenCVFrame frame = new OpenCVFrame(mat); frame.setVisible(true); VideoWriter writer = new VideoWriter(); writer.open( new File("src/tmp.avi").getAbsolutePath(), // 目标文件 VideoWriter.fourcc('M','J','P','G'), // 编码格式 24, // 帧频 new Size(mat.width(), mat.height())); // 视频宽高。OpenCV Error: Assertion failed (img.cols == width && img.rows == height && channels == 3) in cv::mjpeg::MotionJpegWriter::write while(true){ if(frame.isClosed){ break; } camera.read(mat); // 先 writer.write(mat); // 再 frame.updateMat(mat); } writer.release(); } catch(Exception e){ e.printStackTrace(); } } camera.release(); // 释放资源,进程结束 |
声明
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/2231.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设