OpenCV counting cameras - c#

I am currently building an application which is able to access a number of USB webcams. I am well aware that there is no method which can count the number of camera devices on a machine, however, whenever I try to access a camera with a wrong index, I get a black image. Is there some way to use this image to denote a limit?
For example, I have two webcams. The application retrieves frames from the first camera at index 0, and from the second camera at index 1. When i increment index to 2, all I get is a black screen (obviously, since there is no 3rd camera attached).
So far the only way how to go about this is to access every single pixel in a 320x240 bitmap and check that it is black. This is not very efficient so maybe there's some other way of doing this which I am overlooking.
Thanks for your time.

An easy way would be going with openFrameworks, which has a class called ofVideoGrabber. With its listDevices() method you can list all available cams and choose the one you want to use.
Next thing you need: ofxCv is an alternative OpenCV wrapper for openFrameworks, which you can use to transfer the images grabbed by ofVideoGrabber to OpenCV or for the rest of the processing.
So you could do something like this:
// Inside Foo.h
#include "ofxCv.h"
// import namespaces for OpenCV & ofxCv
using namespace cv;
using namespace ofxCv;
// vars we need
ofVideoGrabber vidGrabber;
ofImage inputImg;
Mat matImg;
// setup video grabber
vidGrabber.setVerbose(true);
vidGrabber.setDeviceID(1); // choose the right one via vidGrabber.listDevices()
vidGrabber.initGrabber(320,240,false);
int grabW = vidGrabber.width;
int grabH = vidGrabber.height
// grab current frame
vidGrabber.grabFrame();
inputImg.setFromPixels(vidGrabber.getPixels(), 320, 240, OF_IMAGE_COLOR);
// get cv::Mat
matImg = toCv(inputImg).clone();
... further processing ...
Hope it helps!

Yes, there is method can count cameras.
you have to use directshow or directshow.net.
IEnumMoniker.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms692852%28v=vs.85%29.aspx

Related

Tango / Unity: is Tango3DRExtractWholeMesh() not actually implemented yet?

Playing with TangoDynamicMesh.cs and I'm looking for a more efficient way to get a single mesh out of the SDK. I can walk through the children and grab data out of each of their MeshFilter components but I was hoping that the Tango3DRExtractWholeMesh() function might be a better way to grab a snapshot of the current DynamicMesh. However, the docs on this one are pretty slim, does anyone know how to call this function properly? Or is this a case of a yet-to-be-implemented feature?
Yes you call it like:
private TangoApplication m_tangoApplication;
Tango3DReconstruction.Status status =
m_tangoApplication.Tango3DRExtractWholeMesh(vertices, normals, colors, triangles, out numV, out numT);
But first you must have initiated the vec3[] vertices, vec3[] normals int[] triangles, Color32[] colors and int numV, numT
I have no idea how you are supposed to know which size they are to be... and sometimes the number of triangles you get back (numT) isnt divisible by 3 which means you cannot use that data to create mesh in unity if you would want that... So I guess the function is not correct or that I am missing something...

MonoMac System.Drawing.Image.GetPropertyItem(0x5100)

