Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I increase the contrast of an image in Python OpenCV

I am new to Python OpenCV. I have read some documents and answers here but I am unable to figure out what the following code means:

if (self.array_alpha is None):     self.array_alpha = np.array([1.25])     self.array_beta = np.array([-100.0])  # add a beta value to every pixel  cv2.add(new_img, self.array_beta, new_img)                      # multiply every pixel value by alpha cv2.multiply(new_img, self.array_alpha, new_img)   

I have come to know that Basically, every pixel can be transformed as X = aY + b where a and b are scalars.. Basically, I have understood this. However, I did not understand the code and how to increase contrast with this.

Till now, I have managed to simply read the image using img = cv2.imread('image.jpg',0)

Thanks for your help

like image 327
tsaebeht Avatar asked Sep 03 '16 14:09

tsaebeht


People also ask

How do I change the contrast of an image in OpenCV?

To change the contrast, multiply the pixel values with some constant. For example, if multiply all the pixel values of an image by 2, then the pixel's value will be doubled, and the image will look sharper.


2 Answers

I would like to suggest a method using the LAB color channel. Wikipedia has enough information regarding what the LAB color channel is about.

I have done the following using OpenCV 3.0.0 and python:

import cv2  #-----Reading the image----------------------------------------------------- img = cv2.imread('Dog.jpg', 1) cv2.imshow("img",img)   #-----Converting image to LAB Color model-----------------------------------  lab= cv2.cvtColor(img, cv2.COLOR_BGR2LAB) cv2.imshow("lab",lab)  #-----Splitting the LAB image to different channels------------------------- l, a, b = cv2.split(lab) cv2.imshow('l_channel', l) cv2.imshow('a_channel', a) cv2.imshow('b_channel', b)  #-----Applying CLAHE to L-channel------------------------------------------- clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8)) cl = clahe.apply(l) cv2.imshow('CLAHE output', cl)  #-----Merge the CLAHE enhanced L-channel with the a and b channel----------- limg = cv2.merge((cl,a,b)) cv2.imshow('limg', limg)  #-----Converting image from LAB Color model to RGB model-------------------- final = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR) cv2.imshow('final', final)  #_____END_____# 

You can run the code as it is. To know what CLAHE (Contrast Limited Adaptive Histogram Equalization)is about, you can again check Wikipedia.

like image 187
Jeru Luke Avatar answered Oct 06 '22 19:10

Jeru Luke


For Python, I haven't found an OpenCV function that provides contrast. As others have suggested, there are some techniques to automatically increase contrast using a very simple formula.

In the official OpenCV docs, it is suggested that this equation can be used to apply both contrast and brightness at the same time:

new_img = alpha*old_img + beta

where alpha corresponds to a contrast and beta is brightness. Different cases

alpha 1  beta 0      --> no change   0 < alpha < 1        --> lower contrast   alpha > 1            --> higher contrast   -127 < beta < +127   --> good range for brightness values 

In C/C++, you can implement this equation using cv::Mat::convertTo, but we don't have access to that part of the library from Python. To do it in Python, I would recommend using the cv::addWeighted function, because it is quick and it automatically forces the output to be in the range 0 to 255 (e.g. for a 24 bit color image, 8 bits per channel). You could also use convertScaleAbs as suggested by @nathancy.

import cv2 img = cv2.imread('input.png') # call addWeighted function. use beta = 0 to effectively only operate one one image out = cv2.addWeighted( img, contrast, img, 0, brightness) output = cv2.addWeighted 

The above formula and code is quick to write and will make changes to brightness and contrast. But they yield results that are significantly different than photo editing programs. The rest of this answer will yield a result that will reproduce the behavior in the GIMP and also LibreOffice brightness and contrast. It's more lines of code, but it gives a nice result.

Contrast

In the GIMP, contrast levels go from -127 to +127. I adapted the formulas from here to fit in that range.

f = 131*(contrast + 127)/(127*(131-contrast))
new_image = f*(old_image - 127) + 127 = f*(old_image) + 127*(1-f)

To figure out brightness, I figured out the relationship between brightness and levels and used information in this levels post to arrive at a solution.

#pseudo code if brightness > 0     shadow = brightness     highlight = 255 else:     shadow = 0     highlight = 255 + brightness new_img = ((highlight - shadow)/255)*old_img + shadow 

brightness and contrast in Python and OpenCV

Putting it all together and adding using the reference "mandrill" image from USC SIPI:

import cv2 import numpy as np  # Open a typical 24 bit color image. For this kind of image there are # 8 bits (0 to 255) per color channel img = cv2.imread('mandrill.png')  # mandrill reference image from USC SIPI  s = 128 img = cv2.resize(img, (s,s), 0, 0, cv2.INTER_AREA)  def apply_brightness_contrast(input_img, brightness = 0, contrast = 0):          if brightness != 0:         if brightness > 0:             shadow = brightness             highlight = 255         else:             shadow = 0             highlight = 255 + brightness         alpha_b = (highlight - shadow)/255         gamma_b = shadow                  buf = cv2.addWeighted(input_img, alpha_b, input_img, 0, gamma_b)     else:         buf = input_img.copy()          if contrast != 0:         f = 131*(contrast + 127)/(127*(131-contrast))         alpha_c = f         gamma_c = 127*(1-f)                  buf = cv2.addWeighted(buf, alpha_c, buf, 0, gamma_c)      return buf   font = cv2.FONT_HERSHEY_SIMPLEX fcolor = (0,0,0)  blist = [0, -127, 127,   0,  0, 64] # list of brightness values clist = [0,    0,   0, -64, 64, 64] # list of contrast values   out = np.zeros((s*2, s*3, 3), dtype = np.uint8)  for i, b in enumerate(blist):     c = clist[i]     print('b, c:  ', b,', ',c)     row = s*int(i/3)     col = s*(i%3)          print('row, col:   ', row, ', ', col)          out[row:row+s, col:col+s] = apply_brightness_contrast(img, b, c)     msg = 'b %d' % b     cv2.putText(out,msg,(col,row+s-22), font, .7, fcolor,1,cv2.LINE_AA)     msg = 'c %d' % c     cv2.putText(out,msg,(col,row+s-4), font, .7, fcolor,1,cv2.LINE_AA)          cv2.putText(out, 'OpenCV',(260,30), font, 1.0, fcolor,2,cv2.LINE_AA)  cv2.imwrite('out.png', out) 

enter image description here

I manually processed the images in the GIMP and added text tags in Python/OpenCV:
enter image description here

Note: @UtkarshBhardwaj has suggested that Python 2.x users must cast the contrast correction calculation code into float for getting floating result, like so:

... if contrast != 0:         f = float(131*(contrast + 127))/(127*(131-contrast)) ... 
like image 23
bfris Avatar answered Oct 06 '22 20:10

bfris