java(一些java API)或C#(emgucv,dshownet,Aforge.NET)中的实时对象跟踪

时间:2010-05-26 09:12:27

标签: c# java real-time tracking emgucv

我正在做一个名为用户启动的实时对象跟踪系统项目。在这里,我想在项目中发生

1)从网络摄像头连续播放。

2)使用鼠标,用户可以围绕感兴趣的对象绘制一个正方形。

3)然后从那里开始,正方形与感兴趣的物体一起移动。因此,跟踪对象移动的每个位置,因此术语对象跟踪。


当前进度


我使用dshownet(DirectShow的.NET包装器)从网络摄像头获取输入。我正在将视频分割为帧。我有4种方法来完成这个项目:


技术1


  • 有一个已保存的视频
  • 我加载它。
  • 当视频正在运行时,我暂停(使用暂停按钮)它,在特定场景下,在对象上画一个正方形。
  • 当我按下播放按钮时,方块将与对象一起移动,没有/ 5秒处理时间[或者]我会给应用程序一些处理时间(例如3分钟),然后它将从该点开始播放跟踪发生。

技术2


  • 有一个已保存的视频
  • 我加载它。
  • 当视频正在运行时,我不会暂停它,但会快速在对象上绘制一个正方形(当对象仍在某个时刻时)。
  • 然后在没有处理时间的情况下跟踪对象。 [或]使用一些处理时间(10秒延迟)使文件播放更长时间。

技术3


  • 我从网络摄像头输入1分钟。
  • 将该视频保存到文件
  • 并执行方式1或方式2

技术4 - (显然这看起来很难更难


  • 持续从网络摄像头获取输入
  • 当物体没有任何移动时(例如当一个人坐在椅子上时),在物体周围画一个正方形,没有任何暂停。
  • 然后通过移动方块和对象来显示跟踪,没有处理时间[或] 2秒的轻微处理时间,使得延迟不明显。

要跟踪的对象: -


基本上我可以跟踪任何内容,因为我使用鼠标绘制

  • 我打算使用整个身体(但如果这很麻烦......下一个选项)
  • 我会尝试跟踪个人的面部(显然是用鼠标绘制区域)。

代码时间: 1个半月


进度:分裂时仍然出错。 (有人建议先开始拆分保存的视频,我现在正在尝试这样做)


我的问题


1)我可以在1个半月的时间范围内实施哪种技术(四个中)

2)要编码, java +某些 java框架对此有用,或 C#.net emgucv / AForge进行编码。 net / Dshownet [顺便说一下 java 中的知识 良好,而不是良好 C#的.NET ] ...


提前致谢

3 个答案:

答案 0 :(得分:2)

技术1,2,3您可以使用Java Media Framework和ImageJ库在Java中实现。对于技术4,在给定时间限制的情况下,最好用C ++或其他非解释性语言实现。

答案 1 :(得分:1)

This example基本上实现了您提到的技术4 。用户围绕要跟踪的图案或对象绘制矩形。在这种情况下,跟踪元素用于控制Pong Game中的桨。因此,用户可以使用物体在相机前玩游戏。

我认为它解决了问题的大部分内容。

<强>截图: enter image description here

源代码:

package video.trackingPong; 

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Container; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 

import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

import marvin.gui.MarvinImagePanel; 
import marvin.image.MarvinImage; 
import marvin.image.MarvinImageMask; 
import marvin.io.MarvinImageIO; 
import marvin.plugin.MarvinImagePlugin; 
import marvin.util.MarvinAttributes; 
import marvin.util.MarvinPluginLoader; 
import marvin.video.MarvinJavaCVAdapter; 
import marvin.video.MarvinVideoInterface; 
import marvin.video.MarvinVideoInterfaceException; 

public class TrackingPong extends JFrame implements Runnable{

    private final static int         BALL_INITIAL_PX=100; 
    private final static int         BALL_INITIAL_PY=100; 
    private final static int         BALL_INITIAL_SPEED=3; 

    private MarvinVideoInterface    videoInterface; 
    private MarvinImagePanel         videoPanel; 

    private Thread                     thread; 

    private MarvinImage             imageIn,  
                                    imageOut; 

    private JPanel                    panelSlider; 

