Click here to Skip to main content
15,885,216 members
Articles / Desktop Programming / MFC

Real-Time Object Tracker in C++

Rate me:
Please Sign up or sign in to vote.
4.93/5 (54 votes)
18 Dec 2007GPL37 min read 376.5K   26.3K   255  
This article describes an object tracking approach by estimating a time averaged background scene for tracking static and moving objects in real-time on down-scaled image data.

#ifndef ImageBlobs_h
#define ImageBlobs_h


struct Coord {
        int x;
        int y;
};

struct Element {
        vector<struct Element> neighbs;
        struct Coord coord;        
};

struct Blob {
        unsigned int elements_number;
        vector<struct Element> elements;
        unsigned int area;
        RECT bounding_box;      //[top,left; right,bottom)    
};


//class vec2D;
//class vec2Dc;
#include "vec2D.h"
#include "vec2Dc.h"



class ImageBlobs
{
public:
        ImageBlobs();
        //ImageBlobs(const ImageBlobs& blobs);
        ~ImageBlobs();

// Operators
        //const ImageBlobs& operator=(const ImageBlobs& blobs);

// Operations
        void init(unsigned int width, unsigned int height);
        int find_blobs(const vec2Dc& image, unsigned int min_elements_per_blob = 0);
        void find_bounding_boxes();
        void delete_blobs();

// Access
// Inquiry
        inline unsigned int get_blobs_number() const;
        inline const struct Blob* get_blob(unsigned int i) const;
        inline const vec2Dc* get_image() const;        

protected:
private:
        ImageBlobs(const ImageBlobs& blobs);
        const ImageBlobs& operator=(const ImageBlobs& blobs);
        

        vec2Dc* m_image;                        //image with blobs 1, 2, ... N after find_blobs()        
        vector<struct Blob> m_blobs;


        void remove_blob_from_image(const struct Blob& blob);
        void mark_blobs_on_image();

        //if element has new_element as neighbour
        inline bool has_neighbour(const struct Element& element, const struct Element& new_element) const; 
        inline int is_element_present(const struct Blob& blob, const struct Element& new_element) const;
        inline unsigned int add_up_neighbour(struct Blob& blob, unsigned int i);
        inline unsigned int add_right_neighbour(struct Blob& blob, unsigned int i);
        inline unsigned int add_down_neighbour(struct Blob& blob, unsigned int i);
        inline unsigned int add_left_neighbour(struct Blob& blob, unsigned int i);
                       
};

// Inlines
inline unsigned int ImageBlobs::get_blobs_number() const
{
        return (unsigned int)m_blobs.size();
}

inline const struct Blob* ImageBlobs::get_blob(unsigned int i) const
{
        return &m_blobs[i];
}

inline const vec2Dc* ImageBlobs::get_image() const
{
        return m_image;
}

inline int ImageBlobs::is_element_present(const struct Blob& blob, const struct Element& new_element) const
{
        //int index = 0;
        for(int i = (int)blob.elements_number - 1; i >= 0; i--) {        
                const struct Element& element = blob.elements[i];
                if (element.coord.x == new_element.coord.x &&
                    element.coord.y == new_element.coord.y) {
                            //wprintf(L" %d\n", blob.elements_number - 1 - i);
                            return i;
                }
                //if (++index > 2)  //inspect at least 2 last elements
                //        break;                
        }
        return -1;
}

inline bool ImageBlobs::has_neighbour(const struct Element& element, const struct Element& new_element) const
{
        unsigned int N = (unsigned int)element.neighbs.size();
        if (N > 0) {
                for (unsigned int i = 0; i < N; i++) {
                        if (element.neighbs[i].coord.x == new_element.coord.x &&
                            element.neighbs[i].coord.y == new_element.coord.y) 
                            return true;                        
                }
                return false;
        }
        else
                return false;
}

