Using BlobTrackerAuto to track people in computer vision application - opencv

I am currently trying to develop a system that tracks people in a queue using EmguCV (OpenCV Wrapper). I started by running and understanting the VideoSurveilance example that's in Emgu package I downloaded. Here is my code based on the example:
private static void processVideo(string fileName)
{
Capture capture = new Capture(fileName);
MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_SIMPLEX,
1.0, 1.0);
BlobTrackerAuto<Bgr> tracker = new BlobTrackerAuto<Bgr>();
//I'm using a class that I implemented for foreground segmentation
MyForegroundExtractor fgExtractor = new MyForegroundExtractor();
Image<Bgr, Byte> frame = vVideo.QueryFrame();
fgExtractor.initialize(frame);
while (frame != null)
{
Image<Gray, Byte> foreground = fgExtractor.getForegroundImg(frame);
tracker.Process(frame, foreground);
foreach (MCvBlob blob in tracker)
{
if (isPersonSize(blob))
{
frame.Draw((Rectangle)blob, new Bgr(0, 0, 255), 3);
frame.Draw(blob.ID.ToString(), ref font,
Point.Round(blob.Center), new Bgr(255.0, 255.0, 255.0));
}
}
CvInvoke.cvShowImage("window", frame);
CvInvoke.cvWaitKey(1);
frame = capture.QueryFrame();
}
}
The above code is meant to process each frame of an AVI Video, and show the processed frame with red rectangles around each person in scene. I didn't like the results I was getting using the IBGFGDetector<Bgr> class that is used in VideoSurveilance example, so I am trying to use my own foreground detector, using Emgu's functions such as CvInvoke.cvRunningAvg(), CvInvoke.cvAbsDiff(), CvInvoke.cvThreshold() and cvErode/cvDilate(). I have a few issues:
The video starts with a few people already in the scene. I am not getting the blobs corresponding to the people that are in the scene when the video starts.
Sometimes I "lose" a person for a few frames: I had the red rectangle drawn around a person for several seconds/frames and it disappears and after a while is drawn again with a different ID.
As you can see from the sample code, I check if the blob may be a person checking its height and width (isPersonSize() method), and draw the red rectangle only in the ones that pass in the test. How can I remove the ones that are not person sized?
I want to measure the time a person stays in the scene. What's the best way to know when a blob disappeared? Should I store the IDs of the blobs that I think correspond to people in an array and at each loop check if each one is still there using tracker.GetBlobByID()?
I think I am getting better results if I don't process every frame in the loop. I added a counter variable and an if-statement to process at every 3 frames:
if (i % 3 == 0)
tracker.Process(frame, foreground);
I added the if-statement because the program execution was really slow. But when I did that, I was able to track people that I wasn't able before.
To summarize, I would really appreciate if someone that is more used to OpenCV/EmguCV helped me by saying if it is a good approach to track people using BlobTrackerAuto, and by helping me with the issues above. I get the feeling that I am not taking advantage of the tools EmguCV can provide me.

Related

how draw foreground in flame_tiled