    private JSlider                    sliderSensibility; 

    private JLabel                    labelSlider; 

    private int                        regionPx,
                                    regionPy, 
                                    regionWidth, 
                                    regionHeight; 

    private boolean                    regionSelected=false; 
    private int[]                    arrInitialRegion; 

    private int                        sensibility=30; 



    // Pong Game Attributes 
    private double                    ballPx=BALL_INITIAL_PX,
                                    ballPy=BALL_INITIAL_PY; 

    private int                        ballSide=15; 


    double                            ballIncX=5; 
    private double                    ballIncY=5;     

    private int                        imageWidth,
                                    imageHeight; 

    private Paddle                    paddlePlayer, 
                                    paddleComputer; 

    private int                        playerPoints=0, 
                                    computerPoints=0; 

    private MarvinImagePlugin         findColorPattern, 
                                    flip, 
                                    text; 

    private MarvinImage                imageBall, 
                                    imagePaddlePlayer, 
                                    imagePaddleComputer; 

    private MarvinAttributes        attributesOut; 

    public TrackingPong(){ 
        videoPanel = new MarvinImagePanel(); 

        try{ 
            // 1. Connect to the camera device. 
            videoInterface = new MarvinJavaCVAdapter(); 
            videoInterface.connect(0); 

            imageWidth = videoInterface.getImageWidth(); 
            imageHeight = videoInterface.getImageHeight(); 

            imageOut = new MarvinImage(imageWidth, imageHeight);

            // 2. Load Graphical Interface. 
            loadGUI(); 

            // 3. Load and set up Marvin plug-ins. 
            findColorPattern     = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.pattern.findColorPattern"); 
            flip                = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.transform.flip"); 
            text                = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.render.text"); 
            text.setAttribute("fontFile", MarvinImageIO.loadImage("./res/font.png")); 
            text.setAttribute("color", 0xFFFFFFFF); 

            // 3. Load game images 
            imageBall = MarvinImageIO.loadImage("./res/ball.png"); 
            imagePaddlePlayer = MarvinImageIO.loadImage("./res/paddleA.png"); 
            imagePaddleComputer = MarvinImageIO.loadImage("./res/paddleB.png"); 

            attributesOut = new MarvinAttributes(null);

            // Set up plater and computer paddle properties. 
            paddlePlayer = new Paddle(); 
            paddlePlayer.px=100; 
            paddlePlayer.py=420; 
            paddlePlayer.width=100; 
            paddlePlayer.height=30; 

            paddleComputer = new Paddle(); 
            paddleComputer.px=100; 
            paddleComputer.py=30; 
            paddleComputer.width=100; 
            paddleComputer.height=30; 

            thread = new Thread(this);
            thread.start(); 
        } 
        catch(MarvinVideoInterfaceException e){ 
            e.printStackTrace(); 
        } 
    } 

    private void loadGUI(){     
        setTitle("Video Sample - Tracking Pong"); 

        videoPanel.addMouseListener(new MouseHandler()); 

        sliderSensibility = new JSlider(JSlider.HORIZONTAL, 0, 60, 30);
        sliderSensibility.setMinorTickSpacing(2); 
        sliderSensibility.setPaintTicks(true); 
        sliderSensibility.addChangeListener(new SliderHandler());

        labelSlider = new JLabel("Sensibility"); 

        panelSlider = new JPanel(); 
        panelSlider.add(labelSlider); 
        panelSlider.add(sliderSensibility); 

        Container container = getContentPane(); 
        container.setLayout(new BorderLayout()); 
        container.add(videoPanel, BorderLayout.NORTH); 
        container.add(panelSlider, BorderLayout.SOUTH); 

        setSize(videoInterface.getImageWidth()+20,videoInterface.getImageHeight()+100); 
        setVisible(true); 
    } 

