Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Why does calcHist() method create an empty black histogram Mat?

I have written code to read in an image from gallery, then apply inRange() on it to find blue colored blob and create mask, then used findContours() to find contours, and the drawContours() to draw the contours, then boundingRect() to find a rectangle around the first contour, and then submat() to extract out the submatrix. Then I used Mat.zeroes() to create a mask from that rectangular submat. Then I applied Imgproc.calcHist() to create a histogram, and passed in the Mask as the 3rd argument so that the histogram calculated is that of the area inside the contour only.

Following are two screen shots from my Genymotion emulator, first showing the original Mat with green contours around blue detected blobs and the submatrix I mentioned; the second shows the histogram bmp image stored in sdcard. It is plain black. The question is why is it like this, where is my histogram graph?

image description

HISTOGRAM:

image description

Code:

//Get the image from file path
            rgbaMat = new Mat();
            rgbaMatCopy = new Mat();
            rgbaMat = Highgui.imread(filePath);
            rgbaMatCopy = Highgui.imread(filePath);

            //Preprocessing - color space conversion
            Imgproc.cvtColor(rgbaMat, rgbaMat, Imgproc.COLOR_BGR2RGB);
            Imgproc.cvtColor(rgbaMatCopy, rgbaMatCopy, Imgproc.COLOR_BGR2RGB);
            Mat hsvMat = new Mat();
            Imgproc.cvtColor(rgbaMatCopy, hsvMat, Imgproc.COLOR_RGB2HSV);

            //Make the mask from the detected blue colored blob(s)
            Scalar lowerThreshold = new Scalar(100, 146, 148);
            Scalar upperThreshold = new Scalar(134, 255, 255);
            Mat mask = new Mat();
            Core.inRange(hsvMat, lowerThreshold, upperThreshold, mask);

            //Preprocessing
            Mat dilatedMask = new Mat();
            Imgproc.dilate(mask, dilatedMask, new Mat());
            Imgproc.dilate(dilatedMask, dilatedMask, new Mat());

            //Find the contours
            contours = new ArrayList<>();
            Imgproc.findContours(dilatedMask, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

            //Draw the contours
            for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
                Imgproc.drawContours(rgbaMatCopy, contours, contourIdx, new Scalar(0, 255, 0), 1);
            }

            //Convert the mat with contours drawn to bitmap and display in imageView
            Bitmap theBitmap = Bitmap.createBitmap(rgbaMatCopy.cols(), rgbaMatCopy.rows(),
                    Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(rgbaMatCopy, theBitmap);
            imageView.setImageBitmap(theBitmap);

            //Find and cut out the smallest bounding rectangle around the first contour from the list of contours
            MatOfPoint firstContour = contours.get(0);
            Rect firstContourBoundingRect = Imgproc.boundingRect(firstContour);
            Mat objectSubmat = new Mat();
            objectSubmat = rgbaMat.submat(firstContourBoundingRect);

            Bitmap objectSubmatBitmap = Bitmap.createBitmap(objectSubmat.cols(), objectSubmat.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(objectSubmat, objectSubmatBitmap);
            imageViewOne.setImageBitmap(objectSubmatBitmap);

            //Create mask of the region inside the contour
            Mat regionMask = Mat.zeros(objectSubmat.rows(), objectSubmat.cols(), CvType.CV_8UC1);
            List<MatOfPoint> firstList = new ArrayList<MatOfPoint>();
            firstList.add(firstContour);
            Imgproc.drawContours(regionMask, firstList, 0, new Scalar(255), -1);

            //Preprocessing - color space conversion
            Mat regionHsv = new Mat();
            Imgproc.cvtColor(objectSubmat, regionHsv, Imgproc.COLOR_RGB2HSV);


            //Calculate Histogram
            List<Mat> sourceImageList = new ArrayList<Mat>();
            sourceImageList.add(regionHsv);
            Mat histogram = new Mat();
            //histogramMat.convertTo(histogramMat, CvType.CV_8UC2);
            Imgproc.calcHist(sourceImageList, new MatOfInt(2), regionMask, histogram, new MatOfInt(256), 
                    new MatOfFloat(0f, 256f));

            Highgui.imwrite("/mnt/sdcard/histogram.bmp", histogram);

Why does calcHist() method create an empty black histogram Mat?

I have written code to read in an image from gallery, then apply inRange() on it to find blue colored blob and create mask, then used findContours() to find contours, and the drawContours() to draw the contours, then boundingRect() to find a rectangle around the first contour, and then submat() to extract out the submatrix. Then I used Mat.zeroes() to create a mask from that rectangular submat. Then I applied Imgproc.calcHist() to create a histogram, and passed in the Mask as the 3rd argument so that the histogram calculated is that of the area inside the contour only.

Following are two screen shots is a screenshot from my Genymotion emulator, first showing the original Mat with green contours around blue detected blobs and then the submatrix I mentioned; the second shows mentioned and then the histogram bmp image stored in sdcard. created by calcHist(), It which is plain black. black vertical line The question is why is it like this, where is my histogram graph?

image description

HISTOGRAM:

image description

Code:

//Get the image from file path
            rgbaMat = new Mat();
            rgbaMatCopy = new Mat();
            rgbaMat = Highgui.imread(filePath);
            rgbaMatCopy = Highgui.imread(filePath);

            //Preprocessing - color space conversion
            Imgproc.cvtColor(rgbaMat, rgbaMat, Imgproc.COLOR_BGR2RGB);
            Imgproc.cvtColor(rgbaMatCopy, rgbaMatCopy, Imgproc.COLOR_BGR2RGB);
            Mat hsvMat = new Mat();
            Imgproc.cvtColor(rgbaMatCopy, hsvMat, Imgproc.COLOR_RGB2HSV);

            //Make the mask from the detected blue colored blob(s)
            Scalar lowerThreshold = new Scalar(100, 146, 148);
            Scalar upperThreshold = new Scalar(134, 255, 255);
            Mat mask = new Mat();
            Core.inRange(hsvMat, lowerThreshold, upperThreshold, mask);

            //Preprocessing
            Mat dilatedMask = new Mat();
            Imgproc.dilate(mask, dilatedMask, new Mat());
            Imgproc.dilate(dilatedMask, dilatedMask, new Mat());

            //Find the contours
            contours = new ArrayList<>();
            Imgproc.findContours(dilatedMask, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

            //Draw the contours
            for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
                Imgproc.drawContours(rgbaMatCopy, contours, contourIdx, new Scalar(0, 255, 0), 1);
            }

            //Convert the mat with contours drawn to bitmap and display in imageView
            Bitmap theBitmap = Bitmap.createBitmap(rgbaMatCopy.cols(), rgbaMatCopy.rows(),
                    Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(rgbaMatCopy, theBitmap);
            imageView.setImageBitmap(theBitmap);

            //Find and cut out the smallest bounding rectangle around the first contour from the list of contours
            MatOfPoint firstContour = contours.get(0);
            Rect firstContourBoundingRect = Imgproc.boundingRect(firstContour);
            Mat objectSubmat = new Mat();
            objectSubmat = rgbaMat.submat(firstContourBoundingRect);

            Bitmap objectSubmatBitmap = Bitmap.createBitmap(objectSubmat.cols(), objectSubmat.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(objectSubmat, objectSubmatBitmap);
            imageViewOne.setImageBitmap(objectSubmatBitmap);

            //Create mask of the region inside the contour
            Mat regionMask = Mat.zeros(objectSubmat.rows(), objectSubmat.cols(), CvType.CV_8UC1);
            List<MatOfPoint> firstList = new ArrayList<MatOfPoint>();
            firstList.add(firstContour);
            Imgproc.drawContours(regionMask, firstList, 0, new Scalar(255), -1);

            //Preprocessing - color space conversion
            Mat regionHsv = new Mat();
            Imgproc.cvtColor(objectSubmat, regionHsv, Imgproc.COLOR_RGB2HSV);


            //Calculate Histogram
            List<Mat> sourceImageList = new ArrayList<Mat>();
            sourceImageList.add(regionHsv);
            Mat histogram = new Mat();
            //histogramMat.convertTo(histogramMat, CvType.CV_8UC2);
            Imgproc.calcHist(sourceImageList, new MatOfInt(2), regionMask, histogram, new MatOfInt(256), 
                    new MatOfFloat(0f, 256f));

          Highgui.imwrite("/mnt/sdcard/histogram.bmp", histogram);
histogram);// check
        Mat hish = Highgui.imread("/mnt/sdcard/histogram.bmp");
        Bitmap histogramBitmap = 
                Bitmap.createBitmap(hish.cols(), hish.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(hish, histogramBitmap);
        imageViewTwo.setImageBitmap(histogramBitmap);

Why does calcHist() method create an empty black histogram Mat?

I have written code to read in an image from gallery, then apply inRange() on it to find blue colored blob and create mask, then used findContours() to find contours, and the drawContours() to draw the contours, then boundingRect() to find a rectangle around the first contour, and then submat() to extract out the submatrix. Then I used Mat.zeroes() to create a mask from that rectangular submat. Then I applied Imgproc.calcHist() to create a histogram, and passed in the Mask as the 3rd argument so that the histogram calculated is that of the area inside the contour only.

Following is a screenshot from my Genymotion emulator, showing the original Mat with green contours around blue detected blobs and then the submatrix I mentioned and then the histogram created by calcHist(), which is black vertical line The question is why is it like this, where is my histogram graph?

image description

HISTOGRAM:

image description

Code:

//Get the image from file path
            rgbaMat = new Mat();
            rgbaMatCopy = new Mat();
            rgbaMat = Highgui.imread(filePath);
            rgbaMatCopy = Highgui.imread(filePath);

            //Preprocessing - color space conversion
            Imgproc.cvtColor(rgbaMat, rgbaMat, Imgproc.COLOR_BGR2RGB);
            Imgproc.cvtColor(rgbaMatCopy, rgbaMatCopy, Imgproc.COLOR_BGR2RGB);
            Mat hsvMat = new Mat();
            Imgproc.cvtColor(rgbaMatCopy, hsvMat, Imgproc.COLOR_RGB2HSV);

            //Make the mask from the detected blue colored blob(s)
            Scalar lowerThreshold = new Scalar(100, 146, 148);
            Scalar upperThreshold = new Scalar(134, 255, 255);
            Mat mask = new Mat();
            Core.inRange(hsvMat, lowerThreshold, upperThreshold, mask);

            //Preprocessing
            Mat dilatedMask = new Mat();
            Imgproc.dilate(mask, dilatedMask, new Mat());
            Imgproc.dilate(dilatedMask, dilatedMask, new Mat());

            //Find the contours
            contours = new ArrayList<>();
            Imgproc.findContours(dilatedMask, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

            //Draw the contours
            for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
                Imgproc.drawContours(rgbaMatCopy, contours, contourIdx, new Scalar(0, 255, 0), 1);
            }

            //Convert the mat with contours drawn to bitmap and display in imageView
            Bitmap theBitmap = Bitmap.createBitmap(rgbaMatCopy.cols(), rgbaMatCopy.rows(),
                    Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(rgbaMatCopy, theBitmap);
            imageView.setImageBitmap(theBitmap);

            //Find and cut out the smallest bounding rectangle around the first contour from the list of contours
            MatOfPoint firstContour = contours.get(0);
            Rect firstContourBoundingRect = Imgproc.boundingRect(firstContour);
            Mat objectSubmat = new Mat();
            objectSubmat = rgbaMat.submat(firstContourBoundingRect);

            Bitmap objectSubmatBitmap = Bitmap.createBitmap(objectSubmat.cols(), objectSubmat.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(objectSubmat, objectSubmatBitmap);
            imageViewOne.setImageBitmap(objectSubmatBitmap);

            //Create mask of the region inside the contour
            Mat regionMask = Mat.zeros(objectSubmat.rows(), objectSubmat.cols(), CvType.CV_8UC1);
            List<MatOfPoint> firstList = new ArrayList<MatOfPoint>();
            firstList.add(firstContour);
            Imgproc.drawContours(regionMask, firstList, 0, new Scalar(255), -1);

            //Preprocessing - color space conversion
            Mat regionHsv = new Mat();
            Imgproc.cvtColor(objectSubmat, regionHsv, Imgproc.COLOR_RGB2HSV);


            //Calculate Histogram
            List<Mat> sourceImageList = new ArrayList<Mat>();
            sourceImageList.add(regionHsv);
            Mat histogram = new Mat();
            //histogramMat.convertTo(histogramMat, CvType.CV_8UC2);
            Imgproc.calcHist(sourceImageList, new MatOfInt(2), regionMask, histogram, new MatOfInt(256), 
                    new MatOfFloat(0f, 256f));


        Highgui.imwrite("/mnt/sdcard/histogram.bmp", histogram);// check
        Mat hish = Highgui.imread("/mnt/sdcard/histogram.bmp");
        Bitmap histogramBitmap = 
                Bitmap.createBitmap(hish.cols(), hish.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(hish, histogramBitmap);
        imageViewTwo.setImageBitmap(histogramBitmap);

=================================================================================

EDIT:

Following is my translation of this tutorial.

I am getting this error:

06-26 19:49:45.649: E/cv::error()(1241): OpenCV Error: Assertion failed (j < nimages) in void cv::histPrepareImages(const cv::Mat *, int, const int *, const cv::Mat &, int, const int *, const float **, bool, vector<uchar *> &, vector<int> &, Size &, vector<double> &), file /hdd2/buildbot/slaves/slave_ardbeg1/50-SDK/opencv/modules/imgproc/src/histogram.cpp, line 148

Code:

//Get the image from file path
            rgbaMat = new Mat();
            rgbaMat = Highgui.imread(filePath);

            Bitmap rgbaMatBitmap = Bitmap.createBitmap(rgbaMat.cols(), rgbaMat.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(rgbaMat, rgbaMatBitmap);
            imageView.setImageBitmap(rgbaMatBitmap);

            //Preprocessing. Color space conversion
            Mat hsvMat = new Mat();
            Imgproc.cvtColor(rgbaMat, hsvMat, Imgproc.COLOR_BGR2HSV);

            //Split 3 channel Mat into 1 channel arrays
            List<Mat> channelsSeparated = new ArrayList<>();
            Core.split(hsvMat, channelsSeparated);

            //Artifacts
            MatOfInt numberOfBins = new MatOfInt(256); // From 0 to 255
            MatOfFloat rangeOfValues = new MatOfFloat(0f, 256f); // The upper bound is exclusive
            MatOfInt numberOfChannels = new MatOfInt(1);
            Mat valueHistogram = new Mat();

            //Calculate the histograms
            List<Mat> listOfHsvValueChannelMat = new ArrayList<>();
            listOfHsvValueChannelMat.add(channelsSeparated.get(2));
            Imgproc.calcHist(listOfHsvValueChannelMat, numberOfChannels, new Mat(), valueHistogram, numberOfBins, rangeOfValues);

            //Draw the histogram
            int histogramWidth = 512;
            int histogramHeight = 400;
            int binWidth = Math.round((float) (histogramWidth/256));
            Mat histogramImage = new Mat(histogramHeight, histogramWidth, CvType.CV_8UC1, new Scalar(0, 0, 0));

            //Normalize the histogram so its values fall in the range indicated by the parameters entered
            Core.normalize(valueHistogram, valueHistogram, 0, histogramImage.rows(), Core.NORM_MINMAX, -1, new Mat());

            //Finally, observe that to access the bin (in this case in this 1D-Histogram):
            for (int i=1; i<256; i++) {
                for (int j=1; j<256; j++) {
                    Core.line(histogramImage, 
                            new Point(binWidth*(i-1), histogramHeight-Math.round(valueHistogram.get(i-1, j-1)[0])), 
                            new Point(binWidth*(i), histogramHeight-Math.round(valueHistogram.get(i, j)[0])), 
                            new Scalar(2, 8, 0));
                }
            }

            //Display the histogram

            Bitmap histogramImageBitmap = Bitmap.createBitmap(histogramImage.cols(), histogramImage.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(histogramImage, histogramImageBitmap);
            imageViewOne.setImageBitmap(histogramImageBitmap);

Why does calcHist() method create an empty black histogram Mat?

I have written code to read in an image from gallery, then apply inRange() on it to find blue colored blob and create mask, then used findContours() to find contours, and the drawContours() to draw the contours, then boundingRect() to find a rectangle around the first contour, and then submat() to extract out the submatrix. Then I used Mat.zeroes() to create a mask from that rectangular submat. Then I applied Imgproc.calcHist() to create a histogram, and passed in the Mask as the 3rd argument so that the histogram calculated is that of the area inside the contour only.

Following is a screenshot from my Genymotion emulator, showing the original Mat with green contours around blue detected blobs and then the submatrix I mentioned and then the histogram created by calcHist(), which is black vertical line The question is why is it like this, where is my histogram graph?

image description

HISTOGRAM:

image descriptionimage description

Code:

//Get the image from file path
            rgbaMat = new Mat();
            rgbaMatCopy = new Mat();
            rgbaMat = Highgui.imread(filePath);
            rgbaMatCopy = Highgui.imread(filePath);

            //Preprocessing - color space conversion
            Imgproc.cvtColor(rgbaMat, rgbaMat, Imgproc.COLOR_BGR2RGB);
            Imgproc.cvtColor(rgbaMatCopy, rgbaMatCopy, Imgproc.COLOR_BGR2RGB);
            Mat hsvMat = new Mat();
            Imgproc.cvtColor(rgbaMatCopy, hsvMat, Imgproc.COLOR_RGB2HSV);

            //Make the mask from the detected blue colored blob(s)
            Scalar lowerThreshold = new Scalar(100, 146, 148);
            Scalar upperThreshold = new Scalar(134, 255, 255);
            Mat mask = new Mat();
            Core.inRange(hsvMat, lowerThreshold, upperThreshold, mask);

            //Preprocessing
            Mat dilatedMask = new Mat();
            Imgproc.dilate(mask, dilatedMask, new Mat());
            Imgproc.dilate(dilatedMask, dilatedMask, new Mat());

            //Find the contours
            contours = new ArrayList<>();
            Imgproc.findContours(dilatedMask, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

            //Draw the contours
            for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
                Imgproc.drawContours(rgbaMatCopy, contours, contourIdx, new Scalar(0, 255, 0), 1);
            }

            //Convert the mat with contours drawn to bitmap and display in imageView
            Bitmap theBitmap = Bitmap.createBitmap(rgbaMatCopy.cols(), rgbaMatCopy.rows(),
                    Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(rgbaMatCopy, theBitmap);
            imageView.setImageBitmap(theBitmap);

            //Find and cut out the smallest bounding rectangle around the first contour from the list of contours
            MatOfPoint firstContour = contours.get(0);
            Rect firstContourBoundingRect = Imgproc.boundingRect(firstContour);
            Mat objectSubmat = new Mat();
            objectSubmat = rgbaMat.submat(firstContourBoundingRect);

            Bitmap objectSubmatBitmap = Bitmap.createBitmap(objectSubmat.cols(), objectSubmat.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(objectSubmat, objectSubmatBitmap);
            imageViewOne.setImageBitmap(objectSubmatBitmap);

            //Create mask of the region inside the contour
            Mat regionMask = Mat.zeros(objectSubmat.rows(), objectSubmat.cols(), CvType.CV_8UC1);
            List<MatOfPoint> firstList = new ArrayList<MatOfPoint>();
            firstList.add(firstContour);
            Imgproc.drawContours(regionMask, firstList, 0, new Scalar(255), -1);

            //Preprocessing - color space conversion
            Mat regionHsv = new Mat();
            Imgproc.cvtColor(objectSubmat, regionHsv, Imgproc.COLOR_RGB2HSV);


            //Calculate Histogram
            List<Mat> sourceImageList = new ArrayList<Mat>();
            sourceImageList.add(regionHsv);
            Mat histogram = new Mat();
            //histogramMat.convertTo(histogramMat, CvType.CV_8UC2);
            Imgproc.calcHist(sourceImageList, new MatOfInt(2), regionMask, histogram, new MatOfInt(256), 
                    new MatOfFloat(0f, 256f));


        Highgui.imwrite("/mnt/sdcard/histogram.bmp", histogram);// check
        Mat hish = Highgui.imread("/mnt/sdcard/histogram.bmp");
        Bitmap histogramBitmap = 
                Bitmap.createBitmap(hish.cols(), hish.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(hish, histogramBitmap);
        imageViewTwo.setImageBitmap(histogramBitmap);

=================================================================================

EDIT:

Following is my translation of this tutorial.

I am getting this error:

06-26 19:49:45.649: E/cv::error()(1241): OpenCV Error: Assertion failed (j < nimages) in void cv::histPrepareImages(const cv::Mat *, int, const int *, const cv::Mat &, int, const int *, const float **, bool, vector<uchar *> &, vector<int> &, Size &, vector<double> &), file /hdd2/buildbot/slaves/slave_ardbeg1/50-SDK/opencv/modules/imgproc/src/histogram.cpp, line 148

Code:

//Get the image from file path
            rgbaMat = new Mat();
            rgbaMat = Highgui.imread(filePath);

            Bitmap rgbaMatBitmap = Bitmap.createBitmap(rgbaMat.cols(), rgbaMat.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(rgbaMat, rgbaMatBitmap);
            imageView.setImageBitmap(rgbaMatBitmap);

            //Preprocessing. Color space conversion
            Mat hsvMat = new Mat();
            Imgproc.cvtColor(rgbaMat, hsvMat, Imgproc.COLOR_BGR2HSV);

            //Split 3 channel Mat into 1 channel arrays
            List<Mat> channelsSeparated = new ArrayList<>();
            Core.split(hsvMat, channelsSeparated);

            //Artifacts
            MatOfInt numberOfBins = new MatOfInt(256); // From 0 to 255
            MatOfFloat rangeOfValues = new MatOfFloat(0f, 256f); // The upper bound is exclusive
            MatOfInt numberOfChannels = new MatOfInt(1);
            Mat valueHistogram = new Mat();

            //Calculate the histograms
            List<Mat> listOfHsvValueChannelMat = new ArrayList<>();
            listOfHsvValueChannelMat.add(channelsSeparated.get(2));
            Imgproc.calcHist(listOfHsvValueChannelMat, numberOfChannels, new Mat(), valueHistogram, numberOfBins, rangeOfValues);

            //Draw the histogram
            int histogramWidth = 512;
            int histogramHeight = 400;
            int binWidth = Math.round((float) (histogramWidth/256));
            Mat histogramImage = new Mat(histogramHeight, histogramWidth, CvType.CV_8UC1, new Scalar(0, 0, 0));

            //Normalize the histogram so its values fall in the range indicated by the parameters entered
            Core.normalize(valueHistogram, valueHistogram, 0, histogramImage.rows(), Core.NORM_MINMAX, -1, new Mat());

            //Finally, observe that to access the bin (in this case in this 1D-Histogram):
            for (int i=1; i<256; i++) {
                for (int j=1; j<256; j++) {
                    Core.line(histogramImage, 
                            new Point(binWidth*(i-1), histogramHeight-Math.round(valueHistogram.get(i-1, j-1)[0])), 
                            new Point(binWidth*(i), histogramHeight-Math.round(valueHistogram.get(i, j)[0])), 
                            new Scalar(2, 8, 0));
                }
            }

            //Display the histogram

            Bitmap histogramImageBitmap = Bitmap.createBitmap(histogramImage.cols(), histogramImage.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(histogramImage, histogramImageBitmap);
            imageViewOne.setImageBitmap(histogramImageBitmap);

Why does calcHist() method create an empty black histogram Mat?

I have written code to read in an image from gallery, then apply inRange() on it to find blue colored blob and create mask, then used findContours() to find contours, and the drawContours() to draw the contours, then boundingRect() to find a rectangle around the first contour, and then submat() to extract out the submatrix. Then I used Mat.zeroes() to create a mask from that rectangular submat. Then I applied Imgproc.calcHist() to create a histogram, and passed in the Mask as the 3rd argument so that the histogram calculated is that of the area inside the contour only.

Following is a screenshot from my Genymotion emulator, showing the original Mat with green contours around blue detected blobs and then the submatrix I mentioned and then the histogram created by calcHist(), which is black vertical line The question is why is it like this, where is my histogram graph?

image description

Code:

//Get the image from file path
            rgbaMat = new Mat();
            rgbaMatCopy = new Mat();
            rgbaMat = Highgui.imread(filePath);
            rgbaMatCopy = Highgui.imread(filePath);

            //Preprocessing - color space conversion
            Imgproc.cvtColor(rgbaMat, rgbaMat, Imgproc.COLOR_BGR2RGB);
            Imgproc.cvtColor(rgbaMatCopy, rgbaMatCopy, Imgproc.COLOR_BGR2RGB);
            Mat hsvMat = new Mat();
            Imgproc.cvtColor(rgbaMatCopy, hsvMat, Imgproc.COLOR_RGB2HSV);

            //Make the mask from the detected blue colored blob(s)
            Scalar lowerThreshold = new Scalar(100, 146, 148);
            Scalar upperThreshold = new Scalar(134, 255, 255);
            Mat mask = new Mat();
            Core.inRange(hsvMat, lowerThreshold, upperThreshold, mask);

            //Preprocessing
            Mat dilatedMask = new Mat();
            Imgproc.dilate(mask, dilatedMask, new Mat());
            Imgproc.dilate(dilatedMask, dilatedMask, new Mat());

            //Find the contours
            contours = new ArrayList<>();
            Imgproc.findContours(dilatedMask, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

            //Draw the contours
            for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
                Imgproc.drawContours(rgbaMatCopy, contours, contourIdx, new Scalar(0, 255, 0), 1);
            }

            //Convert the mat with contours drawn to bitmap and display in imageView
            Bitmap theBitmap = Bitmap.createBitmap(rgbaMatCopy.cols(), rgbaMatCopy.rows(),
                    Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(rgbaMatCopy, theBitmap);
            imageView.setImageBitmap(theBitmap);

            //Find and cut out the smallest bounding rectangle around the first contour from the list of contours
            MatOfPoint firstContour = contours.get(0);
            Rect firstContourBoundingRect = Imgproc.boundingRect(firstContour);
            Mat objectSubmat = new Mat();
            objectSubmat = rgbaMat.submat(firstContourBoundingRect);

            Bitmap objectSubmatBitmap = Bitmap.createBitmap(objectSubmat.cols(), objectSubmat.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(objectSubmat, objectSubmatBitmap);
            imageViewOne.setImageBitmap(objectSubmatBitmap);

            //Create mask of the region inside the contour
            Mat regionMask = Mat.zeros(objectSubmat.rows(), objectSubmat.cols(), CvType.CV_8UC1);
            List<MatOfPoint> firstList = new ArrayList<MatOfPoint>();
            firstList.add(firstContour);
            Imgproc.drawContours(regionMask, firstList, 0, new Scalar(255), -1);

            //Preprocessing - color space conversion
            Mat regionHsv = new Mat();
            Imgproc.cvtColor(objectSubmat, regionHsv, Imgproc.COLOR_RGB2HSV);


            //Calculate Histogram
            List<Mat> sourceImageList = new ArrayList<Mat>();
            sourceImageList.add(regionHsv);
            Mat histogram = new Mat();
            //histogramMat.convertTo(histogramMat, CvType.CV_8UC2);
            Imgproc.calcHist(sourceImageList, new MatOfInt(2), regionMask, histogram, new MatOfInt(256), 
                    new MatOfFloat(0f, 256f));


        Highgui.imwrite("/mnt/sdcard/histogram.bmp", histogram);// check
        Mat hish = Highgui.imread("/mnt/sdcard/histogram.bmp");
        Bitmap histogramBitmap = 
                Bitmap.createBitmap(hish.cols(), hish.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(hish, histogramBitmap);
        imageViewTwo.setImageBitmap(histogramBitmap);

=================================================================================

EDIT:

Following is my translation of this tutorial.

I am getting this error:

06-26 19:49:45.649: E/cv::error()(1241): OpenCV Error: Assertion failed (j < nimages) in void cv::histPrepareImages(const cv::Mat *, int, const int *, const cv::Mat &, int, const int *, const float **, bool, vector<uchar *> &, vector<int> &, Size &, vector<double> &), file /hdd2/buildbot/slaves/slave_ardbeg1/50-SDK/opencv/modules/imgproc/src/histogram.cpp, line 148

Code:

//Get the image from file path
            rgbaMat = new Mat();
            rgbaMat = Highgui.imread(filePath);

            Bitmap rgbaMatBitmap = Bitmap.createBitmap(rgbaMat.cols(), rgbaMat.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(rgbaMat, rgbaMatBitmap);
            imageView.setImageBitmap(rgbaMatBitmap);

            //Preprocessing. Color space conversion
            Mat hsvMat = new Mat();
            Imgproc.cvtColor(rgbaMat, hsvMat, Imgproc.COLOR_BGR2HSV);

            //Split 3 channel Mat into 1 channel arrays
            List<Mat> channelsSeparated = new ArrayList<>();
            Core.split(hsvMat, channelsSeparated);

            //Artifacts
            MatOfInt numberOfBins = new MatOfInt(256); // From 0 to 255
            MatOfFloat rangeOfValues = new MatOfFloat(0f, 256f); // The upper bound is exclusive
            MatOfInt numberOfChannels = new MatOfInt(1);
            Mat valueHistogram = new Mat();

            //Calculate the histograms
            List<Mat> listOfHsvValueChannelMat = new ArrayList<>();
            listOfHsvValueChannelMat.add(channelsSeparated.get(2));
            Imgproc.calcHist(listOfHsvValueChannelMat, numberOfChannels, new Mat(), valueHistogram, numberOfBins, rangeOfValues);

            //Draw the histogram
            int histogramWidth = 512;
            int histogramHeight = 400;
            int binWidth = Math.round((float) (histogramWidth/256));
            Mat histogramImage = new Mat(histogramHeight, histogramWidth, CvType.CV_8UC1, new Scalar(0, 0, 0));

            //Normalize the histogram so its values fall in the range indicated by the parameters entered
            Core.normalize(valueHistogram, valueHistogram, 0, histogramImage.rows(), Core.NORM_MINMAX, -1, new Mat());

            //Finally, observe that to access the bin (in this case in this 1D-Histogram):
            for (int i=1; i<256; i++) {
                for (int j=1; j<256; j++) {
                    Core.line(histogramImage, 
                            new Point(binWidth*(i-1), histogramHeight-Math.round(valueHistogram.get(i-1, j-1)[0])), 
                            new Point(binWidth*(i), histogramHeight-Math.round(valueHistogram.get(i, j)[0])), 
                            new Scalar(2, 8, 0));
                }
            }

            //Display the histogram

            Bitmap histogramImageBitmap = Bitmap.createBitmap(histogramImage.cols(), histogramImage.rows(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(histogramImage, histogramImageBitmap);
            imageViewOne.setImageBitmap(histogramImageBitmap);