Search code examples
eclipseimage-processingrgbhsv

Weird color dots on image after converting RGB to HSV and HSV to RGB


Good morning everyone. I am trying to write classes that can convert between RGB and HSV. Below is my code for transferring RGB to HSV and HSV to RGB. I tried to convert from RGB to HSV then HSV to RGB and then print the image. It looks like it works, but there are color dots on my image. I was wondering if someone can help explain this phenomenon.

public class RGBtoHSV {
private float normR, normG, normB, Cmax, Cmin, delta;
private float hue, saturation, value;
private int R, G, B;
int numP;
public RGBtoHSV(int R, int G, int B){
    this.R=R; this.G=G; this.B=B;
    normR = R/255; normG = G/255; normB = B/255;
    Cmax = Math.max(R, Math.max(G, B));
    Cmin = Math.min(R, Math.min(G, B));
    delta = Cmax - Cmin;
    calcHue();
    calcSaturation();
    calcValue();
}
public void calcHue(){
    if(delta == 0 ){
        hue = 0;
    }else if((Cmax == R)){
        hue = 60 * ((G-B)/delta);
    }else if(G  == Cmax){
        hue = 60 * (((B-R)/delta)+2);
    }else{
        hue = 60f * (((R-G)/delta)+4f);
    }
}
public void calcSaturation(){
    if(Cmax == 0)
        saturation = 0;
    else
        saturation = delta/Cmax;
}   
public void calcValue(){
    value = Cmax/255;
}

//getters
public float[] getHSV(){
    float[] HSV = new float[3]; 
    HSV[0] = hue;
    HSV[1] = saturation;
    HSV[2] = value;
    return HSV;
}
}

the code that converts HSV to RGB

public class HSVtoRGB {
int R, G, B;
float C, X, m;
float normR, normG, normB;
public HSVtoRGB(float H, float S, float V){
    C = S *V;
    X = C * (1 - Math.abs((H/60)%2 -1));
    m = V - C;

    if(H < 60){
        normR=C; normG=X; normB=0;
    }else if(H<120){
        normR=X; normG=C; normB=0;
    }else if(H <180){
        normR=0; normG=C; normB=X;
    }else if(H<240){
        normR=0; normG=X; normB=C;
    }else if(H<300){
        normR=X;normG=0;normG=C;
    }else{
        normR=C;normG=0;normG=X;
    }
    R = Math.round((normR+m)*255);
    G = Math.round((normG+m)*255);
    B = Math.round((normB+m)*255);
}
public int[] getRGB(){
    int [] RGB = new int[3];
    RGB[0] = R;
    RGB[1] = G;
    RGB[2] = B;
    return RGB;
}

Original Image

Image after Conversion

Thanks in advance!!


Solution

  • I haven't looked at your code, but I'm confident I know what is causing the problem: Somewhere in your code, values are being wrapped (e.g., from beyond "fully white") to the other end of the scale (e.g., somewhere near "fully black"), typically because a too-small variable is being used to hold temporary values.

    For example, if you have a signed byte variable and use it to store the result of multiplying 16*9 (144, greater than the maximum +127 value of a signed byte), your signed byte value is going to be -16 - which will produce "unexpected" results.

    EDIT

    After looking at your code, I suspect part of your problem is mixed integer and float arithmetic: Some places you use 60, for example, and other places you use 60f, which I assume means you want a floating point number in the calculation. (I'm only guessing that, since you didn't specify what language you are working with.) You need to use floating point numbers in all of the calculations.