Using OpenCV4Android, I wanted to calculate, draw and display the histogram (in an ImageView) of the red color channel in a bgr image. I have tried to follow this Python (?) tutorial and imitate it using Android API. I have also logged out some simple statements after each step which tells me that the step has executed successfully. I get an OpenCV Error and through these log statements, I know that it has occured in my calcHist()
call.
Following is from Logcat:
06-26 23:22:26.160: I/MainActivity(1299): GRANNY rgbaMat read successfully!
06-26 23:22:26.160: I/MainActivity(1299): GRANNY rgbaMatBitmap added to imageView successfully!
06-26 23:22:26.160: I/MainActivity(1299): GRANNY Color space converted to HSV successfully!
06-26 23:22:26.160: I/MainActivity(1299): GRANNY Core.split() carried out successfully!
06-26 23:22:26.164: E/cv::error()(1299): 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
06-26 23:22:26.180: A/libc(1299): Fatal signal 11 (SIGSEGV) at 0x99703ff4 (code=2), thread 1299 (sts.testsixcopy)
Here is my code. The comments in code show what each step is aiming to do. Please tell me what mistake I am making and how to correct it?
// Get the image from file path
rgbaMat = new Mat();
rgbaMat = Highgui.imread(filePath);
Log.i(TAG, "GRANNY rgbaMat read successfully!");// check
Bitmap rgbaMatBitmap = Bitmap.createBitmap(rgbaMat.cols(), rgbaMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(rgbaMat, rgbaMatBitmap);
imageView.setImageBitmap(rgbaMatBitmap);
Log.i(TAG, "GRANNY rgbaMatBitmap added to imageView successfully!");// check
// Split 3 channel Mat into 1 channel arrays
List<Mat> separatedChannelsList = new ArrayList<>();
Core.split(rgbaMat, separatedChannelsList);
Log.i(TAG, "GRANNY Core.split() carried out successfully!");// check
// Start configuring histogram
List<Mat> listOfRedChannelMat = new ArrayList<>();
listOfRedChannelMat.add(separatedChannelsList.get(2));
MatOfInt numberOfBins = new MatOfInt(256); // From 0 to 255
MatOfFloat rangeOfValues = new MatOfFloat(0f, 256f); // The upper bound is exclusive
//boolean uniform = true;//does not exist in android api
boolean accumulate = false;
MatOfInt numberOfDims = new MatOfInt(1);
Mat redHistogram = new Mat();
// Calculate the histograms
Imgproc.calcHist(listOfRedChannelMat, numberOfDims, new Mat(), redHistogram, numberOfBins, rangeOfValues, accumulate);
Log.i(TAG, "GRANNY Imgproc.calcHist() carried out successfully!");// check
// Draw the histogram
int histogramWidth = 512;
int histogramHeight = 400;
int binWidth = Math.round( (float) (histogramWidth / numberOfBins.get(0, 0)[0]) );
Mat histogramImage = new Mat(histogramHeight, histogramWidth, CvType.CV_8UC3, new Scalar(0, 0, 0));
// Normalize the histogram so its values fall in the range indicated by the parameters entered
Core.normalize(redHistogram, valueHistogram, 0, histogramImage.rows(), Core.NORM_MINMAX, -1, new Mat());
Log.i(TAG, "GRANNY Core.normalize() carried out successfully!");// check
// Finally, observe that to access the bin (in this case in this 1D-Histogram):
for (int i = 1; i < 256; i++) {
Core.line(histogramImage,
new Point(binWidth * (i - 1), histogramHeight - Math.round(redHistogram.get(i - 1, 0)[0])),
new Point(binWidth * (i), histogramHeight - Math.round( redHistogram.get(i,0)[0])),
new Scalar(255, 0, 0),
2,
8,
0);
}
Log.i(TAG, "GRANNY Core.line() carried out successfully 255 times!");// check
// Display the histogram
Bitmap histogramImageBitmap = Bitmap.createBitmap(histogramImage.cols(), histogramImage.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(histogramImage, histogramImageBitmap);
imageViewOne.setImageBitmap(histogramImageBitmap);
Log.i(TAG, "GRANNY Histogram image set to imageViewTwo successfully!");// check