-1

I am trying to convert RGB values of an image and get the HSV values of it. I am trying to do this without using Color.RGBtoHSB because I don't like the float values I want the numbers to be in the range of 0-255. When I run this program my conversion algorithm prints out nothing even though I ask it to print out values.

public void splitChannels() {

    Mat firstImage = Imgcodecs.imread("darkGreen.jpg");
    Imgproc.cvtColor(firstImage, firstImage, Imgproc.COLOR_BGR2RGB);
    int width = 20;
    int height = 20;
    Rect roi = new Rect(100,100, width, height);
    Mat smallImg = new Mat(firstImage, roi);

   Imgproc.cvtColor(smallImg,smallImg,Imgproc.COLOR_BGR2RGB);
    // 3 channels in smallImg
    int channels = smallImg.channels();

    int totalBytes = (int)(smallImg.total() * smallImg.channels());

    byte buff[] = new byte[totalBytes];
    smallImg.get(0, 0, buff);

    for (int i=0; i< height; i++) {
        // stride is the number of bytes in a row of smallImg
        int stride = channels * width;
        for (int j=0; j<stride; j+=channels) {
            int r = buff[(i * stride) + j];
            int g = buff[(i * stride) + j + 1]; 
            int b = buff[(i * stride) + j + 2];

            RGBtoHSV(r, g, b);

        } 
    } 
}

private int[] RGBtoHSV(int r, int g, int b){
    int computedH = 0;
    int computedS = 0;
    int computedV = 0;
    int[] HSVarr = new int[3];


    HSVarr[0] = computedH;
    HSVarr[1] = computedS;
    HSVarr[2] = computedV;
    if(r< 0 || g< 0 || b< 0 || r> 255 || g>255 || b> 255){
        System.err.println("RGB values must be in range 0 to 255");
    }

    r=r/255; g=g/255; b=b/255;
    int minRGB = Math.min(r, Math.min(g, b));
    int maxRGB = Math.max(r, Math.min(g, b));

    // Black-gray-white
    if(minRGB==maxRGB){
        computedV = minRGB;
        return  HSVarr;
    }

    int d = (r==minRGB) ? g-b : ((b==minRGB) ? r-g : b-r);
    int h = (r==minRGB) ? 3 : ((b==minRGB) ? 1 : 5);
    computedH = 60*(h - d/(maxRGB - minRGB));
    computedS = (maxRGB = minRGB)/maxRGB;
    computedV = maxRGB;

    System.out.println("H: " + computedH + " V: "+ computedS +" S: " + computedV);
    return HSVarr;
}
cuber
  • 371
  • 5
  • 20
  • You could probably rearrange your equations so that the integer division doesn't introduce an inaccuracy. For example `computedH = 60* h - 60 * d/(maxRGB - minRGB);`. Also, dividing everything by `255` before you do the calculations probably isn't the best plan. – Dawood ibn Kareem Feb 27 '17 at 04:16
  • Your question is essentially "I divided two `int` values, and got zero instead of the floating-point number I expected". The other question is "I divided two `int` values, and got zero instead of the floating-point number I expected". The context is irrelevant - the answer is the same. – Dawood ibn Kareem Feb 27 '17 at 04:18
  • I changed my data types to floats and there was still nothing printed out by the system. Even though I request it to print out numbers. @DavidWallace – cuber Feb 27 '17 at 04:21
  • Also try correcting this line. `int maxRGB = Math.max(r, Math.min(g, b));`. I don't think `Math.min` should be in there. That error could make your program fail to print anything. – Dawood ibn Kareem Feb 27 '17 at 04:24
  • Oh I see, what I was trying to do was to translate this code from JavaScript into java and use the function to pass RGB values I get from reading the pixels RGB values of the image and pass them to that method and get the HSV values. http://www.javascripter.net/faq/rgb2hsv.htm @DavidWallace – cuber Feb 27 '17 at 04:27
  • OK, but Java has different datatypes from Javascript. Also, division is very different between the two languages. So you'll need a good understanding of Java, rather than just a copy-and-paste approach. That misprint (`min` instead of `max`) is something of a biggie though, and I apologise for not noticing it on my first reading of the question. – Dawood ibn Kareem Feb 27 '17 at 04:31
  • I do know Java well but I don't know JavaScript, I was looking for an algorithm used by someone to convert RGB to HSV for Java but found nothing, I could see how the JavaScript was working and tried to implement that but unknowingly there is more difference in the two languages in arithmetic. Also I did fix the `min` and `max` error but still no values printed. Something must be underlying causing it to not print out those values. @DavidWallace – cuber Feb 27 '17 at 04:35
  • Did you step through it with your debugger? – Dawood ibn Kareem Feb 27 '17 at 04:36
  • Did you remove the division by 255? That's guaranteed to turn any `int` in the range 0-254 into 0. – Dawood ibn Kareem Feb 27 '17 at 04:39
  • Now I am receiving values but they are inaccurate. `H: 120.0 V: 1.0 S: 100.0` is not what I should get for a green image. @DavidWallace – cuber Feb 27 '17 at 04:50
  • OK, what values are you expecting? (Note, you've also swapped `computedV` and `computedS` in your output - not sure why). – Dawood ibn Kareem Feb 27 '17 at 04:55
  • I should be getting something near H 134, S 96, V 32 in that ballpark. @DavidWallace those are the HSV values for darkGreen. – cuber Feb 27 '17 at 04:58
  • Well, I still think you need to step through this with your debugger to work out what's going on. If you still can't figure it out, I suggest you tidy up your code, remove all the careless errors, remove all the integer divisions, and ask a new question. – Dawood ibn Kareem Feb 27 '17 at 04:59

1 Answers1

1

I am trying to convert RGB values of an image and get the HSV values of it. I am trying to do this without using Color.RGBtoHSB because I don't like the float values.

Create a wrapper method for the Color.RGBtoHSB(...) method to convert the float values to the appropriate int values.

Something like:

import java.awt.*;

public class Main
{
    public static void main(String[] args) throws Exception
    {
        int[] hsb = RGBtoHSB(0, 0, 255);

        for (int value: hsb)
            System.out.println( value );
    }

    public static int[] RGBtoHSB(int red, int green, int blue)
    {
        float[] hsbFloat = Color.RGBtoHSB(red, green, blue, null);
        int[] hsbInt = new int[3];

        hsbInt[0] = Math.round( hsbFloat[0] * 360 );
        hsbInt[1] = Math.round( hsbFloat[1] * 100 );
        hsbInt[2] = Math.round( hsbFloat[2] * 100 );

        return hsbInt;
    }
}
camickr
  • 321,443
  • 19
  • 166
  • 288