Image Histogram Equalizer in Android Using OpenCV

In our last android OpenCV tutorial, we covered how to draw image histogram in android using OpenCV. It is important you refer to this tutorial before you continue reading.

When we talked about image histogram, we are interested in using image histogram graph to analyze the distribution of pixel intensity in an image. Data obtain from a histogram graph can be use to enhance an image.

OpenCV Histogram Equalizer

In other to understand what a histogram equalizer can do for us. Imagine you have an image with pixel intensity distribution located at one part of the image which reduces contrast, we can use histogram equalizer to adjust image intensity to enhance its contrast.

One of the most outstanding gain with OpenCV is that it has a lot of built-in methods that have abstracted the underlining mathematics and algorithms for us.

You can easily call any OpenCV method and it will get the job done for you. It sounds good but for you to implement something out of the box it is important to understand the mathematics and algorithms behind every OpenCV feature.

App Screenshots

android histogram equalizer

I could not find a better free copyright picture for this tutorial so I decided to use this one. You can search online and test the application with a blur or old picture.

1. CREATE A NEW ANDROID PROJECT

  • Open Android Studio
  • Go to file menu
  • Select  new
  • Enter project name
  • Enter activity name
  • Keep other default settings
  • Click on finish button to create a new android project

2. OPEN ACTIVITY_HISTOGRAM_EQUALIZER.XML

Add some view widgets in the layout like the code below

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".histogramequalizer.HistogramEqualizerActivity">

    <android.support.v7.widget.AppCompatImageView
        android:id="@+id/source_image"
        android:layout_width="300dp"
        android:layout_height="200dp"
        android:layout_marginTop="20dp"
        android:layout_gravity="center"
        android:src="@drawable/sound"
        android:contentDescription="@string/app_name"/>

    <Button
        android:id="@+id/equalizer_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="12dp"
        android:background="@color/colorAccent"
        android:text="@string/show_histogram_equalizer"
        android:padding="12dp"
        android:textColor="@color/colorWhite"
        android:contentDescription="@string/app_name"/>


    <android.support.v7.widget.AppCompatImageView
        android:id="@+id/show_equalizer"
        android:layout_width="300dp"
        android:layout_height="200dp"
        android:layout_marginTop="20dp"
        android:layout_gravity="center"
        android:contentDescription="@string/app_name"/>


</android.support.v7.widget.LinearLayoutCompat>

3. HistogramEqualizer.java

In order to create an image histogram equalizer using OpenCV, we are going to follow the steps below.

1. Obtain a Bitmap object from ImageView with the code below

Bitmap bitmap = ((BitmapDrawable)sourceImage.getDrawable()).getBitmap();

2. Convert the Bitmap Object to a Mat object like below.

Utils.bitmapToMat(bitmap, sourceMat);

3. Convert the Mat object color channel from RGB to GRAY.

Mat destinationMat = new Mat(sourceMat.size(), sourceMat.type());
Imgproc.cvtColor(sourceMat, sourceMat, Imgproc.COLOR_RGB2GRAY);

4. Apply OpenCV histogram equalizer static method (equalizeHist())  using source Mat object and output to destination Mat object.

Imgproc.equalizeHist(sourceMat, destinationMat);

5. Convert the destination Mat object to Bitmap and assign the Bitmap to an ImageView.

 Bitmap equalizerBitmap = Bitmap.createBitmap(sourceMat.cols(), sourceMat.rows(), Bitmap.Config.ARGB_8888);
 Utils.matToBitmap(destinationMat, equalizerBitmap);

//show equalized image
equalizerImage.setImageBitmap(equalizerBitmap);

The complete code in the HistogramEqualizerActivity.java is shown below.

package inducesmile.com.opencvexample.histogramequalizer;

import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatImageView;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import inducesmile.com.opencvexample.R;

public class HistogramEqualizerActivity extends AppCompatActivity {

    private static final String TAG = HistogramEqualizerActivity.class.getSimpleName();

    private AppCompatImageView sourceImage, equalizerImage;


    private BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                    break;
                default:
                    super.onManagerConnected(status);
                    break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_histogram_equalizer);

        sourceImage = (AppCompatImageView)findViewById(R.id.source_image);
        equalizerImage = (AppCompatImageView)findViewById(R.id.show_equalizer);

        //get bitmap
        Bitmap bitmap = bitmapFromImageView();


        Button equalizerButton = (Button)findViewById(R.id.equalizer_button);
        equalizerButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Mat sourceMat = new Mat();
                Utils.bitmapToMat(bitmap, sourceMat);

                Mat destinationMat = new Mat(sourceMat.size(), sourceMat.type());
                Imgproc.cvtColor(sourceMat, sourceMat, Imgproc.COLOR_RGB2GRAY);

                Imgproc.equalizeHist(sourceMat, destinationMat);

                Bitmap equalizerBitmap = Bitmap.createBitmap(sourceMat.cols(), sourceMat.rows(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(destinationMat, equalizerBitmap);

                //show equalized image
                equalizerImage.setImageBitmap(equalizerBitmap);
            }
        });

    }

    private Bitmap bitmapFromImageView(){
        return ((BitmapDrawable)sourceImage.getDrawable()).getBitmap();
    }

    @Override
    public void onResume(){
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_11, this, baseLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            baseLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }
}

You can find the source code for this tutorial and other tutorials related to android OpenCV examples in this Github link

In my next OpenCV tutorial I will look at image noise removal using low-pass filter kernel like Average Filter.

If you have any questions or suggestion on how to improve this tutorial, kindly use the comment box below or contact us through the contact page.

 

Add a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.