Click here to Skip to main content
15,895,142 members

problem in c++ programing 2

ssssdaaads asked:

Open original thread
Hi again
I am working on a image processing project.I can understand matlab program but i have some problem with C++.
I found a C++ program for foreground detection.But i don't understand some of instruction in it.for example:
C++
bgModel[index].mode[m].r[i] = curTextureHist[index].r[i];

whats mean of .mode[m].
and is it writting for one frame?
i don't see the instruction for increasing framenum.
at this code:
C++
unsigned int frameNum = 0;
axisCam->GetImage(image.Ptr(), frameNum);
LBP(image, texture);
Histogram(texture, curTextureHist);
for(int y = REGION_R+TEXTURE_R; y < height-REGION_R-TEXTURE_R; ++y)
{
    for(int x = REGION_R+TEXTURE_R; x < width-REGION_R-TEXTURE_R; ++x)
    {
        int index = x+y*width;

        for(int m = 0; m < NUM_MODES; ++m)
        {
            for(int i = 0; i < NUM_BINS; ++i)
            {
                bgModel[index].mode[m].r[i] = curTextureHist[index].r[i];
                bgModel[index].mode[m].g[i] = curTextureHist[index].g[i];
                bgModel[index].mode[m].b[i] = curTextureHist[index].b[i];
            }
        }
    }
}


and this is the program.
C++
///////////////////////////////////////////////////////////////////////////////
// Texture-based background subtraction based on the paper:
//
// "A texture-based method for modeling the background and
//  detecting moving objects"
// 		by M. Heikkila and M. Pietikainen (2005)
//
// The method has been extended to work with colour images. Strict conditional
// updating is used. Only a single mode is maintained for each pixel.
//
// 
//
// Hit "ESC" to exit the program. You must set AXIS_IP_ADDR to the IP 
// address of your Axis 206 camera.
//
// By Donovan Parks (donovan.parks@gmail.com)
//    January, 2008
//
///////////////////////////////////////////////////////////////////////////////

#include "AxisCamera.h"

#include <fstream>
#include <assert.h>
#include <iostream>

#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <pthread.h>

#include "memJpegDecoder.h"
#include "ConnectedComponents.h"


using namespace std;

// IP address of Axis 206 camera
#define AXIS_IP_ADDR "192.168.2.5"

// Global variable that should be set to true in order to cleanly exit program
bool gTerminate = false;

// Worker threads.
void *readVideo( void *ptr );
void *displayVideo( void *ptr );
void *textureBGS( void *ptr );

int main(int argc, const char* argv[])
{
	AxisSettings axisSettings;
	axisSettings.width = 160;
	axisSettings.height = 120;
	axisSettings.compression = 30;
	axisSettings.requestedFPS = 30;
	axisSettings.colorLevel = 0;		// DP: doesn't work??
	axisSettings.rotation = 0;			
	axisSettings.showClock = 0;
	axisSettings.showDate = 0;
	axisSettings.showText = 0;
	
	// initialize Axis camera
	AxisCamera* axisCam = new AxisCamera(axisSettings, AXIS_IP_ADDR);
	
	// create thread to read video
	pthread_t readVideoThread;
	int ret = pthread_create( &readVideoThread, NULL, readVideo, (void*) axisCam);
	if(ret != 0)
	{
		perror("Error");
		exit(ret);
	}
	
	// create thread to display video
	pthread_t displayVideoThread;
	ret = pthread_create( &displayVideoThread, NULL, displayVideo, (void*) axisCam);
	if(ret != 0)
	{
		perror("Error");
		exit(ret);
	}
	
	// create thread to display results of foreground segmentation
	pthread_t textureThread;
	ret = pthread_create( &textureThread, NULL, textureBGS, (void*) axisCam);
	if(ret != 0)
	{
		perror("Error");
		exit(ret);
	}

	// wait till mediod thread is complete before exiting main
	ret = pthread_join(textureThread, NULL);
	if(ret != 0)
	{
		perror("Error");
		exit(ret);
	}
	
	// wait till display video thread is complete before exiting main
	ret = pthread_join(displayVideoThread, NULL);
	if(ret != 0)
	{
		perror("Error");
		exit(ret);
	}
	
	// wait till read video thread is complete before exiting main
	ret = pthread_join(readVideoThread, NULL);
	if(ret != 0)
	{
		perror("Error");
		exit(ret);
	}
	
	delete axisCam;
	
	exit(0);
}

