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

Some easy techniques for auto contrast:

( 2015-11-07 15:48:54 -0600 )edit

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[0] = 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 ☺

( 2015-11-08 14:40:29 -0600 )edit

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.

( 2015-11-09 04:57:24 -0600 )edit

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

( 2015-11-09 08:51:09 -0600 )edit

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 ;=)

( 2015-11-09 09:28:42 -0600 )edit

@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 :(!

( 2015-11-11 02:19:00 -0600 )edit

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

( 2015-11-11 06:15:46 -0600 )edit

@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?

( 2015-11-13 08:47:13 -0600 )edit

@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!!!

( 2015-11-13 08:49:30 -0600 )edit

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.

( 2015-11-13 10:22:46 -0600 )edit

@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.

( 2015-11-16 07:45:41 -0600 )edit

for python users, here two functions create the same result.

def autoAdjustments_with_convertScaleAbs(img):
alow = img.min()
ahigh = img.max()
amax = 255
amin = 0

# calculate alpha, beta
alpha = ((amax - amin) / (ahigh - alow))
beta = amin - alow * alpha
# perform the operation g(x,y)= α * f(x,y)+ β
new_img = cv2.convertScaleAbs(img, alpha=alpha, beta=beta)

return [new_img, alpha, beta]


def autoAdjustments(img):
# create new image with the same size and type as the original image
new_img = np.zeros(img.shape, img.dtype)

# calculate stats
alow = img.min()
ahigh = img.max()
amax = 255
amin = 0

# access each pixel, and auto adjust
for x in range(img.shape[1]):
for y in range(img.shape[0]):
a = img[x, y]
new_img[x, y] = amin + (a - alow) * ((amax - amin) / (ahigh - alow))

return new_img


more

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

more