OpenCV in advanced Android development: drawing a histogram

published in Android Development, Tutorials
by Slawomir Onyszko

In the last tutorial we’ve covered OpenCV and Android Studio project integration. This time we’ll try to make actual use of this setup. A code sample that we’ve used in a commercial Android application can be found on our GitHub page.

Extract the data from an image

An image histogram is a chart that represents the distribution (frequency of occurrence) of pixels within an image.

To calculate the input data, the best option is to use the Imgproc.calcHist method, provided OpenCV. It will help us to create the histogram from a set of arrays (mostly image data).

advanced Android development

Image histogram showing distribution of Brightness and Red (source: en.wikipedia.org)

 


// Create the required arrays and convert the bitmap (our image) 
// so that it fits the array.
Mat rgba = new Mat();
Utils.bitmapToMat(bitmap, rgba);

// Get the bitmap size.
Size rgbaSize = rgba.size();

Now we are ready to configure our histograms:


// Set the amount of bars in the histogram.
int histSize = 256;
MatOfInt histogramSize = new MatOfInt(histSize);

// Set the height of the histogram and width of the bar.
int histogramHeight = (int) rgbaSize.height;
int binWidth = 5;

// Set the value range.
MatOfFloat histogramRange = new MatOfFloat(0f, 256f);

// Create two separate lists: one for colors and one for channels (these will be used as separate datasets).
Scalar[] colorsRgb = new Scalar[]{new Scalar(200, 0, 0, 255), new Scalar(0, 200, 0, 255), new Scalar(0, 0, 200, 255)};
MatOfInt[] channels = new MatOfInt[]{new MatOfInt(0), new MatOfInt(1), new MatOfInt(2)};

// Create an array to be saved in the histogram and a second array, on which the histogram chart will be drawn.
Mat[] histograms = new Mat[]{new Mat(), new Mat(), new Mat()};
Mat histMatBitmap = new Mat(rgbaSize, rgba.type());

Separating channels

Now we must calculate the histogram for each channel, standardize the datasets and then draw it.


for (int i = 0; i < channels.length; i++) {
    Imgproc.calcHist(Collections.singletonList(rgba), channels[i], new Mat(), histograms[i], histogramSize, histogramRange);
    Core.normalize(histograms[i], histograms[i], histogramHeight, 0, Core.NORM_INF);
    for (int j = 0; j < histSize; j++) {
        Point p1 = new Point(binWidth * (j - 1), histogramHeight - Math.round(histograms[i].get(j - 1, 0)[0]));
        Point p2 = new Point(binWidth * j, histogramHeight - Math.round(histograms[i].get(j, 0)[0]));
        Imgproc.line(histMatBitmap, p1, p2, colorsRgb[i], 2, 8, 0);
    }
}

Using the Imgproc.calcHist method, calculate the histogram for each channel. The following parameters can be used:

  • List<Mat> images: array photos list
  • MatOflnt channels: channels list
  • Mat mask: optional mask
  • Mat hist: an array in which the calculations will be saved
  • MatOflnt histSize: the amount of the bars for every used dimension
  • MatOfFloat rangers: the value range measured for all the dimensions

Normalize the data

After calculating the histogram, standardize it in such a way so his values fit into the range indicated by the given parameters according to the Core.normalize method.

The method takes the following parameters:

  • Mat src: a source array
  • Mat dst: an initial array
  • double alpha
  • double beta
  • int norm_type

Draw the chart

In the second for loop, we create points for each histogram bar and draw a line based on that.


for (int j = 0; j < histSize; j++) {
    Point p1 = new Point(binWidth * (j - 1), histogramHeight - Math.round(histograms[i].get(j - 1, 0)[0]));
    Point p2 = new Point(binWidth * j, histogramHeight - Math.round(histograms[i].get(j, 0)[0]));
    Imgproc.line(histMatBitmap, p1, p2, colorsRgb[i], 2, 8, 0);
}

At the end we display our initial bitmap and create a second one (made out of our arrays) to be displayed as well.


// Don't do that at home or work. It's for visualization purpose.
BitmapHelper.showBitmap(this, bitmap, imageView);

Bitmap histBitmap = Bitmap.createBitmap(histMatBitmap.cols(), histMatBitmap.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(histMatBitmap, histBitmap);
BitmapHelper.showBitmap(this, histBitmap, histogramView);

That’s all! Let’s see the result here:

Android app building

Histogram visualisation

As you can see, it’s much easier to calculate and draw a histogram with OpenCV itself when building an Android app.


A code sample that we’ve used in a commercial Android application can be found on our GitHub page.


 

Slawomir Onyszko Mobile Developer

Sławek is our mobile developer who mostly takes care of creating Android applications. He is constantly enhancing his skills of advanced Android app development and he wants to share this knowledge via Zaven’s blog. In his spare time Sławek enjoys watching a good movie at the cinema.

Popular posts

Effortless deployment of Azure CosmosDB JS functions with GitLab-CI

Effortless deployment of Azure CosmosDB JS functions with GitLab-CI

Working with CosmosDB JavaScript triggers and stored procedures can be problematic, especially when your application consists of three or four separate development environments. The solution we need is found in the effortless deployment of Azure CosmosDB JS functions with GitLab-CI.

Read more
Interviews with startup founders: Fonn Byggemappen

Interviews with startup founders: Fonn Byggemappen

Fonn Byggemappen is an iOS, Android and web application for construction industry projects. The tool’s co-founder Jan Tore Grindheim told us about the beginnings and crucial moments of the app.

Read more
Core ML: Machine Learning for iOS

Core ML: Machine Learning for iOS

You have probably heard phrases like “Machine Learning” or “Artificial Intelligence” without knowing exactly what they mean. In this article, I will shed some light on “What Machine Learning is” by showing you a Core ML iOS sample.

Read more
Mobile Apps

Get your mobile app in 3 easy steps!

1

Spec out

with the help of our
business analyst

2

Develop

design, implement
and test, repeat!

3

Publish

get your app out
to the stores

Contact us

Hire us now!

back to top