PDA

View Full Version : Removing overlay from previous image



Sidd
June 18, 2005, 19:31:34
I am finding feature points (points of my interest) in the image frames. Currently, I am using "grabber->getOverlay()->drawFrameRect( RGB(255,0,0), rectangle);" method to display the feature points in current frame. But the problem is for the next frame the image processing finds out new feature points and I want to delete the old overlay and draw the new feature points in the image.
Can you suggest the right method/functions to do this, and also I would appreciate if you can send me the code for this process.

Stefan Geissler
June 20, 2005, 08:48:10
Hello Sidd,

You should remove the last painted rectangle by drawing it with the current dropout color again (http://www.imagingcontrol.com/ic/docs/html/class/meth_descOverlayBitmap_getDropOutColor.htm )

The next incoming frame has no graphics on it after you did this.

If you want to find you feature points in a realtime live video stream and display the rectangles on the live video, then the approach of using the overlay may is not suitable. If you perform the image processing in the GrabberListener::frameReady() method, you should display the live video on your own. This means, you should call Grabber::startLive( false ).

You should implement following method into your GrabberListener inherited class:


void CListener::DrawBuffer( smart_ptr<MemBuffer> pBuffer)
{
if( m_pDrawCWnd != NULL)
{
if( pBuffer != 0 )
{
CDC *pDC = m_pDrawCWnd->GetDC();

smart_ptr<BITMAPINFOHEADER> pInf = pBuffer->getBitmapInfoHeader();

int nLines = StretchDIBits( pDC->GetSafeHdc(),// Handle to the device
0,
0,
pInf->biWidth, // Dest rectangle width
pInf->
biHeight, // Dest rectangle height
0, // X-coordinate of lower-left corner of the source rect
0, // Y-coordinate of lower-left corner of the source rect
pInf->biWidth, // Source rectangle width
pInf->biHeight, // Number of scan lines
pBuffer->getPtr(), //
reinterpret_cast<LPBITMAPINFO>( &*pInf ), /
DIB_RGB_COLORS, // RGB or palette indices
SRCCOPY
);
m_pDrawCWnd->ReleaseDC(pDC);
}
}
}

The pDrawCWnd is of type CWnd* and is a window of your application (e.g. a Ctatic).

This function can be called after your image processing has been performed. You can use the pDC device context to draw the rectangle. You do not need to delete the old rectangle previously, because it will be overwritten by the StretchDIBits() call.

So your frameReady() would look like follows:


void CListener::frameReady( Grabber& param, smart_ptr<MemBuffer> pBuffer, DWORD FrameNumber)
{
pBuffer->lock();
DoImageProcessing( pBuffer );
DrawBuffer(pBuffer);
pBuffer->unlock();
}

In this code, the rectangle would flicker. To avoid this, you would create a bitmap in memory and draw the video frame and the rectangles into this memory bitmap. Then the memory bitmap would be blitted in the device context of the draw window. (Sounds complicated, but it isn't, it is just a little bit GDI programming.)

Create a HBTIMAP in following way:


// Retrieve the color depth of the desktop
HDC dc = CreateCompatibleDC( NULL );
int bpp = GetDeviceCaps(dc,BITSPIXEL);
DeleteDC(dc);

DWORD Size = ((bpp>>3) * m_cCameraRect.Width() * m_cCameraRect.Height());
BYTE *bytes = NULL;

bytes = new BYTE[Size];

m_hMemoryBitmap = CreateBitmap(640, 480,1,bpp,bytes);
delete [] bytes;

The dimensions of the memory bitmap should be the same as the video format's dimensions.

The drawing would be following:


void CListener::DrawBuffer( Grabber& grabber, smart_ptr<MemBuffer> pBuffer)
{
if( m_pDrawWindow != NULL && pBuffer != NULL)
{
smart_ptr<BITMAPINFOHEADER> pInf = pBuffer->getBitmapInfoHeader();
void* pBuf = pBuffer->getPtr();
HDC hDC = GetDC( m_pDrawWindow->GetSafeHwnd());
HDC memDC;
memDC = CreateCompatibleDC(hDC);

// Select the bitmap of the memory DC to draw in.
SelectObject(memDC, m_hMemoryBitmap);

SetStretchBltMode(hDC , COLORONCOLOR);
SetStretchBltMode(memDC , COLORONCOLOR);

// Now perform the drawings
int nLines = StretchDIBits(memDC,// Handle to the device
0, // x-coord of destination upper-left corner
0, // y-coord of destination upper-left corner
m_cCameraRect.Width(), // width of destination rectangle
m_cCameraRect.Height(), // height of destination rectangle
0, // x-coord of source upper-left corner
0,// y-coord of source upper-left corner
pInf->biWidth, // Source rectangle width
pInf->biHeight, // Source rectangle height
pBuffer->getPtr(), // Modified address of array with DIB bits0, // First scan line in array
reinterpret_cast<LPBITMAPINFO>( &*pInf ),
DIB_RGB_COLORS,// RGB or palette indices
SRCCOPY
);

// Here draw your rectangle in the memDC device context.


// Copy the complete drawing to the hDC so it can be seen on the window.
BitBlt( hDC,0,0, pInf->biWidth , pInf->biHeight , memDC,0,0, SRCCOPY);

DeleteDC( memDC);



ReleaseDC(grabber.getHWND(),hDC);
}


I hope, this gives you an idea about how to solve your problem.

Stefan Geissler
June 20, 2005, 09:25:24
Sidd,

You can download a complete sample from the given link. It implements the flicker free drawing metioned in my last post. You only need to insert your image processing and set the coordinates for your rectangle. And you should draw your rectangle with MoveToEx and LineTo etc, where the ::Rectangle call is.

Copy the sample in the /samples/VC6 directory. It should compile without any problems.