how to use opencv to calculate HSV histogram in java platform?

14,143

Solution 1

In the code, the color conversion:

Imgproc.cvtColor(image, image, Imgproc.COLOR_RGB2GRAY);

should be to HSV not gray:

Imgproc.cvtColor(image, image, Imgproc.COLOR_BGR2HSV);

In your example you will only have one (gray) plane instead of the 3 HSV channels. That will give errors when you access the 2nd and 3rd plane.

Solution 2

Here is the code for comparing the histogram of Source image to a reference image for OpenCV 2.4.11 Java (Android).

      // Assume SourceImage is a Bitmap ARGB_8888
      BitmapFactory.Options options = new BitmapFactory.Options();
      options.inPreferredConfig = Bitmap.Config.ARGB_8888;
      Bitmap refImage = BitmapFactory.decodeFile(mBaseDir + "some_reference.jpg", options);

      Mat hsvRef = new Mat();
      Mat hsvSource = new Mat();

      Mat srcRef = new Mat(refImage.getHeight(), refImage.getWidth(), CvType.CV_8U, new Scalar(4));
      Utils.bitmapToMat(refImage, srcRef);


      Mat srcSource = new Mat(SourceImage.getHeight(), SourceImage.getWidth(), CvType.CV_8U, new Scalar(4));
      Utils.bitmapToMat(SourceImage, srcSource);

      /// Convert to HSV
      Imgproc.cvtColor(srcRef, hsvRef, Imgproc.COLOR_BGR2HSV);
      Imgproc.cvtColor(srcSource, hsvSource, Imgproc.COLOR_BGR2HSV);

      /// Using 50 bins for hue and 60 for saturation
      int hBins = 50;
      int sBins = 60;
      MatOfInt histSize = new MatOfInt( hBins,  sBins);

      // hue varies from 0 to 179, saturation from 0 to 255
      MatOfFloat ranges =  new MatOfFloat( 0f,180f,0f,256f );

      // we compute the histogram from the 0-th and 1-st channels
      MatOfInt channels = new MatOfInt(0, 1);



      Mat histRef = new Mat();
      Mat histSource = new Mat();

      ArrayList<Mat> histImages=new ArrayList<Mat>();
      histImages.add(hsvRef);
      Imgproc.calcHist(histImages,
              channels,
              new Mat(),
              histRef,
              histSize,
              ranges,
              false);
      Core.normalize(histRef,
              histRef,
              0,
              1,
              Core.NORM_MINMAX,
              -1,
              new Mat());

      histImages=new ArrayList<Mat>();
      histImages.add(hsvSource);
      Imgproc.calcHist(histImages,
              channels,
              new Mat(),
              histSource,
              histSize,
              ranges,
              false);
      Core.normalize(histSource,
              histSource,
              0,
              1,
              Core.NORM_MINMAX,
              -1,
              new Mat());

      double resp1 = Imgproc.compareHist(histRef, histSource, 0);
      double resp2 = Imgproc.compareHist(histRef, histSource, 1);
      double resp3 = Imgproc.compareHist(histRef, histSource, 2);
      double resp4 = Imgproc.compareHist(histRef, histSource, 3);
Share:
14,143
user3396727
Author by

user3396727

Updated on June 05, 2022

Comments

  • user3396727
    user3396727 almost 2 years

    Actually, i want to find out the dominant colour in the image, so i want to find the HSV histogram of the image and hence filter out the other colours. However, i dont know how to do this in java platform using opence. I only find the code in C++. Thank you.

        Mat image = Highgui.imread("binary07.jpg");
        //Mat src = new Mat(image.height(), image.width(), CvType.CV_8UC2);
    
        Imgproc.cvtColor(image, image, Imgproc.COLOR_RGB2GRAY);
    
        List<Mat> hsv_planes = new ArrayList<Mat>();
        Core.split(image, hsv_planes);
    
        MatOfInt histSize = new MatOfInt(256);
    
        final MatOfFloat histRange = new MatOfFloat(0f, 256f);
    
        boolean accumulate = false;
    
        Mat h_hist = new Mat();
        Mat s_hist = new Mat();
        Mat v_hist = new Mat();
    
        //error appear in the following sentences
    
        Imgproc.calcHist((List<Mat>) hsv_planes.get(0), new MatOfInt(3), new Mat(), h_hist, histSize, histRange, accumulate);
        Imgproc.calcHist((List<Mat>) hsv_planes.get(1), new MatOfInt(3), new Mat(), s_hist, histSize, histRange, accumulate);
        Imgproc.calcHist((List<Mat>) hsv_planes.get(2), new MatOfInt(3), new Mat(), v_hist, histSize, histRange, accumulate);
    
        int hist_w = 512;
        int hist_h = 600;
        long bin_w = Math.round((double) hist_w / 256);
        //bin_w = Math.round((double) (hist_w / 256));
    
        Mat histImage = new Mat(hist_h, hist_w, CvType.CV_8UC1);
        Core.normalize(h_hist, h_hist, 3, histImage.rows(), Core.NORM_MINMAX);
        Core.normalize(s_hist, s_hist, 3, histImage.rows(), Core.NORM_MINMAX);
        Core.normalize(v_hist, v_hist, 3, histImage.rows(), Core.NORM_MINMAX);
    
    
        for (int i = 1; i < 256; i++) {
            Point p1 = new Point(bin_w * (i - 1), hist_h - Math.round(h_hist.get(i - 1, 0)[0]));
            Point p2 = new Point(bin_w * (i), hist_h - Math.round(h_hist.get(i, 0)[0]));
            Core.line(histImage, p1, p2, new Scalar(255, 0, 0), 2, 8, 0);
    
            Point p3 = new Point(bin_w * (i - 1), hist_h - Math.round(s_hist.get(i - 1, 0)[0]));
            Point p4 = new Point(bin_w * (i), hist_h - Math.round(s_hist.get(i, 0)[0]));
            Core.line(histImage, p3, p4, new Scalar(0, 255, 0), 2, 8, 0);
    
            Point p5 = new Point(bin_w * (i - 1), hist_h - Math.round(v_hist.get(i - 1, 0)[0]));
            Point p6 = new Point(bin_w * (i), hist_h - Math.round(v_hist.get(i, 0)[0]));
            Core.line(histImage, p5, p6, new Scalar(0, 0, 255), 2, 8, 0);
    
        }
    
        Highgui.imwrite("histogram.jpg", histImage);
    

    I dont know how to get the output after the split function.

    reference: http://docs.opencv.org/java/ http://docs.opencv.org/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html