View Full Version : My Source Code for computing mean brightness ?

November 2, 2004, 13:12:11
Dear Stefan,

I tried computing the mean brightness and subtract it from each pixel. But i am unable to get the required results.

This code still considers the light flickering to be a motion and starts recording. I want to avoid this.

I am calculating the mean brightness of the current image and subtracting it from each pixel of the current image. same i do for the previous image. but i dont understand for the code to not work.

I am posting my source code in delphi for your reference. kindly take time to look into it and correct me if i am going wrong. I would be highly obliged if you put some time into this since its urgent to me.

below is my source code,

**************code snippet - Start***************************
//for no. of motion detect areas selected.
for iArea := 0 to MAX_MOTION_AREA - 1 do
//variables initialised for each motion detect area
count := 0;
curBrightnessVal := 0;
keyBrightnessVal := 0;
CurMeanBrightness := 0;
KeyMeanBrightness := 0;

with WorkConfig.Camera[ACameraNo].MotionDetectArea[iArea] do

//calculates the mean brightness for the motion detect area selected.
for i := Top to Bottom - 1 do
for j := Left to Right - 1 do
iPixelPoint := (i * iQuadWidth * 2) + (j * 2);

//count maintains the count of no. of pixels
count := count + 1;

//brightness values of each pixel in current & previous image
liCurPx := ColorToRGB(pYuvBuf[iPixelPoint]); //current image
liKeyPx := ColorToRGB(asKeyBuf[ACameraNo][iPixelPoint]); //previous image

//sum of the colour values of each pixel in the current image
curBrightnessVal := curBrightnessVal + liCurPx;

//sum of the colour values of each pixel in the previous image
keyBrightnessVal := keyBrightnessVal + liKeyPx;

//mean brightness of the current image
CurMeanBrightness := round((curBrightnessVal / count));

//mean brightness of the previous image
KeyMeanBrightness := round((keyBrightnessVal / count));

for i := Top to Bottom - 1 do
for j := Left to Right - 1 do
iPixelPoint := (i * iQuadWidth * 2) + (j * 2);

if pYuvBuf[iPixelPoint] < 0 then
liCurPx := pYuvBuf[iPixelPoint] + 256
else liCurPx := pYuvBuf[iPixelPoint];

//mean brightness subtracted from each pixel in the current image
liCurPx := liCurPx - CurMeanBrightness;

if asKeyBuf[ACameraNo][iPixelPoint] < 0 then
liKeyPx := asKeyBuf[ACameraNo][iPixelPoint] + 256
else liKeyPx := asKeyBuf[ACameraNo][iPixelPoint];

//mean brightness subtracted from each pixel in the previous image
liKeyPx := liKeyPx - keyMeanBrightness;

liSum := liSum + ABS(liCurPx - liKeyPx);

if ((Right - (Left - 1)) * (Bottom - (Top - 1))) = 0 then Continue;
liSum := liSum div ((Right - (Left - 1)) * (Bottom - (Top - 1)));

if liSum > WorkConfig.Camera[ACameraNo].MotionSensitivity then
Result := True;
**************code snippet - End***************************

looking forward to your reply,
thanks & regards,

Stefan Geissler
November 5, 2004, 13:44:38
Hello Atul,

I think, you should think about what is happening, if you subract the mean brightness from each pixel in your image. The image becomes darker. Some pixel values become negative, they should be set to zero and not to be added with 256.
Also you may should calculate the mean brightness between the current image and the previously capture images to get an nearly equal brightness niveau. This is just an idea, i do not know, whether this would work.

As i suggested some posts previously, i would prefer an egde sensing algorithm. This algorithm stores for each line, where the brightness differences are above a threshold. Because the brightness difference within the image is used and only the egde is stored as 0 (no edge) 1 (edge), you would get a brightness independent edge profile. If an object moves, the edges will move with it. Just compare the previously saved edges with the ones in the current image, and find the differences.

November 5, 2004, 14:36:35
Dear Stefan,

Stefan, thanks for your reply. I will modify my code as you have suggested, computing the mean brightness and see if it works.

you are right that the Edge Detection Method would be an ideal method to get better results but since i am not able to perceive the logic thats is why i am not able to go ahead.

