"Static" (VB6) equalivent in C++?

A

Anna Smidt

I have a function which will return a shape from an image everytime it's
called.
Since it's time consuming I would like it to run itself only once, and
at every subsequent calls it should return the shape it calculated the
first time.
In VB6 I would have used the key word "static" to preserve the results
from the first call. Is there an equivalent in C++?

---------------
In VB6 I would have simply said

function Foo(byref uSomething, byref uOutput) as boolean

static bWasRunBefore as boolean //This is a variable will be never get
out of scope
static nFirstTimeResult as something //This is a variable will be never
get out of scope

if not bWasRunBefore
//If it's the first time that this function is called
//do some heavy math stuff
uOutPut = nResult
nFirstTimeResult = nResult //Rember the first result for subsequent calls
bWasRunBefore = True //Remember that this function was called before
else
//Function was already called before, and we will return the old result
//return the return from the first time around
uOutput = nFirstTimeResult
end if

End function

-----------------
C++ code:

bool ViolaJonesFindFace(SHAPE &Shape, const IplImage* image,const char
sDataDir[])
{
if (!pgCascade) // first time?
OpenViolaJones(sDataDir);
Shape.dimClear(NBR_VIOLA_JONES_POINTS, 2);

IplImage* pWork = cvCreateImage
(cvSize(image->width/2, image->height/2), image->depth, image->nChannels);
cvPyrDown(image, pWork, CV_GAUSSIAN_5x5 );


CvSeq* pFaces = cvHaarDetectObjects(pWork, pgCascade, pgStorage,
SCALE_FACTOR, MIN_NEIGHBORS,CV_HAAR_DO_CANNY_PRUNING);

cvReleaseImage(&pWork);

if(0 == pFaces->total)//can't find a face
return false;

int iSelectedFace = 0;
// get most central face
double MaxOffset = 1e10;
// max abs dist from center of face to center of image
for (int iFace = 0; iFace < pFaces->total; iFace++)
{
CvRect* r = (CvRect*)cvGetSeqElem(pFaces, iFace);
double Offset = ABS(r->x*2.0 + r->width - image->width/2.0);
if (Offset < MaxOffset)
{
MaxOffset = Offset;
iSelectedFace = iFace;
}
}

// Write the global detector shape into Shape.
// We must convert the Viola Jones shape coords to our internal shape
coords.
CvRect* r = (CvRect*)cvGetSeqElem(pFaces, iSelectedFace);

int scale = 2;
CvPoint pt1, pt2;
pt1.x = r->x*scale;
pt2.x = (r->x+r->width)*scale;
pt1.y = r->y*scale;
pt2.y = (r->y+r->height)*scale;

Shape(DETECTOR_TopLeft, VX) = r->x*2 - image->width/2.0;
Shape(DETECTOR_TopLeft, VY) = image->height/2.0 - r->y*2;
Shape(DETECTOR_BotRight, VX) = Shape(DETECTOR_TopLeft, VX) + 2*r->width;
Shape(DETECTOR_BotRight, VY) = Shape(DETECTOR_TopLeft, VY) - 2*r->height;

return true;
}
 
D

David Wilkinson

Anna said:
I have a function which will return a shape from an image everytime it's
called.
Since it's time consuming I would like it to run itself only once, and
at every subsequent calls it should return the shape it calculated the
first time.
In VB6 I would have used the key word "static" to preserve the results
from the first call. Is there an equivalent in C++?

---------------
In VB6 I would have simply said

function Foo(byref uSomething, byref uOutput) as boolean

static bWasRunBefore as boolean //This is a variable will be never
get out of scope
static nFirstTimeResult as something //This is a variable will be
never get out of scope

if not bWasRunBefore
//If it's the first time that this function is called
//do some heavy math stuff
uOutPut = nResult
nFirstTimeResult = nResult //Rember the first result for
subsequent calls
bWasRunBefore = True //Remember that this function was called
before
else
//Function was already called before, and we will return the old
result
//return the return from the first time around
uOutput = nFirstTimeResult
end if