I need help to draw map created from Tiled (.tmx)
version info
flame: 1.5.0
flame_tiled: 1.9.0
what I want is to draw background first, then player, then foreground.
I have 4 layer for now,
foreground (tile layer) (top layer).
spawn (object layer).
housing (tile layer).
land (tile layer).
already working with drawing background and player and foreground with this code. but I need to save 2 file of map data.
final currentMap = await TiledComponent.load(
'$mapName.tmx',
Vector2.all(16),
);
add(currentMap);
final spawnPointObject = currentMap.tileMap.getLayer<ObjectGroup>('spawn');
for (final spawnPoint in spawnPointObject!.objects) {
final positions = Vector2(
spawnPoint.x + (spawnPoint.width / 2),
spawnPoint.y + (spawnPoint.height / 2),
);
switch (spawnPoint.class_) {
case 'player':
_player = MyPlayer(
anchor: Anchor.center,
current: 'idle',
position: positions,
size: Vector2.all(16),
name: name,
);
add(_player);
break;
}
}
final currentForeground = await TiledComponent.load(
'${mapName}_foreground.tmx',
Vector2.all(16),
);
add(currentForeground);
I can draw from object layer, but take soo much case will be hard for update later..
so is there any way to draw only 1 layer with flame_tiled.?
this is sample image, I want my player to draw behing the roof when played.
image
- already try with layer object and drawing base on object id, one by one. but take so much effort.
- try with 2 save file, but still hard to maintain (used now)
My personal conclusion about this problem is that flame_tiled is not flexible enough, so the best thing it can do for you is to parse map files. If you need a flexible rendering, you going to implement it on your side, because flame_tiled renders everything as a big flat batch of sprites.
Probably you can do a fast hack by rendering the RenderableTiledMap twice. At first pass you disable "roof" map's layers (see "setLayerVisibility" function) and renders everything into a Picture / Image and wraps it into a component with "ground" priority.
Than you enable "roof" layer and disable "ground", then do the same rendering into another Picture / Image and wraps it into another component with "roof" priority.
Trying to solve this problem, I have made two solutions. One is simpler, another is more complicated and still in development / debug stage:
https://pub.dev/packages/flame_tiled_utils - with this you can render every map's tile as a component into separate layer with given priority. Exactly what you want, but you need to create some additional classes to describe your map's tile types.
https://github.com/ASGAlex/flame_spatial_grid - allows to do the same, but with better abstraction level. Also helps to avoid problems of the previous library (slow rendering on large maps). But it is still in heavy development, sometimes I broke something, sometimes fix...
Sorry for such "longread" answer =)

Stiching top down photos of long items using OpenCV

I'm working on a project that includes taking top-down photos from three stationary cameras mounted above a long white table. Long packs of veneer are placed on the table to be photographed. The three images then need to be stitched together. The goal is to achieve a smooth transition on the border. I'm trying to use OpenCV to achieve this, but I'm running into problems. The images are either stitched with huge overlap and distortion or, most commonly, just give an "assertion failed" error. I've tried using both "panorama" and "scans" modes to no avail. I'm using the Emgu.CV.NET wrapper, but the logic behind it should be the same.
The reason I'm not joining images manually is due to slight chromatic distortions towards the edges of images, which cause the pack size to slightly differ in the place where the connection should be. Also, the exact position of cameras may shift over time, causing further shifts. I was hoping the existing algorithms could fix that.
Am I using the stitcher wrongly, or is it unfit for this task? Can someone recommend other tools or methods for this problem?
Here's example images, which error out the stitcher.
(Click to see full-size versions)
Code used:
class ImageStitching
{
public static Mat StichImages(List<Mat> images)
{
Mat output = new Mat();
VectorOfMat matVector = new VectorOfMat();
foreach (Mat img in images)
{
matVector.Push(img);
}
Stitcher stitcher = new Stitcher(Emgu.CV.Stitching.Stitcher.Mode.Scans);
Brisk detector = new Brisk();
stitcher.SetFeaturesFinder(detector);
stitcher.Stitch(matVector, output);
return output;
}
}

How to make an in-game button (with text) in Phaser?