void *readVideo( void *ptr )
{
	AxisCamera* axisCam = (AxisCamera *) ptr;
	
	// continue to acquire images until the user wishes to terminate
	while(!gTerminate)
	{
		axisCam->AcquireImages();
	}
	
	return 0;
}

void *displayVideo( void *ptr )
{
	AxisCamera* axisCam = (AxisCamera *) ptr;
	
	IplImage* image = cvCreateImage(cvSize(axisCam->Width(), axisCam->Height()), 8, 3);
		
	cvNamedWindow("Video Frame",1);
	
	unsigned int frameNum = 0;
	while(!gTerminate)
	{
		axisCam->GetImage(image, frameNum);
		
		cvShowImage("Video Frame",image);
		
		// sleep for 10ms or until user presses a key
		int key = cvWaitKey(10);
		
		// check if user is finished (i.e., ESC is pressed)
		if((key&0xFF) == 27)	
		{
			gTerminate = true;
		}
	}
	
	cvReleaseImage(&image);	
	cvDestroyWindow("Video Frame");
	
	return 0;
}

// --- Texture-based BGS ----------------------------------------------------------------

const int REGION_R = 5;			// Note: the code currently assumes this value is <= 7
const int TEXTURE_POINTS = 6;	// Note: the code currently assumes this value is 6
const int TEXTURE_R = 2;		// Note: the code currently assumes this value is 2
const int NUM_BINS = 64;		// 2^TEXTURE_POINTS
const int HYSTERSIS = 3;
const float ALPHA = 0.01f;
const float THRESHOLD = 0.7*(REGION_R+REGION_R+1)*(REGION_R+REGION_R+1)*NUM_CHANNELS;
const int NUM_MODES = 1;		// The paper describes how multiple modes can be maintained,
								// but this implementation does not fully support more than one
struct TextureHistogram
{
	unsigned char r[NUM_BINS];	// histogram for red channel
	unsigned char g[NUM_BINS];	// histogram for green channel
	unsigned char b[NUM_BINS];	// histogram for blue channel
};

struct TextureArray
{
	TextureHistogram mode[NUM_MODES];
};

void LBP(RgbImage& image, RgbImage& texture)
{
	for(int y = TEXTURE_R; y < image.Ptr()->height-TEXTURE_R; ++y)
	{
		for(int x = TEXTURE_R; x < image.Ptr()->width-TEXTURE_R; ++x)
		{		
			for(int ch = 0; ch < NUM_CHANNELS; ++ch)
			{
				unsigned char textureCode = 0;
				int centerValue = (int)image(y, x, ch);
	
				// this only works for a texture radius of 2
				if(centerValue - (int)image(y-2, x, ch) + HYSTERSIS >= 0)
					textureCode += 1;
				
				if(centerValue - (int)image(y-1, x-2, ch) + HYSTERSIS >= 0)
					textureCode += 2;
				
				if(centerValue - (int)image(y-1, x+2, ch) + HYSTERSIS >= 0)
					textureCode += 4;
				
				if(centerValue - (int)image(y+1, x-2, ch) + HYSTERSIS >= 0)
					textureCode += 8;
				
				if(centerValue - (int)image(y+1, x+2, ch) + HYSTERSIS >= 0)
					textureCode += 16;
				
				if(centerValue - (int)image(y+2, x, ch) + HYSTERSIS >= 0)
					textureCode += 32;
				
				texture(y,x,ch) = textureCode;
			}
		}
	}
}

