【问题标题】:how to use opencv to calculate HSV histogram in java platform?java平台下如何使用opencv计算HSV直方图?
【发布时间】:2015-08-13 17:33:02
【问题描述】:

实际上,我想找出图像中的主色,所以我想找到图像的 HSV 直方图,从而过滤掉其他颜色。但是,我不知道如何在使用 opence 的 java 平台中执行此操作。我只找到 C++ 中的代码。谢谢。

    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);

我不知道如何获得拆分功能后的输出。

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

【问题讨论】:

    标签: java opencv image-processing


    【解决方案1】:

    在代码中,颜色转换:

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

    应该是HSV而不是灰色:

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

    在您的示例中,您将只有一个(灰色)平面,而不是 3 个 HSV 通道。当您访问 2nd 和 3rd 平面时,这会出错。

    【讨论】:

      【解决方案2】:

      这是用于比较源图像的直方图与 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);
      

      【讨论】:

        【解决方案3】:

        下一个代码适用于一个深度通道。您只需进行一些修改即可添加其他两个频道

        //Calculate histogram
        java.util.List<Mat> matList = new LinkedList<Mat>();
        matList.add(imageIR_gray);
        Mat histogram = new Mat();
        MatOfFloat ranges=new MatOfFloat(0,256);
        MatOfInt histSize = new MatOfInt(255);
        Imgproc.calcHist(
                        matList, 
                        new MatOfInt(0), 
                        new Mat(), 
                        histogram , 
                        histSize , 
                        ranges);
        
        // Create space for histogram image
        Mat histImage = Mat.zeros( 100, (int)histSize.get(0, 0)[0], CvType.CV_8UC1);
        // Normalize histogram                          
        Core.normalize(histogram, histogram, 1, histImage.rows() , Core.NORM_MINMAX, -1, new Mat() );   
        // Draw lines for histogram points
        for( int i = 0; i < (int)histSize.get(0, 0)[0]; i++ )
        {                   
                Core.line(
                        histImage,
                        new org.opencv.core.Point( i, histImage.rows() ),
                        new org.opencv.core.Point( i, histImage.rows()-Math.round( histogram.get(i,0)[0] )) ,
                        new Scalar( 255, 255, 255),
                        1, 8, 0 );
        }
        

        【讨论】:

          猜你喜欢
          • 2014-01-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-12
          • 2012-06-25
          • 1970-01-01
          • 1970-01-01
          • 2012-11-23
          相关资源
          最近更新 更多