0


小浩浅谈利用Java做一个视频运动追踪识别

寒假期间,一起做了一款pc端的美颜相机,在交流会期间,看到有的同学做了一些非常牛的功能添加,心血来潮,想整个视频运动追踪识别,在这和大家分析一下算法思路

1、原理很简单,就是在视频中的物体,就可以通过得到前后两张图片提供的二维数组之差,当两者之前的差值超过一个数,前后相差过大的时候,我们通过画笔去把他画出来,就可以得到我们想要的结果。

2、之前第一步遇到的问题,就是如何得到第一张图的数据,并且去和第二张图进行对比,在这里的话,我的思路是用一个数组去存储通过摄像头获取到底第一张图片,并且通过BufferedImage来缓存图片,然后重新定义一个数组缓存第二张图片的数据,就可以进行处理后的数据啦

3、代码如下(菜单栏的一些功能代码尚未给出,这里仅仅给出运动追踪识别的代码)

a.窗体界面

public class CameraUI {
    public void draw(){
        JFrame jFrame=new JFrame();
        jFrame.setTitle("视频运动追踪识别");
        jFrame.setSize(800,900);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setLocationRelativeTo(null);
        BorderLayout borderLayout=new BorderLayout();
        jFrame.setLayout(borderLayout);
        JPanel cennter=new JPanel();
        cennter.setBackground(Color.cyan);
        jFrame.add(cennter,BorderLayout.CENTER);
        //菜单栏以及相关功能的实现
        //开始定义菜单,菜单栏以及相关按钮
        JMenuBar jMenuBar=new JMenuBar();
        jFrame.add(jMenuBar,BorderLayout.NORTH);
        //监听器的设置
        CameraMouse cameraMouse=new CameraMouse();
        //定义在菜单栏中的菜单选项
        String[]name1={"运动追踪","视频","图片","拍照","特殊滤镜","编辑","帮助"};
        //开辟一个menu数组来存储调用与添加
        JMenu[]menu=new JMenu[name1.length];
        for (int i=0;i< name1.length;i++) {
            JMenu jMenu = new JMenu(name1[i]);
            menu[i]=jMenu;
            jMenuBar.add(jMenu);
        }
        //子菜单中的菜单选项
        String[]name={"打开","关闭","退出"};
        for (int i=0;i<name.length;i++) {
            JMenuItem jMenuItem = new JMenuItem(name[i]);
            jMenuItem.addActionListener(cameraMouse);
            menu[0].add(jMenuItem);
        }
        //可视一定要在画笔前
        jFrame.setVisible(true);
        cameraMouse.graphicsmouse=cennter.getGraphics();
    }

    public static void main(String[] args) {
        CameraUI cameraUI=new CameraUI();
        cameraUI.draw();
    }
}

b.监听器以及线程控制

public class CameraMouse implements ActionListener {
    //获取点击按钮的名字
    public String name;
    //获取画笔
    public Graphics graphicsmouse;
    //创造线程的对象进行调用
    public CameraThread cameraThread;

    public void actionPerformed(ActionEvent e){
        String name=e.getActionCommand();
        System.out.println("正在点击的操作是:"+name);
        if ("打开".equals(name)){
            if (cameraThread==null){
                cameraThread=new CameraThread(graphicsmouse);
                //开始启动线程
                cameraThread.start();
            }
        }else if ("关闭".equals(name)){
            cameraThread.flag=false;
        }
    }
}

c.运动追踪方法实现以及相关线程代码

public class CameraThread extends Thread{
    //开关控制线程
    public boolean flag=true;
    //画笔初始化
    public Graphics graphicsthread;
    //方法构造传送画笔
    public CameraThread(Graphics graphicsthread){
        this.graphicsthread=graphicsthread;
    }
    //线程的书写和使用
    public void run(){
        //摄像头的调动
        Webcam webcam=Webcam.getDefault();
        webcam.open();
        System.out.println("启动线程.."+this.getName());
        //利用while循环来使用线程,线程只能运行一次,结束后的线程不能重新调用
        while (flag) {
            //获取摄像头拍到的数据
            BufferedImage bufferedImage1 = webcam.getImage();
            //用数组存储下来,获取第一张图片
            int[][]pixel1Arr=getImagePixel(bufferedImage1);
            //创建缓冲图片
            BufferedImage buffer=new BufferedImage(bufferedImage1.getWidth(),bufferedImage1.getHeight(),BufferedImage.TYPE_INT_BGR);
            //获取缓存区的画笔
            Graphics grabuffer=buffer.getGraphics();
            //获取摄像头拍到的数据,重新获取
            BufferedImage bufferedImage2 = webcam.getImage();
            //用数组存储下来,存储的目的就是与第一张已经缓存下来的图片做对比,
            int[][]pixel2Arr=getImagePixel(bufferedImage2);
            //遍历第二张图片的数组
            for (int i=0;i<pixel2Arr.length;i++){
                for (int j=0;j<pixel2Arr[0].length;j++){
                    //第二张图片的像素
                    int pixel2=pixel2Arr[i][j];
                    if ((null!=pixel2Arr)){
                        // 转成Color对象,设置给画笔,画出像素点
                        Color rc=new Color(pixel2);
                        Color pixel1=new Color(pixel1Arr[i][j]);
                        //前后相互比较,这里是取的G值做的差
                        int diff=Math.abs(rc.getGreen()- pixel1.getGreen());
                        if ((diff)>30) {
                            grabuffer.setColor(Color.white);
                            grabuffer.fillOval(i, j, 2, 2);
                        } else if (diff<30) {
                            grabuffer.setColor(Color.black);
                            grabuffer.fillOval(i, j, 2, 2);
                        }
                    }
                }
            }
            //把拍到的数据画出来
            graphicsthread.drawImage(buffer, 100, 100,600,600, null);
       
        }
        System.out.println("结束线程");
    }

    //数据存储
    public int[][] getImagePixel(BufferedImage buffImage) {
        int w = buffImage.getWidth();
        int h = buffImage.getHeight();
        int[][] pixelArr = new int[w][h];
        // 获取图片中的每一个像素值保存到二维数组中
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                int pixel = buffImage.getRGB(i, j);
                pixelArr[i][j] = pixel;
            }
        }
        return pixelArr;
    }
}

4.视频效果图不方便截图,感兴趣的小伙伴来call我


本文转载自: https://blog.csdn.net/weixin_64625868/article/details/123055751
版权归原作者 网友小浩 所有, 如有侵权,请联系我们删除。

“小浩浅谈利用Java做一个视频运动追踪识别”的评论:

还没有评论