inline unsigned int ImageBlobs::add_up_neighbour(struct Blob& blob, unsigned int i)
{
        const struct Element& element = blob.elements[i];
        if (element.coord.y - 1 < 0)
                return 0;
        else if ((*m_image)(element.coord.y - 1, element.coord.x) > 0) {
                struct Element new_element;
                new_element.coord.x = element.coord.x;
                new_element.coord.y = element.coord.y - 1;                                
                if (has_neighbour(element, new_element) == false) { 
                        int index = is_element_present(blob, new_element);
                        if (index >= 0) {
                                blob.elements[index].neighbs.push_back(element);
                                return 0;
                        }                        
                        new_element.neighbs.push_back(element);
                        blob.elements_number++;
                        blob.elements.push_back(new_element);                        
                        return 1;
                }
                else
                        return 0;
        }
        else 
                return 0;
}

inline unsigned int ImageBlobs::add_right_neighbour(struct Blob& blob, unsigned int i)
{
        const struct Element& element = blob.elements[i];
        if (element.coord.x + 1 >= m_image->width())
                return 0;
        else if ((*m_image)(element.coord.y, element.coord.x + 1) > 0) {
                struct Element new_element;
                new_element.coord.x = element.coord.x + 1;
                new_element.coord.y = element.coord.y;                
                if (has_neighbour(element, new_element) == false) {
                        int index = is_element_present(blob, new_element);
                        if (index >= 0) {
                                blob.elements[index].neighbs.push_back(element);
                                return 0;
                        }                        
                        blob.elements_number++;
                        blob.elements.push_back(new_element);                        
                        return 1;
                }
                else
                        return 0;
        }
        else 
                return 0;
}

inline unsigned int ImageBlobs::add_down_neighbour(struct Blob& blob, unsigned int i)
{
        const struct Element& element = blob.elements[i];
        if (element.coord.y + 1 >= m_image->height())
                return 0;
        else if ((*m_image)(element.coord.y + 1, element.coord.x) > 0) {
                struct Element new_element;
                new_element.coord.x = element.coord.x;
                new_element.coord.y = element.coord.y + 1;                
                if (has_neighbour(element, new_element) == false) {
                        int index = is_element_present(blob, new_element);
                        if (index >= 0) {
                                blob.elements[index].neighbs.push_back(element);
                                return 0;
                        }                        
                        blob.elements_number++;
                        blob.elements.push_back(new_element);                        
                        return 1;
                }
                else
                        return 0;
        }
        else 
                return 0;
}

inline unsigned int ImageBlobs::add_left_neighbour(struct Blob& blob, unsigned int i)
{
        const struct Element& element = blob.elements[i];
        if (element.coord.x - 1 < 0)
                return 0;
        else if ((*m_image)(element.coord.y, element.coord.x - 1) > 0) {
                struct Element new_element;
                new_element.coord.x = element.coord.x - 1;
                new_element.coord.y = element.coord.y;                
                if (has_neighbour(element, new_element) == false) {
                        int index = is_element_present(blob, new_element);
                        if (index >= 0) {
                                blob.elements[index].neighbs.push_back(element);
                                return 0;
                        }                        
                        blob.elements_number++;
                        blob.elements.push_back(new_element);                        
                        return 1;
                }
                else
                        return 0;
        }
        else 
                return 0;
}

#endif ImageBlobs_h

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Engineer
Russian Federation Russian Federation
Highly skilled Engineer with 14 years of experience in academia, R&D and commercial product development supporting full software life-cycle from idea to implementation and further support. During my academic career I was able to succeed in MIT Computers in Cardiology 2006 international challenge, as a R&D and SW engineer gain CodeProject MVP, find algorithmic solutions to quickly resolve tough customer problems to pass product requirements in tight deadlines. My key areas of expertise involve Object-Oriented
Analysis and Design OOAD, OOP, machine learning, natural language processing, face recognition, computer vision and image processing, wavelet analysis, digital signal processing in cardiology.

Comments and Discussions