I have made a PNG image which will be my button background. In the preload() of my relevant state I load that image. I want a way to have this image placed in the world and be able to set text onto it (and also be clickable but I guess that's a bit unimportant here because I know how to set up event handlers).
I thought I could manage something with
Text text = new Text(x,y,foo,style);
text.texture = <something>
but trying to, for example, create a new Texture() shows a warning "undefined class Texture" in DartEditor, and anyway (as far as I can tell?) Texture doesn't seem to allow giving a source image key/URL..
So could anyone with Phaser experience tell me how I can get an in-game button as I want?
I currently seem to have achieved more or less what I wanted (may have to tweak some values here and there but generally seems alright) with code like this
class MyState
{
preload() {
//...
game.load.image('key','$assetPath/button.png');
//...
}
create() {
Sprite temp2;
temp2 = new Sprite(this.game, x, y, 'button');
BitmapData bmp = game.add.bitmapData(temp2.width, temp2.height);
bmp.draw(temp2);
//Text positioning x,y in fillText() is just my choice of course
bmp.ctx.fillText('Wait', bmp.width / 2, bmp.height / 2);
game.add.sprite(game, someX, someY, bmp);
}
}
EDIT: For what I'm doing there adding the bitmap to game cache wasn't needed; must've been something I was trying when trying to figure it out and forgot to delete.
So I needed to use the BitmapData class. My only little concern with this (although I'm not sure it really is an issue) is how when I create the Sprite temp2 I am giving it a position but of course it is not used in the game, rather the output of drawing the sprite, and then text on top, to bmp is added as a sprite to the game. Does anyone know if there are any real implications of creating that first Sprite and leaving it like so? I'm just wondering because visually it appears it is not an issue since it is not appearing in the "game world".
Also, while this method seems just fine for me at the moment I'm curious as to whether there other ways, like something else that is somehow better and/or more preferred?

Using JavaCV to display live image from camera

I am using JavaCV for on-the-fly image processing from a webcam. It works great! I can define a region of interest in the picture and crop every image before displaying and it'll still do a full 30 frames per second without problems. Nice!
However, I'm using a CanvasFrame object to display the live image. It works great (and easy), but is TOTALLY USELESS for including in an application. I want to put the live image on a panel (or canvas or whatever) as one element of my application window.
The problem: A CanvasFrame lives in its own frame and disappears behind my window when my window gets focus, and also doesn't move when I move my window.
How can I get the live image onto an element that I can integrate with my normal UI elements?
Again, I need a replacement for CanvasFrame in JavaCV. TIA.
I start a camera thread that grabs in a loop and draws on the CanvasFrame until a UI button is pressed. THIS WORKS FINE.
In response to the UI button press, I stop the thread (which triggers grabber.stop). Then I take the last image, and display that image on a panel. THIS WORKS FINE (I know how to display an image, thanks). I'd be done except CanvasFrame is a separate window which kinda sucks.
So instead I want to start a camera thread that grabs in a loop and does NOT draw on a CanvasFrame. Instead it just keeps an internal copy of the last image. Then to display on my UI, I set a timer (which fires correctly) and just display the latest image on my panel. THIS DOES NOT WORK--the panel remains blank. And yet, how is this case any different from the case that works? The only difference is that the grabber in the camera thread has not been stopped yet. It's fine when the camera is NOT in its grabbing loop, but will NOT display when it is looping. And I'm careful to make cvCopy's of the images I pass to the UI, so there's no problem with contention for the memory.
I will also say that displaying on the CanvasFrame in a loop seems to trigger my Logitech C920 auto-focus, whereas just grabbing a single image and displaying it (which I can do easily as long as the grabber is stopped) does NOT seem to auto-focus.
The upshot is CanvasFrame seems to be doing lots of tricky stuff in the backgraound which cannot be matched by just having grabber.start, grabber.grab, grabber.stop, then display on your own panel.
Sam, I've seen your name in the CanvasFrame source code, so you should know better than anyone what's the difference between my 2 scenarios.
I was looking for a replacement for CanvasFrame that can be used in any UI and now I have one. Here it is, a swing element that can display a live (or still) image:
import java.awt.Graphics;
import java.awt.image.*;
import javax.swing.JPanel;
public class CamImagePanel extends JPanel {
private BufferedImage image;
public CamImagePanel() {
super();
// Note that at this point, image = null
// so be sure to call setImage() before setVisible(true)
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) // Not efficient, but safer.
g.drawImage(image, 0, 0, this);
}
public void setImage(BufferedImage img) {
image = img;
repaint();
}
}
Then, I set a timer in my main event thread to wake up 20 to 30 times per second (30-50 ms) and in the alarm callback method, I simply call mypanel.setImage(latestPhoto); and it's just like a live image.
I have a controller object with it's own thread which fills a buffer with an image from the camera as fast as it can, and I just ask the controller for the latest image. This way, synchronizing isn't required, I can actually ask for the images faster or slower than the camera can make them, and my logic still works fine.
A button on the UI stops the timer and I can leave up the final image on the panel or take the panel down completely with setVisible(false).

Dynamically alter or destroy a Texture2D for drawing and collision detection

I am using XNA for a 2D project. I have a problem and I don't know which way to solve it. I have a texture (an image) that is drawn to the screen for example:
|+++|+++|
|---|---|
|+++|+++|
Now I want to be able to destroy part of that structure/image so that it looks like:
|+++|
|---|---|
|+++|+++|
so that collision now will work as well for the new image.
Which way would be better to solve this problem:
Swap the whole texture with another texture, that is transparent in the places where it is destroyed.
Use some trickery with spriteBatch.Draw(sourceRectangle, destinationRectangle) to get the desired rectangles drawn, and also do collision checking with this somehow.
Split the texture into 4 smaller textures each of which will be responsible for it's own drawing/collision detection.
Use some other smart-ass way I don't know about.
Any help would be appreciated. Let me know if you need more clarification/examples.
EDIT: To clarify I'll provide an example of usage for this.
Imagine a 4x4 piece of wall that when shot at, a little 1x1 part of it is destroyed.
I'll take the third option:
3 - Split the texture into 4 smaller
textures each of which will be
responsible for it's own
drawing/collision detection.
It's not hard do to. Basically it's just the same of TileSet struct. However, you'll need to change your code to fit this approach.
Read a little about Tiles on: http://www-cs-students.stanford.edu/~amitp/gameprog.html#tiles
Many sites and book said about Tiles and how to use it to build game worlds. But you can use this logic to everything which the whole is compost from little parts.
Let me quick note the other options:
1 - Swap the whole texture with
another texture, that is transparent
in the places where it is destroyed.
No.. have a different image to every different position is bad. If you need to change de texture? Will you remake every image again?
2- Use some trickery with
spriteBatch.Draw(sourceRectangle,
destinationRectangle) to get the
desired rectangles drawn, and also do
collision checking with this somehow.
Unfortunately it's don't work because spriteBatch.Draw only works with Rectangles :(
4 Use some other smart-ass way I don't
know about.
I can't imagine any magic to this. Maybe, you can use another image to make masks. But it's extremely processing-expensive.
Check out this article at Ziggyware. It is about Deformable Terrain, and might be what you are looking for. Essentially, the technique involves settings the pixels you want to hide to transparent.
Option #3 will work.
A more robust system (if you don't want to be limited to boxes) would use per-pixel collision detection. The process basically works as follows:
Calculate a bounding box (or circle) for each object
Check to see if two objects overlap
For each overlap, blit the sprites onto a hidden surface, comparing pixel values as you go. If a pixel is already set when you try to draw the pixel from the second sprite, you have a collision.
Here's a good XNA example (another Ziggyware article, actually): 2D Per Pixel Collision Detection
Some more links:
Can someone explain per-pixel collision detection
XNA 2-d per-pixel collision
I ended up choosing option 3.
Basically I have a Tile class that contains a texture and dimention. Dimention n means that there are n*n subtiles within that tile. I also have an array that keeps track of which tiles are destroyed or not. My class looks like this in pseudo code:
class Tile
texture
dimention
int [,] subtiles; //0 or 1 for each subtile
public Tile() // constructor
subtiles = new int[dimention, dimention];
intialize_subtiles_to(1);
public Draw() // this is how we know which one to draw
//iterate over subtiles
for(int i..
for(int j ...)
if(subtiles[i,j] == 1)
Vector2 draw_pos = Vector2(i*tilewidth,
j*tileheight)
spritebatch.Draw(texture, draw_pos)
In a similar fashion I have a collision method that will check for collision:
public bool collides(Rectangle rect)
//iterate over subtiles
for i...
for j..
if(subtiles[i,j]==0) continue;
subtile_rect = //figure out the rect for this subtile
if(subtile_rect.intersects(rect))
return true;
return false;
And so on. You can imagine how to "destroy" certain subtiles by setting their respective value to 0, and how to check if the whole tile is destroyed.
Granted with this technique, the subtiles will all have the same texture. So far I can't think of a simpler solution.

Resources