Recently, I was trying to answer another SO question about loading the frames (Bitmap and duration) of animated GIFs. The code can be found on pastenbin.
While doing additional tests on this code before moving it into my dev library, I noticed that there is a problem with this line of code:
//Get the times stored in the gif
//PropertyTagFrameDelay ((PROPID) 0x5100) comes from gdiplusimaging.h
//More info on http://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
var times = img.GetPropertyItem(0x5100).Value;
When running this on Windows .Net using this (example GIF), the array is of the same size as the amount of frames in the animated GIF and filled with the durations of the frames. In this case a byte[20] which converts to (BitConverter.ToInt32()) 5 durations:
[75,0,0,0,125,0,0,0,125,0,0,0,125,0,0,0,250,0,0,0]
On MonoMac however, this line of code for the same example GIF returns a byte[4] which converts to only one duration (the first):
[75,0,0,0]
I tested this for 10 different GIF's and the result is always the same. On Windows all durations are in the byte[], while MonoMac only lists the first duration:
[x,0,0,0]
[75,0,0,0]
[50,0,0,0]
[125,0,0,0]
Looking at the Mono System.Drawing.Image source code, the length seem to be set in this method, which is a GDI wrapper:
status = GDIPlus.GdipGetPropertyItemSize (nativeObject, propid,out propSize);
However, I don't really see any problems, not with the source as with my implementation. Am I missing something or is this a bug?
I don't see anything wrong in the mono source either. It would have been helpful if you would have posted one of the sample images you tried. One quirk about the GIF image format is that the Graphics Control Extension block that contains the frame time is optional and may be omitted before an image descriptor. Non-zero odds therefore that you have GIF files that just have one GCE that applies to all the frames, you are supposed to apply the same frame time to every frame.
Do note that you didn't get 4 values, the frame time is encoded as a 32-bit value and you are seeing the little endian encoding for it in a byte[]. You should use BitConverter.ToInt32(), as you correctly did in your sample code.
I therefore think you should probably use this instead:
//convert 4 bit value to integer
var duration = BitConverter.ToInt32(times, 4*i % times.Length);
Do note that there's another nasty implementation detail about GIF frames, frames #2 and up do not have to be the same size as the frame #1. And each frame has a metadata field that describes what should be done with the previous frame to merge it with the next one. There are no property IDs that I know of to obtain the frame offset, size and undraw method for each frame. I think you need to render each frame into a bitmap yourself to get a proper sequence of images. Very ugly details, GIF needs to die.
If you look into libgdiplus you will see that the properties are always read from the active bitmap:
if (gdip_bitmapdata_property_find_id(image->active_bitmap, propID, &index) != Ok) {
You can set the active bitmap by calling Image.SelectActiveFrame and then mono will return the correct durations, one by one. Since this is an incompatibility with windows, I'd call it a mono bug. As a simple workaround, you can of course just check the array length and handle both cases. This will be better than a check for mono, because if mono gets fixed this will continue to work.

A function like "glReadPixels" in DirectX / SharpDX

I'm searching for a way to read a pixels color at the mousepoint. In OpenGL it was done by calling the function "glReadPixels" after drawing the scene (or parts of it). I want to make a simple color picking routine in the background, for identifing a shapes / lines in 3D Space.
So, is there any equivalent method/function/suggestion for doing the same in SharpDX (DirectX10 / DirectX11) ?
This is perfectly possible with Direct3D11: simply follow these steps:
Use DeviceContext.CopySubResourceRegion to copy part from the source texture to a staging texture (size of the pixel area you want to readback, same format, but with ResourceUsage.Staging)
Retrieve the pixel from this staging texture using Device.Map/UnMap.
There is plenty of discussion about this topic around the net (for example: "Reading one pixel from texture to CPU in DX11")
Another option is to use a small compute shader, like :
Texture2D<float4> TextureInput: register(t0);
StructuredBuffer<float2> UVBuffer: register(t1);
RWStructuredBuffer<float4> RWColorBuffer : register(u0);
SamplerState Sampler : register( s0 );
[numthreads(1, 1, 1)]
void CSGetPixels( uint3 DTid : SV_DispatchThreadID )
{
float4 c = TextureInput.SampleLevel(Sampler , UVBuffer[DTid.x].xy, 0);
RWColorBuffer [DTid.x] = c;
}
It gives you the advantage of being a bit more "format agnostic".
Process is then like that.
Create a small structured buffer for UV (float2) (pixel position/texture size, don't forget to flip Y axis of course). Copy the pixel position you want to sample into this buffer.
Create a writeable buffer and a staging buffer (float4). Needs to be same element count as your uv buffer.
Bind all and Dispatch
Copy writeable buffer into the staging one.
Map and read float4 data in cpu
Please note I omitted thread group optimization/checks in compute shader for simplicity.
Since you're using C#, my suggestion would be to use GDI+, as there is no such function like "glReadPixels" in DX. GDI+ offers very easy methods of reading the color of a pixel at your mouse pointer. Refer to stackoverflow.com/questions/1483928.
If GDI+ is a no go, as it isn't very fast, can't you stick to the usual object picking using a "Ray"? You want to identify (I suppose 3-dimensional) shapes/lines, this would be easy using a ray (and check for intersection) to pick them.

fastest method to capture game screen shots in c#?(more than20 images per second)

How can i make screenshoots to the entire game screen very fast? Somthing like 20-30 per second?(i want to convert them to video)
[[1]]
I've tried WMEncoder.Results were that WMEncoder can capture the screen and regions of screen only in a video format (wma) using a set of preconfigured codecs. (29 fps best encode result).WMEncoder can not make screenshots.
[[2]]
I've tried DirectX :
Surface s = device.CreateOffscreenPlainSurface(
Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
Format.A8R8G8B8, Pool.SystemMemory);
device.GetFrontBufferData(0, s);
SurfaceLoader.Save("c:\\Screenshot"+i.ToString()+".bmp", ImageFileFormat.Bmp, s);
This works like gdi ..very slow....and it works only in DirectX 1.0 because SurfaceLoader does not exist in directX 2.0
Another way that i've read in some post is using :
s = device.GetBackBuffer(0, 0, Microsoft.DirectX.Direct3D.BackBufferType.Mono);
, but this maks screenshots only to the curent window.
[[3]]
I've tried to use Taksi (at sourceforge.net)... but i don't know how to use it in c# and make it work.
Please help me out...
You really want to hook into directx so you can make the calls as if you were that game/application. Below are a few sites that do this (most draw extra things, but i don't see why you couldn't save the backbuffer every x frames):
http://www.gamedev.net/topic/359794-c-direct3d-hooking-sample/
Disclamer: I've not tried this, so not sure what FPS you can get, however i would think this is the fastest method as you're doing it effectively from within the game.

Perspective Image Distortion

The application I am working on currently requires functionality for Perspective Image Distortion. Basically what I want to do is to allow users to load an image into the application and adjust its perspective view properties based on 4 corner points that they can specify.
I had a look at ImageMagic. It has some distort functions with perpective adjustment but is very slow and some certain inputs are giving incorrect outputs.
Any of you guys used any other library or algorithm. I am coding in C#.
Any pointers would be much appreciated.
Thanks
This seems to be exactly what you (and I) were looking for:
http://www.codeproject.com/KB/graphics/YLScsFreeTransform.aspx
It will take an image and distort it using 4 X/Y coordinates you provide.
Fast, free, simple code. Tested and it works beautifully. Simply download the code from the link, then use FreeTransform.cs like this:
using (System.Drawing.Bitmap sourceImg = new System.Drawing.Bitmap(#"c:\image.jpg"))
{
YLScsDrawing.Imaging.Filters.FreeTransform filter = new YLScsDrawing.Imaging.Filters.FreeTransform();
filter.Bitmap = sourceImg;
// assign FourCorners (the four X/Y coords) of the new perspective shape
filter.FourCorners = new System.Drawing.PointF[] { new System.Drawing.PointF(0, 0), new System.Drawing.PointF(300, 50), new System.Drawing.PointF(300, 411), new System.Drawing.PointF(0, 461)};
filter.IsBilinearInterpolation = true; // optional for higher quality
using (System.Drawing.Bitmap perspectiveImg = filter.Bitmap)
{
// perspectiveImg contains your completed image. save the image or do whatever.
}
}
Paint .NET can do this and there are also custom implementations of the effect. You could ask for the source code or use Reflector to read it and get an idea of how to code it.
If it is a perspective transform, you should be able to specify a 4x4 transformation matrix that matches the four corners.
Calculate that matrix, then apply each pixel on the resulting image on the matrix, resulting in the "mapped" pixel. Notice that this "mapped" pixel is very likely going to lie between two or even four pixels. In this case, use your favorite interpolation algorithm (e.g. bilinear, bicubic) to get the interpolated color.
This really is the only way for it to be done and cannot be done faster. If this feature is crucial and you absolutely need it to be fast, then you'll need to offload the task to a GPU. For example, you can call upon the DirectX library to apply a perspective transformation on a texture. That can make it extremely fast, even when there is no GPU because the DirectX library uses SIMD instructions to accelerate matrix calculations and color interpolations.
Had the same problem. Here is the demo code with sources ported from gimp.
YLScsFreeTransform doesn't work as expected. Way better solution is ImageMagic
Here is how you use it in c#:
using(MagickImage image = new MagickImage("test.jpg"))
{
image.Distort(DistortMethod.Perspective, new double[] { x0,y0, newX0,newY0, x1,y1,newX1,newY1, x2,y2,newX2,newY2, x3,y3,newX3,newY3 });
control.Image = image.ToBitmap();
}

Categories

Resources