End function

-----------------
C++ code:

bool ViolaJonesFindFace(SHAPE &Shape, const IplImage* image,const char
sDataDir[])
{
if (!pgCascade) // first time?
OpenViolaJones(sDataDir);
Shape.dimClear(NBR_VIOLA_JONES_POINTS, 2);

IplImage* pWork = cvCreateImage
(cvSize(image->width/2, image->height/2), image->depth,
image->nChannels);
cvPyrDown(image, pWork, CV_GAUSSIAN_5x5 );


CvSeq* pFaces = cvHaarDetectObjects(pWork, pgCascade, pgStorage,
SCALE_FACTOR, MIN_NEIGHBORS,CV_HAAR_DO_CANNY_PRUNING);

cvReleaseImage(&pWork);

if(0 == pFaces->total)//can't find a face
return false;

int iSelectedFace = 0;
// get most central face
double MaxOffset = 1e10;
// max abs dist from center of face to center of image
for (int iFace = 0; iFace < pFaces->total; iFace++)
{
CvRect* r = (CvRect*)cvGetSeqElem(pFaces, iFace);
double Offset = ABS(r->x*2.0 + r->width - image->width/2.0);
if (Offset < MaxOffset)
{
MaxOffset = Offset;
iSelectedFace = iFace;
}
}

// Write the global detector shape into Shape.
// We must convert the Viola Jones shape coords to our internal
shape coords.
CvRect* r = (CvRect*)cvGetSeqElem(pFaces, iSelectedFace);

int scale = 2;
CvPoint pt1, pt2;
pt1.x = r->x*scale;
pt2.x = (r->x+r->width)*scale;
pt1.y = r->y*scale;
pt2.y = (r->y+r->height)*scale;

Shape(DETECTOR_TopLeft, VX) = r->x*2 - image->width/2.0;
Shape(DETECTOR_TopLeft, VY) = image->height/2.0 - r->y*2;
Shape(DETECTOR_BotRight, VX) = Shape(DETECTOR_TopLeft, VX) +
2*r->width;
Shape(DETECTOR_BotRight, VY) = Shape(DETECTOR_TopLeft, VY) -
2*r->height;

return true;
}

Anna:

You can use the static keyword in just this way in C or C++. But you must be
sure the function cannot be called from multiple threads at the same time.
 
A

Anna Smidt

I seem to be a bit stupid... Why is "iDone" always "1"?

static int iDone=0;

iDone++; //Increment each time the void is called

if (iDone>5)
{
iDone=1; // If iDone exceeds 5, set it to 1 again
}

if (iDone=1) //
{
printf("iDone is 1!");
}
else
{
printf("Yieha!! Not 1!");
}

....
 
B

Ben Voigt [C++ MVP]

Anna said:
I seem to be a bit stupid... Why is "iDone" always "1"?

static int iDone=0;

iDone++; //Increment each time the void is called

if (iDone>5)
{
iDone=1; // If iDone exceeds 5, set it to 1 again
}

if (iDone=1) //

Right here, you have used the assignment operator (one =), when you wanted
the equality comparison operator (==, that's two =). Turn up your warning
level and pay attention to the warnings.
 
B

Ben Voigt [C++ MVP]

Anna Smidt said:
Doh!! How embarassing!
Thanks.

The ease with which I and other experts recognize this mistake should
suggest that we've seen it many times before -- most often in our own code.

There are some tricks to help prevent it though.

For example,

if (1 == x)

is legal, but

if (1 = x)

is not. If you put anything on the left side that can't be assigned,
whether a literal number or an expression, the compiler won't let you make
the mistake.
 
S

SvenC

Hi Anna,
Doh!! How embarassing!

In addition to Ben's suggestion.

Turn on warning level 4 in your project's C++ settings.
That will warn on assignments in conditional expressions.

Besides that it will warn you about a lot of dubious code.

So try to get your code warning free in level 4 as good as
you can and you have at least taken all the help the
compiler can give you.
 
Top