Is it possible for you to write down in steps in English Sentences, the algorithm for the same then i can get a head start to implement the logic. That would really be helpful to me. Since you have seen my code, you could be in better position to give me the algorithm as per your knowledge in this area.

Other thing is that i have found a complete Edge Detection code in MATLAB given in the following link:

If you are aware of how can i integrate the MATLAB code into my custom application (Delphi), then please do let me know. It would be really a good help to me.

looking forward for your reply,
thanks & regards,

Stefan Geissler
November 5, 2004, 15:40:01
Hello Atul,

here is the algorithm, that is a little bit more resistant against brightness changes.
First of all, we need an array, that will contain 0 or 1 for the detected edges.
Also we need a threshold variable, that determines the threshold when we detect an edge as moved.

The implementation has been done in C#.

private byte[] Edges;
private byte Threshold;

The size of the Edges array depends on the used video format. After the video capture device and the video format has been determined, the array size is set (memory is allocated):

// Initialize the edges array.
Edges = new byte[icImagingControl1.ImageHeight * icImagingControl1.ImageWidth];
for( int i = 0; i < icImagingControl1.ImageHeight * icImagingControl1.ImageWidth; i++)
Edges[i] = 0;
Threshold = 50; // Edge sense.

The sink type will be set to Y8, because we will only need the brightness of each pixel. So IC Imaging Control is initialized as follows:

// Use the Y8 format, because only the brightness is needed.
icImagingControl1.MemoryCurrentGrabberColorformat = TIS.Imaging.ICImagingControlColorformats.ICY8;
// Grab any incoming frame.
icImagingControl1.LiveCaptureContinuous = true;
// Display the images only, if a motion has been detected.
icImagingControl1.LiveDisplay = false;

Next step is to implement the ImageAvailable event handler:

// Handle the incoming images.
private void icImagingControl1_ImageAvailable(object sender, TIS.Imaging.ICImagingControl.ImageAvailableEventAr gs e)
TIS.Imaging.ImageBuffer CurrentBuffer = null;
CurrentBuffer = icImagingControl1.ImageBuffers[e.bufferIndex];

if( isMotionDeteced(CurrentBuffer))
icImagingControl1.DisplayImageBuffer(CurrentBuffer );

The ImageAvailable event handler locks the current image buffer and calls the function, that does the motion detection (isMotionDetected()). Only if a motion was detected, the image buffer will be displayed.

The motion detection calculates the absolute difference from one pixel to its right neighbour. If the difference is bigger than the Threshold value, we assume there is an edge. Now the algorithm compares the current edge value (0 or 1) with the previously saved edge value in the edges value. If the value differs, it adds one to the counter ChangedEdges. If ChangedEgdes is bigger that a predefined value, a motion was detected. If it was smaller, no motion was detected.
The edge value will no be saved in the Edges array to be used for the next image.

bool isMotionDeteced(TIS.Imaging.ImageBuffer CurrentBuffer)
int ChangedEdges = 0;
byte *pPixel = CurrentBuffer.GetImageData();
int iPixel = 0;
byte Edge = 0;
int H = icImagingControl1.ImageHeight;
int W = icImagingControl1.ImageWidth-1;

for( int y = 0; y < H; y++)
for( int x = 0; x < W; x++)
if( Math.Abs( pPixel[0] - pPixel[1]) > Threshold)
Edge = 1;
Edge = 0;

if( Edge != Edges[iPixel] )
ChangedEdges++; // There was a change to the previous checked image!
Edges[iPixel] = Edge;
// If you want to see the edges, uncomment following:
if(Edge == 1)
*pPixel = 255;
*pPixel = 0;*/
// If more than 100 edges have been changed, return a detected motion.
if( ChangedEdges > 100)
return true;
return false;

This algorithm is simple and fast. I ignores soft changes of light, but it reacts on noise that comes from a camera. Therefore the edge must be detected over a range of pixels. You may insert following:

if( (Math.Abs( pPixel[0] + pPixel[1]+ pPixel[2]- pPixel[3]- pPixel[4] - pPixel[5]))/3 > Threshold)

I suggest to play around with this algorithm. I think it can be enhances.