views:

466

answers:

3

I'm working a game.

The game requires entities to analyse an image and head towards pixels with specific properties (high red channel, etc.)

I've looked into Pixel Bender, but this only seems useful for writing new colors to the image. At the moment, even at a low resolution (200x200) just one entity scanning the image slows to 1-2 Frames/second.

I'm embedding the image and instance it as a Bitmap as a child of the stage. The 1-2 FPS situation is using BitmapData.getPixel() (on each pixel) with a distance calculation beforehand.

I'm wondering if there's any way I can do this more efficiently... My first thought was some sort of spatial partioning coupled with splitting the image up into many smaller pieces.

I also feel like Pixel Bender should be able to help somehow, however I've had little experience with it.

Cheers for any help. Jonathan

+1  A: 

Let us call the pixels which entities head towards "attractors" because they attract the entities.

You describe a low frame rate due to scanning for attractors. This indicates that you may possibly be scanning an image at every frame. You don't specify whether the image scanned is static or changes as frequently as, e.g., a video input. If the image is changing with every frame, so that you must re-calculate attractors somehow, then what you are attempting is real-time computer vision with the ABC Virtual Machine, please see below.

If you have an unchanging image, then the most important optimization you can make is to scan the image one time only, then save a summary (or "memoization") of the locations of the attractors. At each rendering frame, rather than scan the entire image, you can search the list or array of known attractors. When the user causes the image to change, you can recalculate from scratch, or update your calculations incrementally -- as you see fit.

If you are attempting to do real-time computer vision with ActionScript 3, I suggest you look at the new vector types of Flash 10.1 and also that you look into using either abcsx to write ABC assembly code, or use Adobe's Alchemy to compile C onto the Flash runtime. ABC is the byte code of Flash. In other words, reconsider the use of AS3 for real-time computer vision.

Heath Hunnicutt
A: 

BitmapData has a getPixels method (notice it's plural). It returns a byte array of all the pixels which can be iterated much faster than a for loop with a call to getPixel inside, nested inside another for loop . Unfortunately, bytearrays are, as their name implies, 1 dimensional arrays of bytes, so iterating each pixel(4 bytes) requires using a for loop, not a foreach loop. You can access each pixel's color channel individually by default, but this sounds like what you want (find pixels with a "high red channel"), so you won't have to bitwise-and each pixel value to isolate a particular channel.

I read somewhere that getPixel is very slow, so that's where I figured you'd save the most. I could be wrong, so it'd be worth timing it.

Wallacoloo
Sorry, but this is plain wrong. The ammount of iterations is the same in both cases, if what you're trying to do is evaluating *every* pixel. Whether the loops are nested or not doesn't change that fact. Putting the pixels into a ByteArray will gain you nothing in this scenario. In fact it's worse: you will use (at least) twice as much memory; you'll avoid calling getPixel() but you'll end up calling readUnsignedInt() the same number of times; if you need to know the pixel cordinates (quite likely), you'll end up adding counters for x and y or using module. At any rate, there's no gain here.
Juan Pablo Califano
Using getPixels() is definitely preferred to getPixel(). The overhead of any method call in Flash is huge, and since you can access ByteArray like arrays, aka myPixels[index] you will save yourself the overhead of calling a method for every pixel. Also does flash internally do a bounds check for getPixel() which is another slowdown.
Quasimondo
@Quasimondo. You're more knowleadgeable than me regarding image manipulation (I follow your blog!). Still, I'm not sure getPixels is better than getPixels under the circumstances (i.e. assuming you want to do something with every pixel). Function calling has certainly an overhead, but IIRC, Nicolas Canasse demonstrated that array access is also rather slow (not sure if this has changed in the newest players).
Juan Pablo Califano
(cont) As for bounds checkings, as I understand it, both Array and ByteArray are bounds checked in Actionscript. Lastly, some quick testing (could not be a good / representative test, though) showed not significant difference between these two methods (again, under the circumnstances named above).
Juan Pablo Califano
When you access a ByteArray with the bracket syntax it is not bounds checked, so when you do byteArray[ x * 4 + y * width] and use x or y outside the bitmap rect you can run into an error (or read a different pixel than the one you expect due to wrap-around)
Quasimondo
A: 

I would say Heath Hunnicutt's anwser is a good one. If the image doesnt change just store all the color values in a vector. or byteArray of whatever and use it as a lookup table so you don't need to call getPixel() every frame.

__dominic