How to make auto-adjustments(brightness and contrast) for image Android Opencv Image Correction i'm using OpenCV for Android.
I would like to know,how to make image correction(auto adjustments of brightness/contrast) for image(bitmap) in android via OpenCV or that can be done by native ColorMatrixFilter from Android!??

I tried to google,but didn't found good tutorials/examples.
So how can i achieve my goal? Any ideas?
Thanks!

edit retag close merge delete

1

Sort by » oldest newest most voted Brightness and contrast is linear operator with parameter alpha and beta

O(x,y) = alpha * I(x,y) + beta

In OpenCV you can do this with convertTo.

The question here is how to calculate alpha and beta automatically ?

Looking at histogram, alpha operates as color range amplifier, beta operates as range shift.

Automatic brightness and contrast optimization calculates alpha and beta so that the output range is 0..255.

input range = max(I) - min(I)
wanted output range = 255;
alpha = output range / input range =  255 / ( max(I) - min(I) )

You can calculate beta so that min(O) = 0;

min(O) = alpha * min(I) + beta
beta = -min(I) * alpha

Histogram Wings Cut (clipping)

To maximize the result of it's useful to cut out some color with few pixels.

This is done cutting left right and wings of histogram where color frequency is less than a value (typically 1%). Calculating cumulative distribution from the histogram you can easly find where to cut.

may be sample chart helps to understand: EDIT: Histogram Normalization vs Equalization

By the way BrightnessAndContrastAuto could be named normalizeHist because it works on BGR and gray images stretching the histogram to the full range without touching bins balance. If input image has range 0..255 BrightnessAndContrastAuto will do nothing.

Histogram equalization and CLAE works only on gray images and they change grays level balancing. look at the images below: EDIT2: Add support for BGRA images too

EDIT3: Correct error in "restore alpha channel from source "

however here is the code:

/**
*  \brief Automatic brightness and contrast optimization with optional histogram clipping
*  \param [in]src Input image GRAY or BGR or BGRA
*  \param [out]dst Destination image
*  \param clipHistPercent cut wings of histogram at given percent tipical=>1, 0=>Disabled
*  \note In case of BGRA image, we won't touch the transparency
*/
void BrightnessAndContrastAuto(const cv::Mat &src, cv::Mat &dst, float clipHistPercent=0)
{

CV_Assert(clipHistPercent >= 0);
CV_Assert((src.type() == CV_8UC1) || (src.type() == CV_8UC3) || (src.type() == CV_8UC4));

int histSize = 256;
float alpha, beta;
double minGray = 0, maxGray = 0;

//to calculate grayscale histogram
cv::Mat gray;
if (src.type() == CV_8UC1) gray = src;
else if (src.type() == CV_8UC3) cvtColor(src, gray, CV_BGR2GRAY);
else if (src.type() == CV_8UC4) cvtColor(src, gray, CV_BGRA2GRAY);
if (clipHistPercent == 0)
{
// keep full available range
cv::minMaxLoc(gray, &minGray, &maxGray);
}
else
{
cv::Mat hist; //the grayscale histogram

float range[] = { 0, 256 };
const float* histRange = { range };
bool uniform = true;
bool accumulate = false;
calcHist(&gray, 1, 0, cv::Mat (), hist, 1, &histSize, &histRange, uniform, accumulate);

// calculate cumulative distribution from the histogram
std::vector<float> accumulator(histSize);
accumulator = hist.at<float>(0);
for (int i = 1; i < histSize; i++)
{
accumulator[i] = accumulator[i - 1] + hist.at<float>(i);
}

// locate points that cuts at required value
float max = accumulator.back();
clipHistPercent *= (max / 100.0); //make percent as absolute
clipHistPercent /= 2.0; // left and right wings
// locate left cut
minGray = 0;
while (accumulator[minGray] < clipHistPercent)
minGray++;

// locate right cut
maxGray = histSize - 1;
while (accumulator[maxGray] >= (max - clipHistPercent))
maxGray--;
}

// current range
float inputRange = maxGray ...
more

1

Nice answer @pklab. Well done. +1 from me ☺

Funny, it seems that the Gimp white balance command uses the same principle.

I also forgot to mention that the histogram equalization is a built-in functionnality in OpenCV...

There is also the CLAHE function (Contrast Limited Adaptive Histogram Equalization) that could be used but there is some parameters to tune to use it.

@pklab Thanks for great answer,mate! But i have some problem with reproduce in Java version.

The code is plain... it's should be easy to translate in Java, may be you sould use ArrayList instead of std::vector@theodore , @VeTaLio thanks for apreciation ... if it works you could accept the answer ;=)

@pklab yes,that is not a big problem. Ill mark your question as solution,but little bit later,ok:) ? So have some questions about how to reproduce in java,because some stuff doesn't clear for me :(!

@VeTaLio you could do it yourself in Java... it's a simple exercise, feel free to ask about stuffs doesn't clear for you

@pklab as i understand you correct,that wingsCutPercent i need to put manually(as you said,1% => 0.01f value or i need to extract) ? Also,i got a problem,when i'm doing picture,converting via BitmapToMat,my source Mat have type CV_8UC4. So i didn't use your block of code if /else if(where you put CvtColor). I'm doing this directly => CvtColor(source,gray, CV_BGR2GRAY); and the problem occurs here: calcHist - first elemnt,in java there is arraylist of Mat. So via converters i'm trying to convert into ArrayList<mat> and i getting this exception :
java.lang.IllegalArgumentException: CvType.CV_32SC2 != m.type() || m.cols()!=1 I need to convert this for CvType.CV_32SC2?

@pklab once i ask this question and didn't get answer => my old post http://answers.opencv.org/question/74... is similiar problem with Converters! Thanks!!!

OK, 2nd edit...check new code, it supports BGRA images too. wingsCutPercent (now clipHistPercent) is a percent than if you want to cut 1% use 1.0. Howhever it's optional.

@pklab so i've translated to java and problem is that i'm getting too much brightness and contrast. I will upload some example to show you.

Does anyone has been able to convert this to C# or VB.NET? I am having a hard time getting this converted.

more

Stats

Asked: 2015-11-06 02:15:04 -0500

Seen: 36,052 times

Last updated: Nov 17 '15