Sign in to follow this  
Followers 0
emog

Setting up a dynamic array

11 posts in this topic

I would like to scan an image (using PixelGetColor) and store the the locations of the pixels that are of one single particular colour in a single dimensional array.

For example, a 5 x 5 pixel image (zoomed in for legibility) consisting of 25 pixels as below:

Posted Image

.. I was thinking the best solution would be to convert it to a 1 pixel stream:

Posted Image

... and so from here I would like to have the array look for a colour (let's say black in this case) and output the number of their position, such as:

Array[1]=1

Array[2]=2

Array[3]=4

Array[4]=7

Array[5]=8

Array[6]=10

Array[7]=11

Array[8]=12

Array[9]=14

Array[10]=15

Array[11]=17

Array[12]=23

Array[13]=25

The array will only need to have as many values as there are black pixels (in this case), hence is dynamic.

Or would it be easier (or more efficient) to have an array for the full pixel count (each pixel gets its own array entry, ie the array would consist of 25 values in this case) and simply have a yes/no (1 or 0) for each array value rather than a number, as below?:-

Posted Image

Array[1]=1

Array[2]=1

Array[3]=0

Array[4]=1

Array[5]=0

Array[6]=0

Array[7]=1

Array[8]=1

Array[9]=0

Array[10]=1

Array[11]=1

Array[12]=1

Array[13]=0

Array[14]=1

Array[15]=1

Array[16]=0

Array[17]=1

Array[18]=0

Array[19]=0

Array[20]=0

Array[21]=0

Array[22]=0

Array[23]=1

Array[24]=0

Array[25]=1

My actual graphic has near 50,000 pixels in total, though, not just 5 x 5 as in the example, so speed in the calculation is everything.

The array would only need to be temporary, as the array and its values will be dumped and then reset elsewhere further on in the code.

Can arrays be stored in memory (RAM), or do they need to be physically written to a new file? Would an array storing up to 50,000 entries be too much?

Many thanks, and any hints appreciated.

Share this post


Link to post
Share on other sites



Arrays can be 'remembered' by the program, or written to a file (but if speed is a goal then avoid harddisk usage). 50.000 elements is no problem at all. After some quick binary searching (manually :whistle:), I found that the max array is Dim $a[16777215]. That's more than 16 and a half million! That should suit your needs :D

If you want your array to be just as big as the amount of black dots, you could do one of two things:

1 - Run through the dots, ReDim your array with one more every time you find one. (See help for redim.)

2 - Run through the dots, count the amount of black dots, create an array of that amount, and run through it again filling the array.

Though I would prefer the binary array myself. Don't know why exactly, just feels right... Guess it depends on what you want to do with the information :P

I don't know which one is faster, ReDim'ing an array 50000 times or running through 50000 checks two times (resulting in 100000 checks). You might want to test this out.


Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

Nice one, bunny. After thinking about it I went for a single pass Array that starts with one entry and adds any entries as it picks them up. However, I am getting an error and could do with some help debugging if anyone could offer possible hints, please.

#include <Array.au3>
Dim $PixelArray[1]

;~~ Scanning image and creating an Array for a single colour
;~~ Encodes to a single pixel stream
$PixelCounter = 0
$ColourInstances = 0
For $YAxis = $Y1 to $Y2 Step 1
    For $XAxis = $X1 to $X2 Step 1
        $PixelCounter = $PixelCounter + 1
        $SourceColour = PixelGetColor($XAxis, YAxis)
        If $SourceColour = $ClrPal[$PalletteCounter] Then
            _ArrayAdd($PixelArray, $PixelCounter)
            $ColourInstances = $ColourInstances + 1
        EndIf
    Next
Next
MsgBox(0, "Array colour pixel count", "Instances of coloured pixels in template is: " & $ColourInstances)
;~~~~~~~ End pixel colour array scan ~~~~~~~~


;~~~~~~~~ RR Array Output ~~~~~~~~~
        WinActivate("OutputWindow")
        WinWaitActive("OutputWindow")
    
;~~~ decodes and reconstructs back to a 2D image
$PixelCounter = 0
For $YAxis = $Y1 to $Y2 Step 1
    For $XAxis = $X1 to $X2 Step 1
        $PixelCounter = $PixelCounter + 1
>>>     If $PixelArray[$PixelCounter] = $PixelCounter Then
            Mouseclick("left", $XAxis, $YAxis, 1, 0)
        EndIf
    Next
Next

The error I'm getting is: "Error: Array Variable has incorrect number of subscripts or subscript dimension range exceeded." and I added a ">>>" to show the line in question.

Am seriously scratching my head as to what could be causing it.

Any suggestions/hints much appreciated! :whistle:

Share this post


Link to post
Share on other sites

Still having problems trying to debug the array. Any hints anyone could possibly give?

Thanks

Share this post


Link to post
Share on other sites

Ok, first of all: Don't do this kind of crazy calculations in AutoIt. This is some crazy binary stuff.

Second, create an 50000 element array and read in the values to the array. Considering the history and background of computers this is a more efficient way of doing it.

Share this post


Link to post
Share on other sites

Still having problems trying to debug the array. Any hints anyone could possibly give?

Thanks

I tried your code, and modified it so that it reads from my desktop (scite was active) and remembers if a pixel is white, and then in the second part make the mouse move to all white pixels found. I needed to do this to be able to test your code. But it gives me no error whatsoever. The code I derived from your test code is:

#include <Array.au3>
Dim $PixelArray[1]

;~~ Scanning image and creating an Array for a single colour
;~~ Encodes to a single pixel stream
$X1 = 500
$X2 = 550
$Y1 = 100
$Y2 = 104

$PixelCounter = 0
$ColourInstances = 0
For $YAxis = $Y1 to $Y2 Step 1
    For $XAxis = $X1 to $X2 Step 1
        $PixelCounter = $PixelCounter + 1
        $SourceColour = PixelGetColor($XAxis, $YAxis)
        If $SourceColour = 16777215 Then
            _ArrayAdd($PixelArray, $PixelCounter)
            $ColourInstances = $ColourInstances + 1
        EndIf
    Next
Next
MsgBox(0, "Array colour pixel count", "Instances of coloured pixels in template is: " & $ColourInstances)
;~~~~~~~ End pixel colour array scan ~~~~~~~~


;~~~~~~~~ RR Array Output ~~~~~~~~~
;        WinActivate("OutputWindow")
;        WinWaitActive("OutputWindow")
    
;~~~ decodes and reconstructs back to a 2D image
$PixelCounter = 0
For $YAxis = $Y1 to $Y2 Step 1
    For $XAxis = $X1 to $X2 Step 1
        $PixelCounter = $PixelCounter + 1
        If $PixelArray[$PixelCounter] = $PixelCounter Then
            MouseMove($XAxis,$YAxis)
        EndIf
    Next
Next

It works like a charm, as I suspected, because I couldn't foresee a problem with this array... You sure the $PixelArray does not get changed in any part of the code you didn't include?


Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

But as I said earlier (and I believe Manadar meant this too?), a 50000 element array is probably better then thousands of _addArray operations...


Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

Thanks ever so much. It's taken me a good while but I've nailed it in the end, it was actually another variable that the main Array output loop was reliable on, but which wasn't being reset after every cycle. So I placed it inside the loop so that it was reset after every cycle and all was well.

Must say it's been a great lateral-thinking learning process.

One thing I found particularly useful is placing MsgBox displays after every command that you're having problems with, so you can follow the execution of the program step by step and find exactly where the code is going wrong.

I have also ditched the previous "add array per cycle" routine in favour of a single 50,000 pass array retrieval of all the colours of the pixels in one go, as suggested. Takes less than a second to carry out the scan, and the array export works beautifully. What originally took the program 3 hours to carry out (individually retrieving the colour and position of a pixel and exporting them individually, up to 50,000 times) now takes about 10 minutes for the whole 50,000 pixels using a single scan Array and then dumping the Array in one, as opposed to switching back and forth between windows for every pixel as before. - A literal real-world improvement of ~1800%. :whistle: And that includes painting in all 200 colours! Dead chuffed.

All it needs now is a GUI. :P

Thanks too all, expecially Bunny. Have a great weekend!

Share this post


Link to post
Share on other sites

Thanks too all, expecially Bunny. Have a great weekend!

Whee! I'm getting all warm inside... :whistle:

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

Whee! I'm getting all warm inside... :whistle:

All those shots of Jack make everyone warm inside :P ....

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

All those shots of Jack make everyone warm inside :P ....

Hmm... Is it that obvious, huh... :whistle:

Edited by SadBunny

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0