    public void run(){ 
        long time = System.currentTimeMillis(); 
        int ticks=0; 

        // The game loop. 
        try{ 
            while(true){ 

                ticks++; 
                if(System.currentTimeMillis() - time > 1000){ 
                    System.out.println("FPS: "+ticks+"       "); 
                    ticks=0; 
                    time = System.currentTimeMillis();                     
                } 

                // 1. Get the current video frame. 
                imageIn = videoInterface.getFrame(); 
                MarvinImage.copyColorArray(imageIn, imageOut); 

                // 2. Flip the frame horizontally so the player will see him on the screen like looking at the mirror. 
                flip.process(imageOut, imageOut); 

                if(regionSelected){ 

                    // 3. Find the player paddle position. 
                    findColorPattern.setAttribute("differenceColorRange", sensibility); 
                    findColorPattern.process(imageOut, imageOut, attributesOut, MarvinImageMask.NULL_MASK, false);
                    regionPx         = (Integer)attributesOut.get("regionPx"); 
                    regionPy         = (Integer)attributesOut.get("regionPy"); 
                    regionWidth     = (Integer)attributesOut.get("regionWidth"); 
                    regionHeight    = (Integer)attributesOut.get("regionHeight"); 

                    // 4. Invoke the game logic 
                    pongGame(); 

                    // 5. Draw the detected region 
                    imageOut.drawRect(regionPx, regionPy, regionWidth, regionHeight, Color.red); 

                    // 6. Draw the player and computer points. 
                    text.setAttribute("x", 105); 
                    text.setAttribute("y", 3); 
                    text.setAttribute("text", "PLAYER:"+playerPoints); 
                    text.process(imageOut, imageOut); 

                    text.setAttribute("x", 105); 
                    text.setAttribute("y", 460); 
                    text.setAttribute("text", "COMPUTER:"+computerPoints); 
                    text.process(imageOut, imageOut); 
                } 


                videoPanel.setImage(imageOut); 
            } 
        } 
        catch(MarvinVideoInterfaceException e){ 
            e.printStackTrace(); 
        } 
    } 

    private void pongGame(){ 
        // 1. Move the ball 
        ballIncX*=1.001; 
        ballIncY*=1.001; 
        ballPx+=ballIncX; 
        ballPy+=ballIncY; 

        // 2. Set the player paddle position to the the coordinates of the detected region. 
        paddlePlayer.px = regionPx+((regionWidth-paddlePlayer.width)/2); 

        // 3. Invoke simple computer AI 
        computerAI(); 

        // 4. Check object positions and collisions. 
        checkPaddlePosition(paddlePlayer); 
        checkPaddlePosition(paddleComputer); 
        collisionScreen(); 
        collisionTap(); 

        // 5. Draw the game elements. 
        imageOut.fillRect(horizontalMargin, 0, 5, imageHeight, Color.black);
        imageOut.fillRect(imageWidth-horizontalMargin, 0, 5, imageHeight, Color.black);

        combineImage(imagePaddlePlayer, paddlePlayer.px, paddlePlayer.py); 
        combineImage(imagePaddleComputer, paddleComputer.px, paddleComputer.py); 
        combineImage(imageBall,(int)ballPx, (int)ballPy); 
    } 

    private void checkPaddlePosition(Paddle a_paddle){ 
        if(a_paddle.px < horizontalMargin){ 
            a_paddle.px = horizontalMargin; 
        } 
        if(a_paddle.px+a_paddle.width > imageWidth-horizontalMargin){ 
            a_paddle.px = imageWidth-horizontalMargin-a_paddle.width; 
        }         
    } 

    private void computerAI(){ 
        if(ballPx < paddleComputer.px+(paddleComputer.width/2)-10){ 
            paddleComputer.px-=4; 
        } 
        if(ballPx > paddleComputer.px+(paddleComputer.width/2)+10){ 
            paddleComputer.px+=4; 
        } 
    } 

    private int horizontalMargin = 100;
    private void collisionScreen(){ 

        if(ballPx < horizontalMargin){ 
            ballPx = horizontalMargin; 
            ballIncX*=-1; 
        } 
        if(ballPx+ballSide >= imageWidth-horizontalMargin){
            ballPx=(imageWidth-horizontalMargin)-ballSide; 
            ballIncX*=-1; 
        } 
        if(ballPy < 0){ 
            playerPoints++; 
            ballPx = BALL_INITIAL_PX; 
            ballPy = BALL_INITIAL_PY; 
            ballIncY=BALL_INITIAL_SPEED; 
            ballIncX=BALL_INITIAL_SPEED; 
        } else if(ballPy+ballSide >= imageHeight){ 
            computerPoints++; 
            ballPx = BALL_INITIAL_PX; 
            ballPy = BALL_INITIAL_PY; 
            ballIncY=BALL_INITIAL_SPEED; 
            ballIncX=BALL_INITIAL_SPEED; 
        } 
    } 

