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:
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:
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.
#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;
#define AXIS_IP_ADDR "192.168.2.5"
bool gTerminate = false;
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; axisSettings.rotation = 0;
axisSettings.showClock = 0;
axisSettings.showDate = 0;
axisSettings.showText = 0;
AxisCamera* axisCam = new AxisCamera(axisSettings, AXIS_IP_ADDR);
pthread_t readVideoThread;
int ret = pthread_create( &readVideoThread, NULL, readVideo, (void*) axisCam);
if(ret != 0)
{
perror("Error");
exit(ret);
}
pthread_t displayVideoThread;
ret = pthread_create( &displayVideoThread, NULL, displayVideo, (void*) axisCam);
if(ret != 0)
{
perror("Error");
exit(ret);
}
pthread_t textureThread;
ret = pthread_create( &textureThread, NULL, textureBGS, (void*) axisCam);
if(ret != 0)
{
perror("Error");
exit(ret);
}
ret = pthread_join(textureThread, NULL);
if(ret != 0)
{
perror("Error");
exit(ret);
}
ret = pthread_join(displayVideoThread, NULL);
if(ret != 0)
{
perror("Error");
exit(ret);
}
ret = pthread_join(readVideoThread, NULL);
if(ret != 0)
{
perror("Error");
exit(ret);
}
delete axisCam;
exit(0);
}
void *readVideo( void *ptr )
{
AxisCamera* axisCam = (AxisCamera *) ptr;
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);
int key = cvWaitKey(10);
if((key&0xFF) == 27)
{
gTerminate = true;
}
}
cvReleaseImage(&image);
cvDestroyWindow("Video Frame");
return 0;
}
const int REGION_R = 5; const int TEXTURE_POINTS = 6; const int TEXTURE_R = 2; const int NUM_BINS = 64; 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; struct TextureHistogram
{
unsigned char r[NUM_BINS]; unsigned char g[NUM_BINS]; unsigned char b[NUM_BINS]; };
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);
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)
{
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);
for(int i = 0; i < NUM_BINS; ++i)
{
curTextureHist[index].r[i] = 0;
curTextureHist[index].g[i] = 0;
curTextureHist[index].b[i] = 0;
}
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);
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;
RgbImage image = cvCreateImage(cvSize(width, height), 8, 3);
BwImage fgMask = cvCreateImage(cvSize(width, height), 8, 1);
BwImage tempMask = cvCreateImage(cvSize(width, height), 8, 1);
cvZero(fgMask.Ptr());
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];
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];
}
}
}
}
ConnectedComponents cc;
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)
{
axisCam->GetImage(image.Ptr(), frameNum);
LBP(image, texture);
Histogram(texture, curTextureHist);
BgsCompare(bgModel, curTextureHist, modeArray, THRESHOLD, fgMask);
cvShowImage("Before Post Processing", fgMask.Ptr());
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);
cvDilate(fgMask.Ptr(), fgMask.Ptr(), dilateElement, 1);
cvErode(fgMask.Ptr(), fgMask.Ptr(), erodeElement, 1);
cvShowImage("Texture BGS", fgMask.Ptr());
UpdateModel(fgMask, bgModel, curTextureHist, modeArray);
int key = cvWaitKey(10);
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;
}