[PYTHON] Gamma correction without using OpenCV

Introduction

Gamma correction is a method for converting brightness and contrast in image processing.

The formula is simple, if the input is x and the output is y $ y = 255 ・ (\ frac {x} {255}) ^ \ frac {1} {\ gamma} $ Can be represented by. By changing the value of this $ \ gamma $, you can change the pixel value of the output image. If $ \ gamma $ is greater than 1, it will be brighter overall, and if $ \ gamma $ is less than 1, it will be darker overall. The figure below shows the relationship between input and output when the value of $ \ gamma $ is changed. gamma.png

In some cases, $ \ frac {1} {\ gamma} $ in the formula is just $ \ gamma $. In that case, the convex on the top and the convex on the bottom are switched.

The image processing library OpenCV also has a gamma correction function. As you can see from the formula, it's so easy that you can create a gamma correction function with just numpy.

Actually try

Let's create a gamma correction function based on the formula. For a moment.

#python version 3.6.5
import numpy as np               #version 1.14.3
import matplotlib.pyplot as plt 
from skimage import io           #scikit image version 0.13.1
plt.rcParams["font.family"] = "Times New Roman"
plt.rcParams["font.size"] = 12

def gammma(x, r):
    """
Gamma correction y=255*(x/255) 
x Input image
r Gamma correction coefficient
    """
    x = np.float64(x)
    y = x/255.
    y = y **(1/r)
    return np.uint8(255*y)

Also create a function to create and display a histogram for each RGB. (Reinventing the wheel ... omitted below)

def hist_rgb(img):
    #Function to create a histogram of rgb
    #The variable res that stores the result[brightness, channel]
    res = np.zeros([256, 3])   
    for channel in range(3):
        #Extract a channel
        img_tmp = img[:,:,channel]
        #Make the image one-dimensional
        img_tmp =img_tmp.reshape(img_tmp.size)
        for i in img_tmp:
            res[i, channel] += 1
    return res

def mat_hist_rgb(hist, ylim = 0.06):
    #hist_Display the histogram calculated by the function of rgb
    x = np.arange(hist.shape[0])
    #Specify the color of the histogram
    colors = ["red", "green", "blue"]
    for i, color in enumerate(colors):
        plt.bar(x,hist[:, i], color=color, alpha=0.3, width=1.0)
    plt.xlabel("Brightness")
    plt.ylabel("Frequency")
    plt.xlim(0, 255)
    plt.yticks([])
    plt.show()

First, read lenna and display the histogram of the original image.

img_lena = io.imread("lena_std.tif")
hist_lena = hist_rgb(img_lena)
mat_hist_rgb(hist_lena)

lena_std.jpg origin.png

You can see that there is a lot of red component.

When $ \ gamma = 0.5 $

img_gamma = gammma(img_lena, r=0.5)
io.imsave("r05.png ", img_gamma)
mat_hist_rgb(hist_rgb(img_gamma))

r05.png

If you look at the histogram, you can see that it is much darker than the original image.

05hist.png

When $ \ gamma = 2.0 $

img_gamma = gammma(img_lena, r=2.0)
io.imsave("r05.png ", img_gamma)
mat_hist_rgb(hist_rgb(img_gamma))

It will be considerably brighter.

r20.png

20.png

Correct only specific colors

If you look at the histogram, you can see that Lenna's image is a reddish image overall. Therefore, gamma correction is applied only to a specific color, in this case the red channel.

#Specify RGB to be converted by channel, R=0, G=1, B=2
channel = 0

​#Copy the original image
img_gamma = np.copy(img_lena)
​
#Gamma correction
img_gamma[:,:,channel] = gammma(img_lena[:,:,channel], r=0.3)
io.imsave("red.png ", img_gamma)
mat_hist_rgb(hist_rgb(img_gamma))

Since $ \ gamma = 0.3 $, the red component is weakened. This feels more natural.

red.png

rr.png

References

Digital Image Processing [Revised 2nd Edition], Public Interest Incorporated Foundation Image Information Education Promotion Association (2020)

Recommended Posts

Gamma correction without using OpenCV
Modulo without using%
Write FizzBuzz without using "="
Quicksort without using sort
Modulo without using%
Bubble sort without using sort
Write FizzBuzz without using "="
Quicksort without using sort
Gamma correction without using OpenCV
I tried "gamma correction" of the image with Python + OpenCV
Feature detection using opencv (corner detection)
[Python] Using OpenCV with Python (Basic)
Try using OpenCV on Windows
Using OpenCV with Python @Mac
Create a striped illusion with gamma correction for Python3 and openCV3
Vertical Tower of Pisa using OpenCV
[Python] Using OpenCV with Python (Image Filtering)
Judgment of backlit image using OpenCV
[Python] Using OpenCV with Python (Image transformation)
[Python3] Google translate google translate without using api
[Python] Using OpenCV with Python (Edge Detection)
I tried using GrabCut of OpenCV
Horizon processing using OpenCV morphology transformation