I made harmonic mean code for two images. But

#1

Hi, All.

I made harmonic mean code for two images.

// Function that returns harmonic mean.
int harmonicMean(float arr[], int n)
{
// Declare sum variables and initialize
// with zero.
float sum = 0;
for (int i = 0; i < n; i++)
sum = sum + 1 / arr[i];

return (int)n/sum;

}

//--------------------------------------------------------------
void ofApp::setup(){

aa.load("/Users/kerbal/Desktop/low.png");
bb.load("/Users/kerbal/Desktop/high.png");

ofPixels p1 = aa.getPixels();
ofPixels p2 = bb.getPixels();
ofPixels pp = aa.getPixels();

float arr[] = {};
for(int i = 0; i < aa.getWidth()*aa.getHeight(); i++){
    arr[0]= p1[i];
    arr[1]= p2[i];
    
    pp[i]= harmonicMean(arr, 2); // <-bad access error happen
}
cc.setFromPixels(pp);
cc.update();

}

But bad access error happen like above.
What’s wrong to me ?

Thanks.
Best,
@bemoregt.

#2

Is your harmonic mean formula correct? From what I understand, harmonic mean = n/(sum of reciprocals of the dataset) where n == the number of elements in the set.

Going by that, a harmonic mean function would be (using floats),

float harmonicMean(vector<float> arr){
    float sum = 0;
    for(int i=0; i<arr.size(); i++){
        sum += 1.0/arr[i];
        }
    return arr.size()/sum;
}

If you want to do it the way you’ve done it, by defining the number of elements to get the harmonic mean from from a given array (I’d be using vectors instead of uninitialised arrays as how it’s done in the later part of your code), I think you have a missing {} in the for-loop as you’re trying to return from within a for-loop. The correct way to do your version would be,

int harmonicMean(vector<float> arr, int n)
{
float sum = 0;
for (int i = 0; i < n; i++){
    sum = sum + 1.0 / arr[i];
    }

return (int)n/sum;
}

Now for the second part of the code, where you’re getting the actual issue, from what I understand you’re trying to get the harmonic mean of every pixel value between p1 and p2, correct? I’m writing this without testing the code so bear with me, from what I can see, there are potentially two areas that are the problem. One is that you’re using an uninitialised array, which could be simply fixed with doing vector<float> arr and then using

arr.push_back(p1[i]);
arr.push_back(p2[i]);

But potentially what I see what the problem is the fact that… what is p1[i] and p2[i] in the first place? Is it a float? Can you do a cout << p1[i] << endl; and actually verify that? Wouldn’t you rather be doing .getColor() and doing a harmonic mean with ofColor variables and not float values? This is where I’m confused and I could run the code at some point and see, haven’t worked with pixels for a while. But to iterate between two instances of ofPixels and getting their colours and doing harmonic means with floats/ints, I’d be doing

for(int x=0; x<p1.getWidth(); x++){
    for(int y=0; y<p1.getHeight(); y++){
        ofColor c1 = p1.getColor(x, y);
        ofColor c2 = p2.getColor(x, y);
        
        vector<float> r, g, b;
        r.push_back(c1.r);
        r.push_back(c2.r);

        float harmonicRed = harmonicMean(r, 2);

        //similarly for green and blue.
        //and then set the colour to your ofPixels pp with

        pp.setColor(x, y, ofColor(harmonicRed, harmonicGreen, harmonicBlue));

…or something to that effect.

2 Likes
#3

Hi, @ayruos.

I made this from your help.

Thanks a lot.

from @bemoregt.