我是靠谱客的博主 听话樱桃,最近开发中收集的这篇文章主要介绍树莓派java 控制摄像头_【树莓派】使用JavaCV1.5.2调用摄像头,自写的摄像头控件...,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

已更新JavaCV1.5.3版本:https://blog.csdn.net/ap114/article/details/105531743

做毕设要用到摄像头,可是树莓派上的摄像头就那么几种,jmf、webcam、javacv,前两个都老掉牙了,windows上还行,树莓派上各种不得劲,armhf平台还有奇奇怪怪的问题,javacv又特别庞大,真是太难选择了,为啥java用个摄像头就这么麻烦。各种爬坑在此做下笔记,本帖阐述了如何使用java在树莓派上使用opencv开发摄像头。

因为是开发树莓派桌面应用,所以开发swing我选择的IDE只有Netbeans用着最顺手。我的版本是8.2。

树莓派上的java版本是1.8.0_231,安装见https://blog.csdn.net/ap114/article/details/102757478

1.下载jar

7c17f207d2dddde6e235b33ced0c21ad.png

本项目使用的是javacv1.5.2,首先下载jar,github地址:https://github.com/bytedeco/javacv/releases或者见文末的项目打包链接,里面附带图中的jar

120298eefbb117b07b473375fe443060.png

为了方便在windows上调试,所以同时导入了windows平台包和armhf平台包。

2.导入jar

a7cddeb4b819fb072f970d3f5277799d.png

3.导入类

查阅多方资料特地写了一个摄像头面板类,本摄像头面板可以使用VideoCapture和OpenCVFrameGrabber两种方式读取摄像头

readType =0 就使用VideoCapture方式获取摄像头数据

readType =1 就使用OpenCVFrameGrabber方式获取摄像头数据

deviceNumber就是摄像头编号,默认为0,就是笔记本上的摄像头

deviceStr是摄像头字符串编号,例如/dev/video0

JPanel parent主要是获取父面板的宽高,用于设置画板宽高,绘制摄像头的数据

主要的功能如下

3d636cb728aee06b9788715c48910c0c.png

a32827f1c0c4f4350b0c5f1a4fc75281.png

CameraJPanel类就是一个摄像头的面板控件,随意发挥用途。

import java.awt.Canvas;

import java.awt.Color;

import java.awt.Image;

import java.awt.image.BufferedImage;

import javax.swing.SwingUtilities;

import javax.swing.JPanel;

import org.bytedeco.javacv.Frame;

import org.bytedeco.javacv.Java2DFrameConverter;

import org.bytedeco.opencv.global.opencv_imgcodecs;

import org.bytedeco.opencv.opencv_core.Mat;

import org.bytedeco.opencv.opencv_videoio.VideoCapture;

import org.bytedeco.javacv.OpenCVFrameConverter;

import org.bytedeco.javacv.FrameGrabber.Exception;

import org.bytedeco.javacv.OpenCVFrameGrabber;

/**

*树莓派摄像头面板组件

*原贴地址:https://blog.csdn.net/ap114/article/details/105250320

* @author 钟离彧

*/

