Comparing bitmap data in AS3 pixel for pixel - apache-flex

I am looking for a fairly simple image comparison method in AS3. I have taken an image from a web cam (with no subject) passed it in to bitmap data, then a second image is taken (this time with a subject) to compare this data, from these two images I would like to create a mask from the pixels that match on both bitmaps. I have been scratching my head for a while, and I am not really making any progress. Could any one point me in the right direction for pixel comparison method, something like getPixel32()
Cheers
Jono

use compare to create a difference between the two and then use treshold to extract the parts that interest you.
edit: actually it is pretty straight forward. the trick is to apply the threshold multiple times per channel using the mask parameter (otherwise the comparison only makes little sense, since 0x010000 (which is almost black) is consider greater than 0x0000FF (which is anything but black)). here's how:
var dif:BitmapData;//your original bitmapdata
var mask:BitmapData = new BitmapData(dif.width, dif.height, true, 0);
const threshold:uint = 0x20;
for (var i:int = 0; i < 3; i++)
mask.threshold(dif, dif.rect, new Point(), ">", threshold << (i * 8), 0xFF000000, 0xFF << (i * 8));
this creates a transparent mask. then the threshold is applied for all three channels, setting the alpha channel to fully opaque where the channels value exceeds the threshold value (you might wanna decrease it).
you can isolate the foreground object ("the guy in front of the webcam") by copying the alpha channel from the mask to the current video image.

one of the problems here is that you want to find if a pixel has ANY change to it, and if it does then to convert that pixel to another color (for masking). Unfortunately, a webcam's quality isn't great so even if your scene does not change at all the bitmapdata coming from the webcam will change slightly. Therefor, when your subject steps into frame...you will get pixel changes for the subject...but also noise in other areas due to lighting changes or camera quality. What you'll need to do is write a function that analyzes the result of a bitmapdaya.compare() for change in area's larger than _____ to determine if there is enough change to warrant an actual object being there. That will help remove noise and make your mask more accurate.

Related

TriangleMesh with a partially transparent material gives an unexpected result

Recently, i tried to make transparency work in JavaFX 3D as some of the animations i want to play on meshes use transforms that change the alpha of the mesh each keyframe.
However to my surprise, my TriangleMesh that uses a material which has transparent areas doesn't look as expected.
Current result(depth buffer enabled): https://i.imgur.com/EIIWY1p.gif
Result with depth buffer disabled for my TriangleMeshView: https://i.imgur.com/1C95tKy.gif (this looks much closer to the result i was expecting)
However i don't really want to disable depth buffering because it causes other issues.
In case it matters, this is the diffuse map i used for my TriangleMesh: https://i.imgur.com/UqCesXL.png (1 pixel per triangle as my triangles have a color per face, 128 pixels per column).
I compute UV's for the TriangleMesh like this:
float u = (triangleIndex % width + 0.5f) / width;
float v = (triangleIndex / width + 0.5f) / (float) atlas.getHeight();
and then use these for each vertex of the triangle.
What's the proper way to render a TriangleMesh that uses a transparent material(in my case only part of the image is transparent, as some triangles are opaque)?
After a bit of research, i've found this which potentially explains my issue: https://stackoverflow.com/a/31942840/14999427 however i am not sure whether this is what i should do or whether there's a better option.
Minimal reproducible example(this includes the same exact mesh i showed in my gifs): https://pastebin.com/ndkbZCcn (used pastebin because it was 42k characters and the limit in stackoverflow is 30k) make sure to copy the raw data as the preview in pastebin stripped a few lines.
Update: a "fix" i found orders the triangles every time the camera moves the following way:
Take the camera's position multiplied by some scalar(5 worked for me)
Order all opaque triangles first by their centroids distance to the camera and then after that order all transparent triangles the same way.
I am not sure why multiplying the camera's position is necessary but it does work, best solution i've found so far.
I have not yet found a 'proper fix' for this problem, however this is what worked for me pretty well:
Create an ArrayList that'll store the sorted indices
Take the Camera's position multiplied by some scalar (between 5-10 worked for me), call that P
Order all opaque triangles first by their centroids distance to P and add them to the list
Order all triangles with transparency by their centroids distance to P and add them to the list
Use the sorted triangle indices when creating the TriangleMesh

