ColorDistance and Vectors

Hi There,

My main question is: what would be the best way to store pixel information (brightness) for all the pixels of a directory of images in a vector (or array) and then draw these pixels as circles?

I’m trying to develop the example in ofBook for the “eyedropper-style” where you process an image and determine the closeness of each pixel to a set color.
I’m performing this process on a set of images taken from a directory.
I’d then like to store the closeness of each pixel in each photo and then draw these as circles and then animate the circles.
In the OfBook, the process is done in the draw function. Doing this in the Draw function seems really slow.

// Code fragment for tracking a spot with a certain target color. 
// Our target color is CSS LightPink: #FFB6C1 or (255, 182, 193)
float rTarget = 255; 
float gTarget = 182;
float bTarget = 193; 

// these are used in the search for the location of the pixel 
// whose color is the closest to our target color.
float leastDistanceSoFar = 255; 
int xOfPixelWithClosestColor = 0; 
int yOfPixelWithClosestColor = 0;

for (int y=0; y<h; y++) {
	for (int x=0; x<w; x++) {
	
		// Extract the color components of the pixel at (x,y)
		// from myVideoGrabber (or some other image source)
		ofColor colorAtXY = myVideoGrabber.getColor(x, y);
		float rAtXY = colorAtXY.r; 
		float gAtXY = colorAtXY.g; 
		float bAtXY = colorAtXY.b;
		
		// Compute the difference between those (r,g,b) values 
		// and the (r,g,b) values of our target color
		float rDif = rAtXY - rTarget; // difference in reds 
		float gDif = gAtXY - gTarget; // difference in greens 
		float bDif = bAtXY - bTarget; // difference in blues 
		
		// The Pythagorean theorem gives us the Euclidean distance.
		float colorDistance = 
			sqrt (rDif*rDif + gDif*gDif + bDif*bDif); 
			
		if(colorDistance < leastDistanceSoFar){
			leastDistanceSoFar = colorDistance;
			xOfPixelWithClosestColor = x;
			yOfPixelWithClosestColor = y;
		}
	}
}

// At this point, we now know the location of the pixel 
// whose color is closest to our target color: 
// (xOfPixelWithClosestColor, yOfPixelWithClosestColor)

Any tips?

Hi @floftus,

I believe you can try to store the differences into vectors once in the setup function.
If i understand it well, you won’t recalculate the distances, so you don’t have to re-do the calculations.

Something like :

vector < vector < float > > > distImgs;
distImgs.resize(amntOfImages);
for(int i =0; i < distImgs.size(); i++){
    vector < float > tmpPixDist;
    tmpDistPix = calculateDistImg(i);
    distImgs[i] = tmpDistPix;
}

Where amntOfImages is the amount of images you have in your folder, adnd calculateDistImg a method calculating all the distances to your set Color:

vector < float > ofApp::calculateDistimg( int i){
    ofImage tmpImg = getImgNbr(i);
vector < float > distances;
    // use the code from the ofBook here

for (int y=0; y<h; y++) {
	for (int x=0; x<w; x++) {
// [ ... ]
    //store each distance into the vector of float 
    distances.push_back(colorDistance);
}
}
return distances;
}

With getImgNbr(int i), returning the right image from the folder.

Then in the draw function you can use the vector of vector of floats - distImgs - to draw things.

I hope this is stirring you in the right direction, it’s not super precise…

If a bit confusion, try only with one image to start with…

++

P

Hi, thanks so much for your response.

How would you use the vector of floats to draw things?
I’ve been trying with an x,y loop that checks the float value at x,y co,ordinates and then draws those above a certain threshold but I think I’m doing it wrong

Thanks

Hi @floftus,

I think that i would do something which draws things just like it is set in an image.
But first you need to store it the right way in the image, so you unpack it the same way when reading it.

So I would store it as follow :
ofApp.cpp::setup():

img.load("PachoDreamTeam.png");
    width = img.getWidth();
    height = img.getHeight();
    int amntChannel = 4;
    float thresholdVal = 10000;
    
    ofPixels_<unsigned char> pixs = img.getPixels();
    for(int i = 0; i < pixs.size(); i+=amntChannel){
        float valRed = pixs[i];
        float valGreen = pixs[i + 1];
        float valBlue = pixs[i + 2];
        float valAlpha = pixs[i + 3];
        
        float val = 0;
        if(valRed + valGreen + valBlue + valAlpha < thresholdVal){
            val = valRed;
        }
        
        vectFloats.push_back(val);
    }

With predefined
int width, height;
vector < float > vectFloats;
( in ofApp.h).

using this image :
PachoDreamTeam

And using the threshold condition :
valRed + valGreen + valBlue + valAlpha < thresholdVal

then drawing it like so :
ofApp.cpp::draw():

for( int i = 0; i < vectFloats.size(); i++){
        ofSetColor(vectFloats[i]);
        ofDrawRectangle(i % width , i/width, 1, 1);
    }

hope this helps,

++
P