We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi there, let's say I have an image with some red pixels and some blue. I'm creating two arrays, one for red pixels and one for the blue. For each red pixel I want to calculate the distance to each of the blue pixels. The problem is that processing stores pixels in 1D using this common formula "int loc = x + y*img.width", so I'm not able to use the dist() function as it takes 4 args. I was wondering if there's a method to assign each pixel a 2D location.
Answers
What you want is to get the x and y locations for a pixel in the array
x = loc % img.width;
y = loc / img.width;
That's after calculating the 1D location? Or instead of that?
Here's my code, I'm having difficulties on how to calculate the distance between each pixels in the arrays:
I'm obviously getting an error when calculating the distance as "blackPix(x), ecc." is not a function, but I can't figure out how to make it work.
replace line 46
with
not tested.
Chrisir
Actually you should have these lines:
outside the main double for-loop
otherwiese it could get very time consuming....
BTW you have the initial x and y
and convert it to loc and now you want to convert it back...
instead you could also store x,y in the ArrayLists using PVector. See reference.
If a put this lines i get "cannot convert from float to int"
I saw that coming ;-)
BTW i've seen the reference but didn't really understand how to use PVector in my code
Changing dist to float does not give error but my output image is completely blank, weird.
you don't perform any changes on img ...
also line 52 should probably be
Also remember that draw() runs 60 times per sec
you can stop that by saying noLoop(); somewhere
otherwise he will change your img on and on fast....
just to test your loading you might want to try
so it should show me the original image,isn't it?
remember the name of the file must be perfectly the same as on your hard drive (even small / capital letters)
yes
It doesn't work changing does lines in void draw(). If I remove the for loop which calculates the distance my image shows up, so it's not a filename problem. BTW here's my new code:
Maybe there's some logic problem
well, as said, you don't change the img at all, you just do some detections and calc a dist....
also, in line 58 you should refer to the image
this works and gives you a pink pixel instead of a black one when the dist < 170.
but, I had to change line 36 and 37 (<130) because no pixel was added to blackPix before... you can see this when you println the size of the ArrayLists with
println (blackPix.size() + " " +colouredPix.size() );
here is the sketch
there is also a logic flaw in this
this applies already when not if (r < 130) {
but you want it to apply when all 3 previous conditions are false, not only the first...
since the change is applied to the image and then saved and applied again to it and on and on, we only have a change in the first round, then it stops (and both ArrayLists stay empty)
you could change this, when you insert instead of pink e.g. red (i.e. something that gets detected the next time draw runs)
Thanks Chrisir, but using your sketch the output image is gray. If I try to remove this line:
frameRate(1);
in void setup(), output image is white, I'm wonder how. BTW my aim with this sketch was to put all the black pixels into an array and coloured ones into another, then for each item in blackpixels[] calculate the distance to each item in coloured[] and choose the pixel with the minimum distance (using the min() function), the closest one basically. Then replace every black pixel to its closest coloured pixel. Am i setting up the sketch in the right way?you wrote
well, the frameRate slows the sketch down to 1 screen update per sec, so you need to wait 2-4 secs
It works with my test image, when you have another image, you maybe need to adjust the values for detection (130,130,30 in the if and 170 in the dist()) to make it work.
Thanks, that actually worked but I had to wait something like a minute. BTW here's how I'm proceding to replace blackpixels to closest color:
but I'm obviously getting the error here ("cannot converto from float to int"):
color closestCol = color(img.pixels[closestPix]);
I think that's wrong: lines 63 to 73
color closestCol = color(img.pixels[ int (closestPix) ]);
but the overall design is wrong for lines 63 to 73
any hints??
let me see
you want to find out for each blackpixel the closest coloured pixel
for each blackpixel you loop over all coloured pixels to find the closest....
shouldn't you therefore put
before the inner for-loop
and evaluate which one is closest (min) from the list after you completed building the list distList (after closing the inner for-loop) and not for every coloured pixel?
I mean you need to build the complete list before it is worth to check which element is the smallest dist....
(it reminds me of a previous bug you had in your 1st version ;-) )
Mmm..I'll give it a try
I've tried following your hints, but I'm a bit stacked as I'm still looping trough the coloured pixels, otherwise "xCol" and "yCol" variable are not defined, can't find a different way of doing it. The result is that I'm getting black pixels replaced by coloured ones, but not really as expected. Here's my new code:
i've changed the image used for testing to better figure out the results and realized that the code is working but is replacing the color of the first black pixels and then calculating the closest coloured again (which results to be the previous black pixel turned into coloured). Here you can see the source image on the left and the result on the right.
I've put the line to replace pixels' colour outside the loop, but the output image is the same as the source, nothing changes.
line 13 must be after line 15
you need to build the complete list in the inner for-loop
I've put the distList.append() in the inner for loop, but the resulting image is the same as the source
please enter the line noLoop() into draw()
we want to run it only once
why are you setting x and y here? you already have their values from the loop counters. at best these lines do nothing...
I am afraid the approach won't work
you're mixing up things a little...
you store the dist and take the smallest dist
but then suddenly you use the smallest dist (!) as a index (!) for pixels... won't work
instead of line 12
distList.append(dist(xBlack, yBlack, xCol, yCol));
better compare the dist dist(xBlack, yBlack, xCol, yCol)
to the previous smallest dist smallestDist ( just use < )
if smaller, set smallestDist to dist(xBlack, yBlack, xCol, yCol)
and store xBlack, yBlack into xBlackForSmallestDist, yBlackForSmallestDist
and store xColoured, yColoured into xColouredForSmallestDist, yColouredForSmallestDist
and use this later on...
you really need to dive into this...
breathe the code...
is that correct:
Yes that's correct
the thing is when you use min on you list of floats it returns that value but not the index. Therefore you can not retrieve the screen coords from another array.
Therefore I advised you to do a different approach....
see above
You mean something like this in the inner for loop?
Obviously I've previously declared the lists
more like this...
the idea is not to keep a list of all dist and take the smallest after the for-loop
but instead compare throughout in the for-loop and just take the smallest dist value by comparison AND the 2 pixels that belong to this dist
when you come out of the for-loop the vars xBlackForSmallestDist yBlackForSmallestDist etc. hold the right values