XNA FBX model drawing problems, it's either my code, the way I export models or the way content is exported

So basically when I try to draw more a mesh inside an FBX file its orientation is always removed and it's scaled down. I'm not sure if the issue is caused by code or the way I'm exporting the FBX files. I have been trying to narrow down the cause and I am fairly sure it's not caused by the way I export the FBX (but I could be wrong), so it's either the XNA content pipeline or my drawing code
Here are some pics I took to show my problem, where the gray background is in 3Ds Max as I see it and red background is in XNA:
THis is as it appears in 3D StudioMax: http://i.stack.imgur.com/e0oW4.png
This is how it appears in XNA: http://i.stack.imgur.com/1vOcx.png
Both are being viewed from the same angle and direction but varying distances.
Now what is really odd is if I create another mesh in max, say a box, and export that (along with the original model), it works fine: http://i.stack.imgur.com/SIDg9.png
So long as there is more than one mesh in the fbx model it draws properly (though I'm still suspicious if it's drawing with proper scaling applied, i.e. if in Max it is 1 unit long in XNA it becomes something like 1.27 units long), if there is less its orientation which I applied to it in 3D studio max is removed when I draw it.
This is how I draw the model:
model.CopyAbsoluteBoneTransformsTo(boneTransforms);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = boneTransforms[mesh.ParentBone.Index];
Vector3 cameraPosition = Camera.Get.Position;// new Vector3(0, 0, 0);
//cameraPosition.X = -Camera.Get.PosX;
//cameraPosition.Y = Camera.Get.PosY;
effect.View = Camera.Get.View;// Matrix.CreateLookAt(cameraPosition, cameraPosition + Camera.Get.LookDir, Camera.Get.Up);
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
BaseGame.Get.GraphicsDevice.Viewport.AspectRatio,
0.01f, 1000000); //Matrix.CreateOrthographic(800 / 1, 480 / 1, 0, 1000000);
//effect.TextureEnabled = true;
effect.LightingEnabled = true;
effect.PreferPerPixelLighting = true;
//effect.SpecularColor = new Vector3(1, 0, 0);
}
mesh.Draw();
}
Obviously mesh.draw() is called twice when there is more than one mesh in the fbx file..
Generally if you are having a problem with the position or scale of the mesh while rendering, then it's likely to be related to the matrices. Not necessarily the exporting, but rather how you use them in the code.
I use blender3d for modelling, but I know that Blender3d actually defines different spaces when you are creating the meshes within the editor. For example, if you create a mesh while in 'object' mode, the position/rotation/scale of the object in the scene will not be exported (because that object will be the root of a new tree, centered around 0,0,0). So I would check for a similar situation in 3DMax - make sure you are transforming the vertices in Max relative to 0,0,0, or else you may lose the 'initial' translation and when you render in XNA, all the objects will be rendered around your 0,0,0 (i.e. appear mixed together).
Failing that, and I can't remember exactly off the top of my head, but I think you may need to multiply the current mesh's absolute matrix transform with that of the parent's world matrix transform. Although it's been a while so I'm not too sure.

How to randomly but evenly distribute nodes on a plane