public class CameraJPanel extends JPanel{

//摄像头打开关闭标志

private boolean open = false;

//摄像头暂停标志

private boolean pause = false;

//摄像头画板

private final Canvas canvas = new Canvas();

//当前帧是否绘制完成的锁,若不加锁会造成阻塞

private boolean isDrawfinish = false;

//通过OpenCVFrameGrabber方式过得每帧图像

private OpenCVFrameGrabber grabber;

//通过VideoCapture方式过得每帧图像

private VideoCapture capture;

//OpenCV_VideoCapture格式转换Java图像格式

private final Java2DFrameConverter java2dFrameConverter = new Java2DFrameConverter();

//OpenCV_OpenCVFrameGrabber格式转换Java图像格式

private static OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();

//当前每帧的图像

private BufferedImage bufferedImage = null;

//通过Opencv方式的摄像头获取到的帧

private Mat mat = new Mat();

//不停读取摄像头并刷新画板数据的后台线程

private Thread refreshCanvasThread;

//读取方式0=VideoCapture方式读摄像头,1=OpenCVFrameGrabber方式

private int readType = 0;

private int deviceNumber = 0;

private String deviceStr = "";

public CameraJPanel(JPanel parent,int deviceNumber){

this(parent);

this.deviceNumber = deviceNumber;

}

public CameraJPanel(JPanel parent){

this.setBounds(0, 0, parent.getWidth(), parent.getHeight());

initOpenCV();

}

public CameraJPanel(JPanel parent,int deviceNumber,int readType){

this(parent);

this.deviceNumber = deviceNumber;

if(readType!=0 && readType!=1)readType=0;

this.readType = readType;

initOpenCV();

}

//例如:/dev/video0

public CameraJPanel(JPanel parent,String deviceStr){

this(parent);

this.deviceStr = deviceStr;

}

public CameraJPanel(){

this.setBounds(0, 0, 640, 480);

initOpenCV();

}

public CameraJPanel(int width,int height){

this.setBounds(0, 0, width, height);

initOpenCV();

}

private void initOpenCV(){

canvas.setBounds(0, 0, this.getWidth(), this.getHeight());

this.add(canvas);

openCamera();

}

//打开摄像头

public void openCamera(){

this.pause = false;

this.open = true;

if("".equals(deviceStr)){

if(readType == 0){

capture = new VideoCapture(deviceNumber);

}else if(readType == 1){

grabber = new OpenCVFrameGrabber(deviceNumber);

try {

grabber.start(); //开始获取摄像头数据

} catch (Exception ex) {

System.out.println(ex.getMessage());

return;

}

}

}else{

if(readType == 0){

capture = new VideoCapture(deviceStr);

}else if(readType == 1){

grabber = new OpenCVFrameGrabber(deviceStr);

try {

grabber.start(); //开始获取摄像头数据

} catch (Exception ex) {

System.out.println(ex.getMessage());

return;

}

}

}

//设置刷新画板线程

refreshCanvasThread = new Thread(){

public void run() {

while(open){

while(pause)thread_sleep(1);//发现暂停锁,进入暂停

//画板绘图是否完成标志

isDrawfinish = false;

//跨线程更新UI

SwingUtilities.invokeLater(new Runnable() {

@Override

public void run() {

if(readType == 0){

getImageByVideoCapture();

}else{

getImageByOpenCVFrameGrabber();

}

isDrawfinish = true;

}

});

//上次的绘图没有完成就不允许继续读取摄像头

while(!isDrawfinish)thread_sleep(1);

}

}

};

refreshCanvasThread.start();

}

//暂停绘画,但不会停止摄像头

public void pauseCamera(){

this.pause = true;

}

//继续绘画

public void continueCamera(){

this.pause = false;

}

//关闭摄像头

public void closeCamera(){

this.pause = false;

this.open = false;

if(readType == 0){

capture.close();

}else if(readType == 1){

try {

grabber.stop();

grabber.close();

grabber.release();

} catch (Exception ex) {

System.out.println(ex.getMessage());

}

}

}

//清除画板

public void clearCanvas(Color c){

canvas.getGraphics().setColor(c);

canvas.getGraphics().fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

}

//清除画板

public void clearCanvas(){

canvas.getGraphics().clearRect(0, 0, canvas.getWidth(), canvas.getHeight());

}

//通过VideoCapture获取当前帧

public BufferedImage getImageByVideoCapture(){

boolean have = capture.read(mat);

bufferedImage = null;

if(have){

Frame convertFrame2 = converter.convert(mat);

bufferedImage= java2dFrameConverter.convert(convertFrame2);

Image newimage = bufferedImage.getScaledInstance(getWidth(), getHeight(), Image.SCALE_FAST);

canvas.getGraphics().drawImage(newimage, 0, 0,null);

}

return bufferedImage;

}

//通过OpenCVFrameGrabber获取当前帧

public BufferedImage getImageByOpenCVFrameGrabber(){

bufferedImage = null;

try {

if(this.open==false)return null;

Frame convertFrame2 = grabber.grabFrame();

bufferedImage= java2dFrameConverter.convert(convertFrame2);

Image newimage = bufferedImage.getScaledInstance(getWidth(), getHeight(), Image.SCALE_FAST);

canvas.getGraphics().drawImage(newimage, 0, 0,null);

} catch (Exception ex) {

System.out.println(ex.getMessage());

}

return bufferedImage;

}

//保存当前帧,默认class路径/时间戳.png

public String saveImage(){

String savepath= getClass().getResource("").getPath() + System.currentTimeMillis() + ".png";

//一个奇怪的BUG,通过上行代码获取当前运行路径会以/开头,例如"/C:/img/1.png"

if(savepath.charAt(0) == '/'){

savepath = savepath.substring(1, savepath.length());

}

return saveImage(savepath);

}

//保存当前帧

public String saveImage(String path) {

try {

boolean isSave = false;

if(readType==1)mat = converter.convertToMat(grabber.grabFrame());

isSave = opencv_imgcodecs.imwrite(path, mat);

if(isSave == false)path=""; //保存失败返回空

} catch (Exception ex) {

System.out.println(ex.getMessage());

}

System.out.println(path);

return path;

}

private void thread_sleep(int time){

try {

Thread.sleep(time);//time毫秒刷新一次图像

} catch (InterruptedException ex) {

System.out.println(ex.getMessage());

}

}

}

使用方法(伪代码)

JPanel jp1;//你自己的组件,可以随意拖动设计

private CameraJPanel camera;//摄像头控件

//构造函数

public NewJFrame() {

initComponents();

}

//初始化组件

private void initComponents() {

jp1 = new javax.swing.JPanel();

jp1.setBackground(new Color(0, 0, 0));//整个黑色背景高大上

camera = new CameraJPanel(jp1);

jp1.add(camera);

}

//保存图片

private void btn_saveOnclick(ActionEvent evt) {

System.out.println(camera.saveImage());

}

//暂停绘画,摄像头灯会亮着,不会关闭

private void btn_pauseOnclick(ActionEvent evt) {

camera.pauseCamera();

}

//继续绘画

private void btn_continueOnclick(ActionEvent evt) {

camera.continueCamera();

}

//关闭摄像头

private void btn_closeOnclick(ActionEvent evt) {

camera.closeCamera();

camera.clearCanvas(Color.BLACK);

}

//开启摄像头

private void btn_openOnclick(ActionEvent evt) {

camera.openCamera();

}

效果

42a2fa9a8819114196433b3286dcc4b7.png

Github地址:做完毕设就传上来

项目已打包送给各位伸手党,如果对您有用,您点个赞就行了,转载请注明出处。

Netbeans打包项目下载:https://download.csdn.net/download/ap114/12293162

项目中的控件未和博文控件同步,请以博文贴出的控件代码为准

最后

以上就是听话樱桃为你收集整理的树莓派java 控制摄像头_【树莓派】使用JavaCV1.5.2调用摄像头,自写的摄像头控件...的全部内容,希望文章能够帮你解决树莓派java 控制摄像头_【树莓派】使用JavaCV1.5.2调用摄像头,自写的摄像头控件...所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部