Отслеживание объектов в реальном времени в Java (некоторые API Java) или C # (emgucv, dshownet, Aforge.NET) - PullRequest
6 голосов
/ 26 мая 2010

Я выполняю проект под названием , инициированный пользователем в режиме реального времени, система отслеживания объектов . Вот что я хочу, чтобы произошло в проекте :

1) Возьмите непрерывный поток с веб-камеры.

2) С помощью мыши пользователь может нарисовать квадрат вокруг объекта интереса.

3) Затем оттуда квадрат движется вместе с объектом интереса. Таким образом, отслеживание каждого и каждого места, где перемещается объект, отсюда и термин «отслеживание объекта».


Текущий прогресс


Я использовал dshownet (оболочку .NET для DirectShow) для получения информации с веб-камеры. И я нахожусь в процессе разделения видео на кадры. Я имею в виду 4 способа сделать проект:


Техника 1


  • есть сохраненное видео
  • Я загружаю его.
  • когда видео запущено, я приостанавливаю его (используя кнопку паузы) в определенной сцене и рисую квадрат на объекте.
  • И когда я нажимаю кнопку воспроизведения, квадрат будет двигаться вместе с объектом без времени обработки 5 секунд [ИЛИ] Я дам приложению некоторое время обработки (например, 3 минуты), а затем оно будет воспроизводиться с этого момента отслеживание происходит.

Техника 2


  • есть сохраненное видео
  • Я загружаю его.
  • когда видео запущено, я не приостанавливаю его, а быстро рисую квадрат на объекте (когда объект все еще находится в некоторой точке).
  • После этого объект будет отслеживаться без времени обработки. [ИЛИ] с некоторым временем обработки (задержка 10 секунд), заставляющим файл воспроизводиться немного дольше.

Техника 3


  • Я беру ввод с веб-камеры в течение 1 мин.
  • Сохранить это видео в файл
  • И выполнить Путь 1 или Путь 2

Техника 4 - (По-видимому, это кажется много сложнее )


  • Постоянно принимать данные с веб-камеры
  • Нарисуйте квадрат вокруг объекта без каких-либо пауз, когда объект не показывает движения (например, когда человек садится на стул)
  • А затем покажите трекинг, переместив квадрат вместе с объектом без времени обработки [ИЛИ] с небольшим временем обработки, равным 2 секундам, так что задержка не будет значительно заметна.

Объекты для отслеживания: -


В принципе, я могу отследить что угодно, так как я рисую с помощью мыши

  • Я планирую использовать все тело (но если это хлопотно ... следующий вариант)
  • Я бы попытался отследить лицо человека (очевидно, нарисовав область мышью).

Время кодирования: 1 и 1/2 месяца


Прогресс: По-прежнему возникают ошибки при разбиении. (Кто-то предложил сначала разбить сохраненное видео, и сейчас я пытаюсь это сделать)


МОИ ВОПРОСЫ


1) Какую технику (из четырех) я мог бы реализовать за 1 и 1/2 месяца?

2) Для кодирования это Java + некоторые Java Framework хорошо для этого или C # .net с emgucv / AForge.net / Dshownet [кстати мои знания в java - хорошо и не очень хорошо в C # .net ] ??


Заранее спасибо

Ответы [ 3 ]

2 голосов
/ 26 мая 2010

Техника 1,2,3 вы можете реализовать на Java, используя Java Media Framework и библиотеки ImageJ. Для Техники 4 вам лучше реализовать на C ++ или другом неинтерпретированном языке, учитывая временные ограничения.

1 голос
/ 24 ноября 2016

Этот пример в основном реализует то, что вы упомянули как Техника 4 . Пользователь рисует прямоугольник вокруг шаблона или объекта, который нужно отслеживать. В этом случае отслеживаемый элемент используется для управления веслом в игре понг. Поэтому пользователь может использовать объекты, чтобы играть в игру перед камерой.

Я думаю, что это решает большую часть вашей проблемы.

Скриншот: 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;
    } 
} 
0 голосов
/ 20 февраля 2016

Эта статья полностью объясняет алгоритм, очень похожий на то, что вы хотите, и сопровождающий исходный код находится здесь . Вы можете увидеть это в действии в этом видео . Часть, которую вам нужно было бы добавить, когда пользователь рисует прямоугольник, идентифицирует, какие объекты (уже найденные алгоритмом) вокруг него, а затем просто следует за объектом с этим int ID по всем кадрам (алгоритм коррелирует объекты покадрово, чтобы знать, что это один и тот же объект во всем видео).

Отказ от ответственности: я автор; но я думаю, что это очень полезно, и я сам успешно использовал алгоритм.)

Когда речь идет о коммерческих приложениях для компьютерного зрения, OpenCV и Библиотека облаков точек (PCL ) - ваши лучшие друзья. А в статьях, подобных ссылкам, объясняется, как использовать такие инструменты, как OpenCV, для полного отслеживания движения в стеке. (Чистая реализация Java показывает, как она работает вплоть до отдельных пикселей.)

...