void Histogram(RgbImage& texture, TextureHistogram* curTextureHist)
{
	// calculate histogram within a 2*REGION_R square
	for(int y = REGION_R+TEXTURE_R; y < texture.Ptr()->height-REGION_R-TEXTURE_R; ++y)
	{
		for(int x = REGION_R+TEXTURE_R; x < texture.Ptr()->width-REGION_R-TEXTURE_R; ++x)
		{	
			int index = x+y*(texture.Ptr()->width);
			
			// clear histogram
			for(int i = 0; i < NUM_BINS; ++i)
			{
				curTextureHist[index].r[i] = 0;
				curTextureHist[index].g[i] = 0;
				curTextureHist[index].b[i] = 0;
			}
			
			// calculate histogram
			for(int j = -REGION_R; j <= REGION_R; ++j)
			{
				for(int i = -REGION_R; i <= REGION_R; ++i)
				{
					curTextureHist[index].r[texture(y+j,x+i,2)]++;
					curTextureHist[index].g[texture(y+j,x+i,1)]++;
					curTextureHist[index].b[texture(y+j,x+i,0)]++;
				}
			}
		}
	}
}

int ProximityMeasure(TextureHistogram& bgTexture, TextureHistogram& curTextureHist)
{
	int proximity = 0;	
	for(int i = 0; i < NUM_BINS; ++i)
	{
		proximity += min(bgTexture.r[i], curTextureHist.r[i]);
		proximity += min(bgTexture.g[i], curTextureHist.g[i]);
		proximity += min(bgTexture.b[i], curTextureHist.b[i]);
	}
	
	return proximity;	
}

void BgsCompare(TextureArray* bgModel, TextureHistogram* curTextureHist, 
					unsigned char* modeArray, float threshold, BwImage& fgMask)
{
	cvZero(fgMask.Ptr());
	
	for(int y = REGION_R+TEXTURE_R; y < fgMask.Ptr()->height-REGION_R-TEXTURE_R; ++y)
	{
		for(int x = REGION_R+TEXTURE_R; x < fgMask.Ptr()->width-REGION_R-TEXTURE_R; ++x)
		{	
			int index = x+y*(fgMask.Ptr()->width);
		
			// find closest matching texture in background model
			int maxProximity = -1;
			for(int m = 0; m < NUM_MODES; ++m)
			{
				int proximity = ProximityMeasure(bgModel[index].mode[m], curTextureHist[index]);
						
				if(proximity > maxProximity)
				{
					maxProximity = proximity;
					modeArray[index] = m;
				}
			}
			
			if(maxProximity < threshold)
			{
				fgMask(y,x) = 255;
			}
		}
	}
}

void UpdateModel(BwImage& fgMask, TextureArray* bgModel, 
					TextureHistogram* curTextureHist, unsigned char* modeArray)
{
	for(int y = REGION_R+TEXTURE_R; y < fgMask.Ptr()->height-REGION_R-TEXTURE_R; ++y)
	{
		for(int x = REGION_R+TEXTURE_R; x < fgMask.Ptr()->width-REGION_R-TEXTURE_R; ++x)
		{		
			int index = x+y*(fgMask.Ptr()->width);
			
			if(fgMask(x,y) == 0)
			{
				for(int i = 0; i < NUM_BINS; ++i)
				{
					bgModel[index].mode[modeArray[index]].r[i]
				      = (unsigned char)(ALPHA*curTextureHist[index].r[i]
					    + (1-ALPHA)*bgModel[index].mode[modeArray[index]].r[i] + 0.5);
				}
			}				
		}
	}	
}

