1. WebCam with wxEuphoria
- Posted by Jerome Mar 25, 2011
- 1377 views
I've just started on a project to do image acquisition with OpenCV, EU4, and wxEuphoria. OpenCV allows me to grab images from my webcam, and it returns a pointer to the memory location of the RGB values for each pixel. I would like to be able to display these images with wxEuphoria using something like wxImage or wxBitmap, but I'm not sure how to organize the pixel data. Do I need to make a 2D sequence where each entry is a sequence of 3 characters representing the RGB values? Something like this:
image = {{{R,G,B},{R,G,B},{R,G,B},{R,G,B}}, {{R,G,B},{R,G,B},{R,G,B},{R,G,B}}, {{R,G,B},{R,G,B},{R,G,B},{R,G,B}}}
If so, then what is the appropriate function to pass this info to display these images?
Thanks in advance,
Ira
2. Re: WebCam with wxEuphoria
- Posted by mattlewis (admin) Mar 25, 2011
- 1354 views
I've just started on a project to do image acquisition with OpenCV, EU4, and wxEuphoria. OpenCV allows me to grab images from my webcam, and it returns a pointer to the memory location of the RGB values for each pixel. I would like to be able to display these images with wxEuphoria using something like wxImage or wxBitmap, but I'm not sure how to organize the pixel data. Do I need to make a 2D sequence where each entry is a sequence of 3 characters representing the RGB values? Something like this:
image = {{{R,G,B},{R,G,B},{R,G,B},{R,G,B}}, {{R,G,B},{R,G,B},{R,G,B},{R,G,B}}, {{R,G,B},{R,G,B},{R,G,B},{R,G,B}}}
If so, then what is the appropriate function to pass this info to display these images?
I suppose there are a few ways to go here. It's hard to say which will be best, since I'm not sure what all you need to do.
- Looking at the OpenCV docs, you could use cvSaveImage(), and then load it from your code. This is probably the easiest, but also likely the slowest.
- You could encode it on the fly as an XPM, and pass that to the constructor.
- You could create a bitmap in memory, use a wxMemoryDC, and use draw_point.
I suspect that #2 may be the fastest, but it's hard to say.
Matt
3. Re: WebCam with wxEuphoria
- Posted by Jerome Mar 25, 2011
- 1385 views
Matt,
Thanks for the options! I agree that number 1 is probably the easiest and slowest. I'll try using wxMemoryDC and draw_point first since I have a decent idea of how that should work. I'm not familiar with XPM, but I noticed some examples in the wxEuphoria demos that I can play with.
Thanks,
Ira
4. Re: WebCam with wxEuphoria
- Posted by raseunew Mar 27, 2011
- 1356 views
I have been able to successfully map from an SDL image buffer
to a wxWidgets buffer and display images.
See below for code snippets.
wxWidgets requires images to be in BGR format, where
the list of bytes is a single sequence buffer.
so, an image buffer of
image = {{{R,G,B},{R,G,B},{R,G,B},{R,G,B}}, {{R,G,B},{R,G,B},{R,G,B},{R,G,B}}, {{R,G,B},{R,G,B},{R,G,B},{R,G,B}}}
would need to be 'flattened'. I think eu4 standard library
has a flatten() function
if your opencv image is RGB it will
need to be converted.
--// Convert SDL surface from RGB to BGR public enum ofsRED = 1, ofsGREEN, ofsBLUE, ofsALPHA public function RGBtoBGR(sequence rgbbuf, integer bytesPerPixel=3) --// swap B with R sequence bgrbuf = {} sequence rgb = {} integer l = length(rgbbuf) for i = 1 to l by bytesPerPixel do rgb = rgbbuf[i..(i + (bytesPerPixel - 1))] bgrbuf &= { rgb[ofsBLUE], rgb[ofsGREEN], rgb[ofsRED] } end for --// return buffer atom bgr = allocate(length( rgbbuf )) poke(bgr, bgrbuf) return bgr end function
something similar to the following will display
a BGR buffer to a wxWidgets DC.
--// convert sdl surface into wx compatible buffer -- atom bgr = RGBtoBGR(sdlcanvas, 3) /* you would probably need to flatten your image here and create your bgr surface */ atom bgr = RGBtoBGR( flatten(openCVImage), 3) --// create image from converted bgr surface atom img = wx:create(wxImage, { openCVImageWidth, openCVImageHeight, bgr }) --// free converted bgr surface free(bgr) --// create bitmap from image atom bmp = wx:create(wxBitmap,{ BM_FROM_IMAGE, img, -1 }) --// update client DC atom clientDC = wx:create(wxClientDC, this) wx:begin_drawing(clientDC) wx:draw_bitmap(clientDC, bmp, 0, 0, true) wx:end_drawing(clientDC) --// clean up wx:delete_instance(clientDC) wx:delete_instance(bmp) wx:delete_instance(img)
HTH
5. Re: WebCam with wxEuphoria
- Posted by Jerome Mar 27, 2011
- 1255 views
Thanks for the help so far! I've tried the following:
1) Saving the image to disk from OpenCV and opening the image in my EU code to display on screen
2) Drawing the individual pixel values of the image using draw_point
3) The method suggested by raseunew that creates wxImage from the pixels in memory
Method 1 is the slowest with lots of jitter in the picture. Method 2 works better but also has a noticeable lag from drawing the individual pixels. I like what raseunew suggested but I'm getting strange results. I'm working with 320 by 240 images from my webcam and using the code below, the picture shrinks and is tiled when displayed in my EU program. I thought there might be a problem with how I'm interfacing with my C++ code, but Method 2 would not work if there was a problem there. I can make things slightly better by playing with set_user_scale but this does not seem like the appropriate solution. Any help is appreciated!
- Ira
--// create image from converted bgr surface atom img = wx:create(wxImage, { openCVImageWidth, openCVImageHeight, bgr }) --// free converted bgr surface free(bgr) --// create bitmap from image atom bmp = wx:create(wxBitmap,{ BM_FROM_IMAGE, img, -1 }) --// update client DC atom clientDC = wx:create(wxClientDC, this) wx:begin_drawing(clientDC) wx:draw_bitmap(clientDC, bmp, 0, 0, true) wx:end_drawing(clientDC) --// clean up wx:delete_instance(clientDC) wx:delete_instance(bmp) wx:delete_instance(img)
6. Re: WebCam with wxEuphoria
- Posted by mattlewis (admin) Mar 28, 2011
- 1271 views
Thanks for the help so far! I've tried the following:
1) Saving the image to disk from OpenCV and opening the image in my EU code to display on screen
2) Drawing the individual pixel values of the image using draw_point
3) The method suggested by raseunew that creates wxImage from the pixels in memory
Method 2 works better but also has a noticeable lag from drawing the individual pixels.
There might be some ways to speed it up. For instance, since you're capturing video, many of the pixels may not be changing in each frame. You could possibly skip updating those. You might also detect if you have the same color pixel multiple times, and use draw_line() to reduce the number of calls. There might also be some micro optimizations possible in your euphoria code. Finally, you might compare the difference interpreted vs translated.
I like what raseunew suggested but I'm getting strange results. I'm working with 320 by 240 images from my webcam and using the code below, the picture shrinks and is tiled when displayed in my EU program. I thought there might be a problem with how I'm interfacing with my C++ code, but Method 2 would not work if there was a problem there. I can make things slightly better by playing with set_user_scale but this does not seem like the appropriate solution. Any help is appreciated!
- Ira
--// create image from converted bgr surface atom img = wx:create(wxImage, { openCVImageWidth, openCVImageHeight, bgr }) --// free converted bgr surface free(bgr) --// create bitmap from image atom bmp = wx:create(wxBitmap,{ BM_FROM_IMAGE, img, -1 })
I'm really surprised that works at all. The "data" parameter is supposed to be XPM data. If you're not familiar with XPM, there are several used in the demos. When they're created, the wxEuphoria library converts the euphoria sequences into "raw" xpm char data. It's basically an array of pointers to C strings.
You can pass the euphoria sequence versions to the wxBitmap constructor, and the library converts it, or you can convert it yourself and pass it to the wxImage constructor.
Matt