    private void collisionTap(){ 
        if(ballCollisionTap(paddlePlayer)){ 
            ballIncY*=-1; 
            ballPy = paddlePlayer.py-ballSide; 
        } 
        if(ballCollisionTap(paddleComputer)){ 
            ballIncY*=-1; 
            ballPy = paddleComputer.py+paddleComputer.height; 
        } 
    } 

    private boolean ballCollisionTap(Paddle a_tap){ 
        if 
        ( 
            ( 
                ballPx >= a_tap.px && ballPx <= a_tap.px+a_tap.width || 
                ballPx <= a_tap.px && ballPx+ballSide >= a_tap.px 
            ) 
            && 
            ( 
                ballPy >= a_tap.py && ballPy <= a_tap.py+a_tap.height || 
                ballPy <= a_tap.py && ballPy+ballSide >= a_tap.py 
            ) 
        ) 
        { 
            return true; 
        } 
        return false; 
    } 

    private void combineImage(MarvinImage img, int x, int y){ 
        int rgb; 
        int width = img.getWidth(); 
        int height = img.getHeight(); 

        for(int iy=0; iy<height; iy++){ 
            for(int ix=0; ix<width; ix++){ 
                if 
                ( 
                    ix+x > 0 && ix+x < imageWidth &&
                    iy+y > 0 && iy+y < imageHeight
                ) 
                { 
                    rgb=img.getIntColor(ix, iy);                 
                    if(rgb != 0xFFFFFFFF){ 
                        imageOut.setIntColor(ix+x, iy+y, rgb); 
                    } 
                } 
            } 
        }         
    } 

    public static void main(String args[]){ 
        TrackingPong trackingPong = new TrackingPong(); 
        trackingPong.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 

    private class SliderHandler implements ChangeListener{
        public void stateChanged(ChangeEvent a_event){ 
            sensibility = (60-sliderSensibility.getValue());
        } 
    } 

    private class MouseHandler implements MouseListener{
        public void mouseEntered(MouseEvent a_event){} 
        public void mouseExited(MouseEvent a_event){} 
        public void mousePressed(MouseEvent a_event){} 
        public void mouseClicked(MouseEvent a_event){} 

        public void mouseReleased(MouseEvent event){ 
            if(!regionSelected){ 
                if(arrInitialRegion == null){ 
                    arrInitialRegion = new int[]{event.getX(), event.getY(),0,0}; 
                } 
                else{ 
                    arrInitialRegion[2] = event.getX()-arrInitialRegion[0]; 
                    arrInitialRegion[3] = event.getY()-arrInitialRegion[1]; 

                    findColorPattern.setAttribute("regionPx", arrInitialRegion[0]); 
                    findColorPattern.setAttribute("regionPy", arrInitialRegion[1]); 
                    findColorPattern.setAttribute("regionWidth", arrInitialRegion[2]); 
                    findColorPattern.setAttribute("regionHeight", arrInitialRegion[3]); 

                    regionSelected = true; 
                }     
            } 
        }         
    } 

    private class Paddle{ 
        public int px,py,width,height;
    } 
} 

答案 2 :(得分:0)

This article fully explains一种非常类似于您想要的算法,the accompanying source code is here。你可以see it in action in this video。当用户绘制一个方框时,您需要添加的部分是识别哪些对象(已经由算法找到),该方框就在周围,然后在整个帧中简单地跟随具有该ID的对象(算法相关)这些对象逐帧地知道它是整个视频中的同一个对象。

免责声明:我是作者;但我认为这非常有用,并且我自己也成功地使用了这个算法。)

在商业计算机视觉应用方面,OpenCVPoint Cloud Library aka PCL是您最好的朋友。像链接这样的文章解释了如何使用像OpenCV这样的工具来完成完整的堆栈运动跟踪。 (纯Java实现显示了它如何适用于各个像素。)