void *textureBGS( void *ptr )
{
	AxisCamera* axisCam = (AxisCamera *) ptr;
	int width = axisCam->Width();
	int height = axisCam->Height();
	int size = width*height;
	
	// camera image
	RgbImage image = cvCreateImage(cvSize(width, height), 8, 3);
	
	// foreground masks
	BwImage fgMask = cvCreateImage(cvSize(width, height), 8, 1);
	BwImage tempMask  = cvCreateImage(cvSize(width, height), 8, 1);
	cvZero(fgMask.Ptr());
	
	// create background model
	TextureArray* bgModel = new TextureArray[size];
	RgbImage texture = cvCreateImage(cvSize(width, height), 8, 3);
	unsigned char* modeArray = new unsigned char[size];
	TextureHistogram* curTextureHist = new TextureHistogram[size];
	
	// initialize background model
	unsigned int frameNum = 0;
	axisCam->GetImage(image.Ptr(), frameNum);
	LBP(image, texture);
	Histogram(texture, curTextureHist);
	for(int y = REGION_R+TEXTURE_R; y < height-REGION_R-TEXTURE_R; ++y)
	{
		for(int x = REGION_R+TEXTURE_R; x < width-REGION_R-TEXTURE_R; ++x)
		{
			int index = x+y*width;
			
			for(int m = 0; m < NUM_MODES; ++m)
			{
				for(int i = 0; i < NUM_BINS; ++i)
				{			
					bgModel[index].mode[m].r[i] = curTextureHist[index].r[i];
					bgModel[index].mode[m].g[i] = curTextureHist[index].g[i];
					bgModel[index].mode[m].b[i] = curTextureHist[index].b[i];
				}
			}
		}
	}

	// connected-components
	ConnectedComponents cc;
	
	// structuring element used for dilation and erosion
	IplConvKernel* dilateElement = cvCreateStructuringElementEx(7, 7, 3, 3,	CV_SHAPE_RECT);
	IplConvKernel* erodeElement = cvCreateStructuringElementEx(3, 3, 1, 1,	CV_SHAPE_RECT);
		
	cvNamedWindow("Before Post Processing",1);
	cvNamedWindow("Texture BGS",1);
	
	while(!gTerminate)
	{
		// get the new image
		axisCam->GetImage(image.Ptr(), frameNum);

		// preprocessing
		//cvSmooth(image.Ptr(), image.Ptr(), CV_GAUSSIAN, 3, 0, 0); 

		// perform background subtraction
		LBP(image, texture);
		Histogram(texture, curTextureHist);
		BgsCompare(bgModel, curTextureHist, modeArray, THRESHOLD, fgMask);
		
		cvShowImage("Before Post Processing", fgMask.Ptr());
		
		// size filtering
		CBlobResult largeBlobs;
		cc.SetImage(&fgMask);
		cc.Find(127);
		cc.FilterMinArea(size/30, largeBlobs);
		fgMask.Clear();
		CvScalar color = CV_RGB(255,255,255);
		cc.ColorBlobs(fgMask.Ptr(), largeBlobs, color);
		
		// morphological operators
		cvDilate(fgMask.Ptr(), fgMask.Ptr(), dilateElement, 1);
		cvErode(fgMask.Ptr(), fgMask.Ptr(), erodeElement, 1);
			
		// show results of background subtraction
		cvShowImage("Texture BGS", fgMask.Ptr());
		
		// update background subtraction		
		UpdateModel(fgMask, bgModel, curTextureHist, modeArray);
		
		// sleep for 10ms or until user presses a key
		int key = cvWaitKey(10);
		
		// check if user is finished (i.e., ESC is pressed)
		if((key&0xFF) == 27)	
		{
			gTerminate = true;
		}
	}
	
	cvReleaseStructuringElement(&dilateElement);
	cvReleaseStructuringElement(&erodeElement);
	
	cvDestroyWindow("Before Post Processing");
	cvDestroyWindow("Texture BGS");
	
	delete[] bgModel;
	delete[] modeArray;
	delete[] curTextureHist;
	
	return 0;
}
Tags: C++

Plain Text
ASM
ASP
ASP.NET
BASIC
BAT
C#
C++
COBOL
CoffeeScript
CSS
Dart
dbase
F#
FORTRAN
HTML
Java
Javascript
Kotlin
Lua
MIDL
MSIL
ObjectiveC
Pascal
PERL
PHP
PowerShell
Python
Razor
Ruby
Scala
Shell
SLN
SQL
Swift
T4
Terminal
TypeScript
VB
VBScript
XML
YAML

Preview



When answering a question please:
  1. Read the question carefully.
  2. Understand that English isn't everyone's first language so be lenient of bad spelling and grammar.
  3. If a question is poorly phrased then either ask for clarification, ignore it, or edit the question and fix the problem. Insults are not welcome.
  4. Don't tell someone to read the manual. Chances are they have and don't get it. Provide an answer or move on to the next question.
Let's work to help developers, not make them feel stupid.
Please note that all posts will be submitted under the http://www.codeproject.com/info/cpol10.aspx.



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900