I need to place 1 to 100 nodes (actually 25px dots) on a html5 canvas. I need to make them look randomly distributed so using some kind of grid is out. I also need to ensure these dots are not touching or overlapping. I would also like to not have big blank areas. Can someone tell me what this kind of algorithm is called? A reference to an open source project that does this would also be appreciated.
Thanks all
Guido
What you are looking for is called a Poisson-disc distribution. It occurs in nature in the distribution of photoreceptor cells on your retina. There is a great article about this by Mike Bostock (StackOverflow profile) called Visualizing Algorithms. It has JavaScript demos and a lot of code to look at.
In the interest of doing more then dropping a link into the answer, I will try to give a brief summary of the article:
Mitchell's best-candidate algorithm
A simple approximation known as Mitchell’s best-candidate algorithm. It is easy to implement both crowds some spaces and leaves gaps in other. The algorithm adds new points one at a time. For each new sample, the best-candidate algorithm generates a fixed number of candidates, say 10. The point furthest from any other point is added to the set and the process is repeated until the desired density is achieved.
Bridson's Algorithm
Bridson’s algorithm for Poisson-disc sampling (original paper pdf) scales linearly and is easy to implement as well. This algorithm grows from an initial point and (IMHO) is quite fun to watch (again see Mike Bostock's article). All points in the set are either active or inactive. all points are added as active. One point is chosen from the active set and some number of candidate points are generated in the annulus (a.k.a ring) that extends from the sample with the inner circle having a radius r and the outer circle having a radius 2r. Candidate sample less then r distance away from any point in the FinalSet are rejected. Once a sample is found that is not rejected it is added the the FinalSet. If all the candidate sample are rejected the original point is marked as inactive on the assumption that is has so many neighboring points that no more can be added around it. When all samples are inactive the algorithm terminates.
A grid of size r/√2 can be used to greatly increase the speed of checking candidate points. Only one point may ever be in a grid square and only a limited number of adjacent squares need to be checked.
The easiest way would be to just generate random (x, y) coordinates for each one, repeating if they are touching or overlapping.
Pseudocode:
do N times
{
start:
x = rand(0, width)
y = rand(0, height)
for each other point, p
if distance(p.x, p.y, x, y) < radius * 2
goto start
add_point(x, y);
}
This is O(n^2), but if n is only going to be 100 then that's fine.
I don't know if this is a named algorithm, but it sounds like you could assign each node a position on a “grid”, then pick a random offset. That would give the appearance of some chaos while still guaranteeing that there are no big empty spaces.
For example:
node.x = node.number / width + (Math.random() - 0.5) * SOME_SCALE;
node.y = node.number % height + (Math.random() - 0.5) * SOME_SCALE;
Maybe you could use a grid of circles and place one 25px-dot in every circle? Wouldn't really be random, but look good.
Or you could place dots randomly and then make empty areas attract dots and give dots a limited-range-repulsion, but that is maybe too complicated and takes too much CPU time for this simple task.

ActionScript 3.0 : How to access a Shape's segments? [duplicate]

This question already has an answer here:
Can I get vector data back out out of a Graphics object?
(1 answer)
Closed 9 years ago.
EDIT (for clarification):
I have a vector image with a simple contour, an irregular closed polygon.
I need to import it into Flash in a way that I can then programmatically access each of the segments that form the polygon.
Importing the vector image into the library as a MovieClip wasn't good because all I get is a shape from which I can take no geometry information at all.
My goal is being able to calculate the polygon's area and also calculating the intersection between the polygon and another polygon.
I guess I could write an Illustrator script that reads all the segments and writes a CSV files with their coordinates, but there has to be a simpler way, I mean, they're both vectorial, they should understand each other.
Thanks!
.
-- Old Post: --
I have a contour in vector graphics that I imported to the Flash library as a movieclip.
I Instanciate the movieclip and it has a Shape child which is the actual contour.
I need to be able to access the contour segments, i.e. the polygon's sides, to be able to get their starting and ending points, is there a way?
the Graphics class only allows to draw but what you draw, as with the Shape class, are not objects, it's not a polygon with sides or whatever.
Am I being clear?
Thanks
There is no way to read the data of a Graphics object (which is essentially what contains the information that you are after.) This applies to any vector graphics object that has already been drawn, either by the Graphics/drawing API itself, or in Flash CS3/CS4, or was embedded using the [Embed] meta-tag.
Your best bet if you need to calculate the algebraic area, or for some other reason retain the vectors in your algorithms, is definitely exporting an SVG or some single-purpose format (like a CSV of the points) from Illustrator, and parsing that in ActionScript.
Another option is to use a BitmapData, and draw the Shape object onto that, then counting the colored (opaque) pixels to numerically calculate it's area.
var bmp : BitmapData = new BitmapData(myShape.width, myShape.height, true, 0);
bmp.draw(myShape);
var i : uint;
var area : uint = 0;
var num_pixels : uint = bmp.width*bmp.height;
for (i=0; i<num_pixels; i++) {
var px : uint = bmp.getPixel32(i%bmp.width, Math.floor(i/bmp.height));
// Determine from px color/alpha whether it's part of the shape or not.
// This particular if statement should determine whether the alpha
// component (first 8 bits of the px integer) are greater than zero, i.e.
// not transparent.
if ((px >> 24) > 0)
area++;
}
trace('number of opaque pixels (area): '+area);
Depending on your application, you might also be able to use the BitmapData.hitTest() method for your collision detection.
I believe the best you can do is to retrieve a rectangular bounding box on the Shape object. Depending on how you imported it, you may or may not have direct access to the Shape object as an instance variable; however, if you do, you can call shapeVar.transform.getBounds() or shapeVar.transform.getRect() (bounds returns a rectangle inclusive of strokes on the shape, rect does not).
I'm curious, so I'm doing a bit of research on alternate means of getting some pixel bounds. I'll edit this further if I find something useful.

How do I rotate an image?

See also: Why is my image rotation algorithm not working?
This question isn't language specific, and is a math problem. I will however use some C++ code to explain what I need as I'm not experienced with the mathematic equations needed to express the problem (but if you know about this, I’d be interested to learn).
Here's how the image is composed:
ImageMatrix image;
image[0][0][0] = 1;
image[0][1][0] = 2;
image[0][2][0] = 1;
image[1][0][0] = 0;
image[1][1][0] = 0;
image[1][2][0] = 0;
image[2][0][0] = -1;
image[2][1][0] = -2;
image[2][2][0] = -1;
Here's the prototype for the function I'm trying to create:
ImageMatrix rotateImage(ImageMatrix image, double angle);
I'd like to rotate only the first two indices (rows and columns) but not the channel.
The usual way to solve this is by doing it backwards. Instead of calculating where each pixel in the input image ends up in the output image, you calculate where each pixel in the output image is located in the input image (by rotationg the same amount in the other direction. This way you can be sure that all pixels in the output image will have a value.
output = new Image(input.size())
for each pixel in input:
{
p2 = rotate(pixel, -angle);
value = interpolate(input, p2)
output(pixel) = value
}
There are different ways to do interpolation. For the formula of rotation I think you should check https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions
But just to be nice, here it is (rotation of point (x,y) angle degrees/radians):
newX = cos(angle)*x - sin(angle)*y
newY = sin(angle)*x + cos(angle)*y
To rotate an image, you create 3 points:
A----B
|
|
C
and rotate that around A. To get the new rotated image you do this:
rotate ABC around A in 2D, so this is a single euler rotation
traverse in the rotated state from A to B. For every pixel you traverse also from left to right over the horizontal line in the original image. So if the image is an image of width 100, height 50, you'll traverse from A to B in 100 steps and from A to C in 50 steps, drawing 50 lines of 100 pixels in the area formed by ABC in their rotated state.
This might sound complicated but it's not. Please see this C# code I wrote some time ago:
rotoZoomer by me
When drawing, I alter the source pointers a bit to get a rubber-like effect, but if you disable that, you'll see the code rotates the image without problems. Of course, on some angles you'll get an image which looks slightly distorted. The sourcecode contains comments what's going on so you should be able to grab the math/logic behind it easily.
If you like Java better, I also have made a java version once, 14 or so years ago ;) ->
http://www.xs4all.nl/~perseus/zoom/zoom.java
Note there's another solution apart from rotation matrices, that doesn't loose image information through aliasing.
You can separate 2D image rotation into skews and scalings, which preserve the image quality.
Here's a simpler explanation
It seems like the example you've provided is some edge detection kernel. So if what you want to is detect edges of different angles you'd better choose some continuous function (which in your case might be a parametrized gaussian of x1 multiplied by x2) and then rotate it according to formulae provided by kigurai. As a result you would be able to produce a diskrete kernel more efficiently and without aliasing.

Resources