【树莓派】使用JavaCV1.5.3调用摄像头,自写的摄像头控件

才写完1.5.2没多久,昨天,bytedeco发布了JavaCV1.5.3。再跟一把风。再升级下控件。

其实1.5.3也没升太多,就是更新到OpenCV 4.3.0,没涉及到和摄像头方面的东西,只用摄像头1.5.2都够用了。

因为1.5.2修复了两个摄像头相关的事情。传送门:https://github.com/bytedeco/javacv/releases

  • Fix OpenCVFrameConverter error in IPCameraFrameGrabber (pull #1278)
  • Allow setting properties for OpenCVFrameGrabber and OpenCVFrameRecorder with setOption() (issue #1269)

包括下载、使用等、JAVACV1.5.2版本看传送门https://blog.csdn.net/ap114/article/details/105250320,在此不过多赘述。

我的树莓派是3B+ Buster。其他版本pi没试过,理论上同一个系统不会有太大偏差。

我使用的摄像头是USB摄像头,淘宝20块那种,咸鱼10多块也可以捡捡漏,usb摄像头吃cpu。

csi摄像头没试过,对帧率和分辨率有需求的话,用csi摄像头最好。

如果csi摄像头不行烦请在此留言。


这次把1.5.3的各个平台给分开了,每个平台一个文件夹,方便OpenCV小白快速找到自己想要的东西。

项目打包至末尾链接,如发现项目代码和本文代码不同,请以本文为准。

1.5.3分类各平台打包下载:链接:https://pan.baidu.com/s/13dmmxWPABY3w_BuuUPvGfQ 提取码:zgzf 

一、首先导入公共平台,然后再导入armhf平台和windows平台。

Netbeans 8.5导入
Netbeans 8.2 项目导入

二、导入摄像头面板控件

package rpi_javacv_camera;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
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;
/**
 *树莓派摄像头OpenCV1.5.3面板组件
 *原贴地址:https://blog.csdn.net/ap114/article/details/105531743
 * @author 钟离彧
 */
public class CameraJPanel extends JPanel{
    //摄像头打开关闭标志
    public 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 = "";
    JLabel lb_img = new JLabel();
    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());
        lb_img.setBounds(0, 0, this.getWidth(), this.getHeight());
        lb_img.setVisible(false);
        this.add(canvas);
    }
    //打开摄像头
    public void openCamera(){
        this.remove(lb_img);
        if(open)return;
        this.pause = false;
        this.open = true;
        canvas.setVisible(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(() -> {
                        if(open && readType == 0){
                            getImageByVideoCapture();
                        }else{
                            getImageByOpenCVFrameGrabber();
                        }
                        isDrawfinish = true;
                    });
                    //上次的绘图没有完成就不允许继续读取摄像头
                    while(!isDrawfinish)thread_sleep(1);
                }
            }
        };
        refreshCanvasThread.start();
    }
    //暂停绘画,但不会停止摄像头
    public void pauseCamera(){
        this.remove(lb_img);
        this.pause = true;
    }
    //继续绘画
    public void continueCamera(){
        this.remove(lb_img);
        this.pause = false;
        canvas.setVisible(true);
    }
    //关闭摄像头
    public void closeCamera(){
        if(!open)return;
        //this.remove(canvas);
        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){
        this.remove(lb_img);
        canvas.getGraphics().setColor(c);
        canvas.getGraphics().fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
    }
    //清除画板
    public void clearCanvas(){
        this.remove(lb_img);
        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;
    }
    //保存当前帧,默认路径/img/时间戳.png
    public String saveImage(){
        if(!open)return "";
        String currenttime = System.currentTimeMillis() + ".png";
        String savepath = getImgPath() + currenttime;
        //一个奇怪的BUG,通过上行代码获取当前运行路径会以/开头,例如"/C:/img/1.png"
        if(savepath.charAt(0) == '/'){
            savepath = savepath.substring(1, savepath.length());
        }
        saveImage(savepath);
        return currenttime;
    }
    //保存当前帧
    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;
    }
    //重新设置图片
    public void setImage(String imgname){
        pauseCamera();
        this.add(lb_img);
        String savepath = imgname;
        Image image = new ImageIcon(savepath).getImage();
        image = image.getScaledInstance(getWidth(), getHeight(), Image.SCALE_FAST);
        lb_img.setIcon(new ImageIcon(image));
        lb_img.setVisible(true);
        canvas.setVisible(false);
    }
    //工具方法,线程延迟
    private void thread_sleep(int time){
        try {
            Thread.sleep(time);//time毫秒刷新一次图像
        } catch (InterruptedException ex) {
           System.out.println(ex.getMessage());
        }
    }
    //工具方法,获取当前运行路径
    public static String getRunPath(){
        String path = "";
        File directory = new File("");//设定为当前文件夹 
        try{ 
           // System.out.println(directory.getCanonicalPath());//获取标准的路径 
           // System.out.println(directory.getAbsolutePath());//获取绝对路径 
            path = directory.getAbsolutePath();
        }catch(java.lang.Exception e){} 
        return path;
    }
    //工具方法,获取当前图片路径
    public static String getImgPath(){
        String path = "";
        path+=getRunPath()+"\\img\\";
        return path;
    }
}

三、效果图

Netbeans 8.2 项目打包:https://download.csdn.net/download/ap114/12329651

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章