# 【 Digital image processing series 3 】 image enhancement ： linear , piecewise linear , logarithm , Inverse logarithm , Power law ( gamma ) Transformation , histogram equalization

This series python edition ：python3.5.4

This series opencv-python edition ：opencv-python3.4.2.17

The development environment used in this series is jupyter notebook, It's a python Interactive development environment based on , The test is very convenient , And integrated vim operation , Installation tutorial can refer to ：

windows upper jupyter notebook Subject background , Font and extension configuration ( integrate vim Environmental Science )

<https://blog.csdn.net/feilong_csdn/article/details/80186276>

Above 【 Digital image processing series 2 】 Basic concepts ： brightness , contrast ratio , saturation , sharpening , resolving power

<https://blog.csdn.net/feilong_csdn/article/details/82755816>

We learned the concept and formation principle of digital image , The brightness of the image is analyzed in practice and comparison , contrast ratio , saturation , sharpening , Resolution and other attributes . The basic knowledge of image is introduced , After that, we will focus on digital image processing and analysis , This paper starts from

Image gray level transformation and enhancement , This can also be said to be very important in image preprocessing , Bar ~~

Old rules , Above ：

Images after image enhancement ：

<> One , Image enhancement knowledge preheating

<>1, Why do image enhancement

In the process of image formation , There are many factors that affect the image clarity , Several common factors affecting image clarity are listed below ：

* The light is not even enough , This will cause the image grayscale to be too concentrated

* from CCD( camera ) Image acquisition A/D( Mathematical model ) transformation , Noise pollution is produced during transmission , Affect image quality

Therefore, the image quality must be improved before image processing and analysis , There are two types of improvement methods ：

* image enhancement

* image restoration

Image enhancement does not consider the reason of image quality degradation , Only the features of interest in the image are selectively highlighted , And attenuation doesn't need features , Its main purpose is to improve the intelligibility of images ;

Image restoration technology is different from enhancement technology , It needs to understand why image quality is declining , First of all, we should establish " Degradation model ", Reuse the model , Restore original image .

This paper focuses on the image enhancement technology , Image enhancement is mainly for the purpose of contrast and threshold processing , And they are all operations in the spatial domain . We assume that f(x,y) Is the input image ,g(x,y)

It is the image after enhancement transformation , Then there are ：

there T It's at the dot (x,y) On the definition of neighborhood f Operator of , According to the neighborhood , There are two kinds of image enhancement ：

* Neighborhood processing technology

* Point processing technology , also called Image gray level transformation enhancement technology , This article will focus on the discussion

<>2, Image enhancement neighborhood processing technology

Spatial domain processing g(x,y) = T[f(x, y)] midpoint (x,y) This is the pixel coordinates of the image , And neighborhood is the center (x,y)

Rectangle of , It's much smaller than the image , As shown in the figure below ：

The core idea of image enhancement neighborhood processing technology is ： When right (x,y) When making a change , Transformation operator T It's for Israel (x,y) Then we get the transformation result

, As shown above , If the size of the neighborhood is 3*3 Square of , operator T Defined as The average gray level of the neighborhood is calculated , as (x,y) = (100,200), be g(100,200)

The result is calculation f(100,200) And its 8 Sum of adjacent points , And then divide by 9

( It is the average value of the pixel gray level surrounded by the neighborhood ), Of course, this idea of neighborhood processing is the basic application in the subsequent image filtering , Such as mean filtering , Median filtering and Gaussian filtering are all using neighborhood processing technology .

<>3, Image enhancement point processing technology

Point processing technology , When the neighborhood size is 1*1 Time , here g The value of depends only on the point (x,y) Value at , here T

It is called the gray transformation function , This kind of image enhancement method is image gray transformation enhancement , The definition formula is as follows ：

among s Is the transformed pixel ,r Is the pixel before the transformation , Linear transformation discussed later , Piecewise linear transformation , Logarithmic transformation , Anti number transformation ,

Power law ( gamma ) The transformation is based on this formula , Therefore, image gray level transformation is based on point enhancement , It converts the gray value of each pixel into a new gray value according to a certain mathematical transformation formula , To enhance the image effect .

<> Two , Image gray transformation enhancement

Say it in front of you ： Linear transformation and piecewise linear transformation are usually used to process gray image , You can also directly RGB Image processing ; Logarithmic transformation , Anti number transformation ,

Power law ( gamma ) The transformation is directly related to RGB The image is enhanced accordingly , Achieve the results you want

If yes RGB Two more operations are needed after image transformation ：(1) image normalization ,(2)

The image pixel value type is converted to np.uint8, Two functions are needed , Here is a brief introduction , You will use the ：

function cv2.normalize()

# Digital image normalization operation cv2.normalize(src, dst, alpha, beta, norm_type, dtype, mask) → dst

Parameter interpretation ：

*

src： Original image object

*

dst： Transformed image object

*

alpha： Minimum value of gray pixel after normalization , It is generally 0

*

beta： Maximum value of gray pixel after normalization , It is generally 255

*

norm_type： Types of normalization , You can take the following values

(1) cv2.NORM_MINMAX： The values of the array are panned or scaled to a specified range , Linear normalization , It is generally used

(2) cv2.NORM_INF: The definition of this type is not found , according to OpenCV 1 Corresponding items of , It may be a normalized array C- norm ( Maximum value of absolute value )

(3) cv2.NORM_L1 : Normalized array L1- norm ( Sum of absolute values )

(4) cv2.NORM_L2: Normalized array ( Euclid )L2- norm

*

dtype： When it is negative , Output image pixel value type Same as input , Default is generally used

*

mask： Operating mask , Indicates whether the function operates only on the specified element , Default is generally used

function cv2.convertScaleAbs()

# The function is simple , In other words, the pixel values of the original image are converted to type np.uint8 dst = cv2.convertScaleAbs(src)

<>1, linear transformation

Image enhancement linear transform can adjust the contrast and brightness of the image , The linear transformation formula is as follows ：

parameter a Affects the contrast of the image , parameter b Affects the brightness of the image , It can be divided into the following situations ：

* a>1： Enhance image contrast , The image looks clearer

* a<1： The contrast of the image is reduced , The image looks dimmed

* a<0 and b=0： The bright areas of the image darken , Dark areas brighten

* a=1 and b≠0： The gray value of the whole image moves up or down , In other words, the whole image becomes bright or dark , Does not change the contrast of the image ,b>0 When the image is bright ,b<0 The image darkens

* a=-1 and b=255： Image flip

Code up ：

import cv2 import random import imutils import numpy as np # Color image per pixel value is [x,y,z],

Each pixel value of gray image is one np.uint8 image =

cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/ali.jpg') gray_img =

cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Image resizing ori_h, ori_w = image.shape[:2]

height, width = gray_img.shape[:2] image = cv2.resize(image,

(int(ori_w/ori_h*400), 400), interpolation=cv2.INTER_CUBIC) gray_img =

cv2.resize(gray_img, (int(width/height*400), 400),

interpolation=cv2.INTER_CUBIC) #a<0 and b=0: The bright areas of the image darken , Dark areas brighten a, b = -0.5, 0

new_img1 = np.ones((gray_img.shape[0], gray_img.shape[1]), dtype=np.uint8) for

i in range(new_img1.shape[0]): for j in range(new_img1.shape[1]):

new_img1[i][j] = gray_img[i][j]*a + b #a>1: Enhance image contrast , The image looks clearer a, b = 1.5, 20

new_img2 = np.ones((gray_img.shape[0], gray_img.shape[1]), dtype=np.uint8) for

i in range(new_img2.shape[0]): for j in range(new_img2.shape[1]): if

gray_img[i][j]*a + b > 255: new_img2[i][j] = 255 else: new_img2[i][j] =

gray_img[i][j]*a + b #a<1: The contrast of the image is reduced , The image looks dimmed a, b = 0.5, 0 new_img3 =

np.ones((gray_img.shape[0], gray_img.shape[1]), dtype=np.uint8) for i in

range(new_img3.shape[0]): for j in range(new_img3.shape[1]): new_img3[i][j] =

gray_img[i][j]*a + b #a=1 And b≠0, The gray value of the whole image moves up or down , In other words, the whole image becomes bright or dark , Does not change the contrast of the image a, b =

1, -50 new_img4 = np.ones((gray_img.shape[0], gray_img.shape[1]),

dtype=np.uint8) for i in range(new_img4.shape[0]): for j in

range(new_img4.shape[1]): pix = gray_img[i][j]*a + b if pix > 255:

new_img4[i][j] = 255 elif pix < 0: new_img4[i][j] = 0 else: new_img4[i][j] =

pix #a=-1, b=255, Image flip new_img5 = 255 - gray_img cv2.imshow('origin',

imutils.resize(image, 800)) cv2.imshow('gray', imutils.resize(gray_img, 800))

cv2.imshow('a<0 and b=0', imutils.resize(new_img1, 800)) cv2.imshow('a>1 and

b>=0', imutils.resize(new_img2, 800)) cv2.imshow('a<1 and b>=0',

imutils.resize(new_img3, 800)) cv2.imshow('a=1 and b><0',

imutils.resize(new_img4, 800)) cv2.imshow('a=-1 and b=255',

imutils.resize(new_img5, 800)) if cv2.waitKey(0) == 27: cv2.destroyAllWindows()

Code running effect , Original gray image ：

Through the contrast of the image , After the brightness enhancement, the effect is as follows ：

notes ：

One thing to understand is that image enhancement has never been a universal theory , There will be different requirements in different scenarios , The simplest linear transformation of image gray enhancement can meet the requirements of random adjustment of image contrast and brightness , Get what you want

<>2, Piecewise linear transformation

The method of piecewise linear transformation function to enhance image contrast is actually to enhance the contrast of each part of the original image , That is to enhance the gray region of interest in the input image , The gray areas that are not interested in are relatively suppressed .

The main advantage of increasing piecewise linear function is that its form can be arbitrarily synthesized , The disadvantage is that it requires more user input . The general formula of piecewise linear function is as follows ：

Next, we will experience the application of piecewise linear function for image enhancement through examples , And understand the meaning of the above formula !

<>2.1 Contrast stretching for piecewise linear transformation , Threshold processing

Low contrast images are generally caused by insufficient illumination , The dynamic range of imaging sensor is too small , In the process of image acquisition, the lens aperture is set incorrectly , Contrast stretching is the processing of expanding the dynamic range of gray level of image . Transformation operator T As shown below ：

according to r1,s1,r2,s2 It can be divided into the following two kinds of enhancement ：

* r1 <= r2,s1 <= s2： Contrast stretch , Enhance ROI

* r1 = r2： Threshold processing , Generate a binary image

(1) Example demonstration of contrast stretching

Order (r1, s1) = (rmin,0),(r2, s2) = (rmax,L-1), among rmin,rmax

They represent the minimum gray level and the maximum gray level respectively , This transform function linearly stretches the gray level from the original range to the whole range [0,L-1], Example code above ：

import cv2 import imutils import numpy as np image =

cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/pollen.jpg') gray_img =

cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # The linear contrast of gray scale was drawn

# In this way, the transformation function extends the gray level from the original linear to the whole range [0, 255] r_min, r_max = 255, 0 for i in

range(gray_img.shape[0]): for j in range(gray_img.shape[1]): if gray_img[i, j]

> r_max: r_max = gray_img[i, j] if gray_img[i, j] < r_min: r_min = gray_img[i,

j] r1, s1 = r_min, 0 r2, s2 = r_max, 255 precewise_img =

np.zeros((gray_img.shape[0], gray_img.shape[1]), dtype=np.uint8) k1 = s1/r1 k3

= (255-s2)/(255-r2) k2 = (s2 - s1)/(r2 - r1) for i in range(gray_img.shape[0]):

for j in range(gray_img.shape[1]): if r1 <= gray_img[i, j] <= r2:

precewise_img[i, j] = k2*(gray_img[i, j] - r1) elif gray_img[i, j] < r1:

precewise_img[i, j] = k1*gray_img[i, j] elif gray_img[i, j] > r2:

precewise_img[i, j] = k3*(gray_img[i, j] - r2) cv2.imshow('origin image',

imutils.resize(image, 480)) cv2.imshow('precewise image',

imutils.resize(precewise_img, 480)) if cv2.waitKey(0) == 27:

cv2.destroyAllWindows()

The above code is the gray image on the image enhancement , We can also enhance the image directly on the original image , The effect is the same , The code is as follows ：

import cv2 import imutils import numpy as np image =

cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/pollen.jpg')

# Segment linear contrast stretching is performed directly on the original image # In this way, the transformation function extends the gray level from the original linear to the whole range [0, 255] r_min, r_max = 255, 0 for

i in range(image.shape[0]): for j in range(image.shape[1]): for k in

range(image.shape[2]): if image[i, j, k] > r_max: r_max = image[i, j, k] if

image[i, j, k] < r_min: r_min = image[i, j, k] r1, s1 = r_min, 0 r2, s2 =

r_max, 255 k1 = s1/r1 k3 = (255-s2)/(255-r2) k2 = (s2 - s1)/(r2 - r1)

precewise_img = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32)

for i in range(image.shape[0]): for j in range(image.shape[1]): for k in

range(image.shape[2]): if r1 <= image[i, j, k] <= r2: precewise_img[i, j, k] =

k2*(image[i, j, k] - r1) elif image[i, j, k] < r1: precewise_img[i, j, k] =

k1*gray_img[i, j, k] elif image[i, j, k] > r2: precewise_img[i, j, k] =

k3*(gray_img[i, j, k] - r2) # After making piecewise linear changes in the original image, it is necessary to normalize the image , And convert the data type to np.uint8

cv2.normalize(precewise_img, precewise_img, 0, 255, cv2.NORM_MINMAX)

precewise_img = cv2.convertScaleAbs(precewise_img) cv2.imshow('origin image',

imutils.resize(image, 480)) cv2.imshow('precewise image',

imutils.resize(precewise_img, 480)) if cv2.waitKey(0) == 27:

cv2.destroyAllWindows()

The effect of the original pollen image and contrast stretching is as follows ：

(2) Example demonstration of threshold processing

import cv2 import imutils import numpy as np image =

cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/pollen.jpg') gray_img =

cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Threshold processing function ： When r1=r2, s1=0,

s2=L-1 Time , In this case, the piecewise linear function is the threshold processing function plist = [] for i in range(gray_img.shape[0]): for j in

range(gray_img.shape[1]): plist.append(gray_img[i, j]) r_avg =

int(sum(plist)/len(plist)) thresh_img = np.zeros((gray_img.shape[0],

gray_img.shape[1]), dtype=np.uint8) for i in range(gray_img.shape[0]): for j in

range(gray_img.shape[1]): if gray_img[i, j] < r_avg: thresh_img[i, j] = 0 else:

thresh_img[i, j] = 255 cv2.imshow('origin image', imutils.resize(image, 480))

cv2.imshow('thresh image', imutils.resize(thresh_img, 480)) if cv2.waitKey(0)

== 27: cv2.destroyAllWindows()

The pollen image after threshold processing is shown below :

<>2.2 Gradation of gray level for piecewise linear transformation

In order to highlight the gray level region of interest in digital image [A,B], In practice, there are two ways to deal with it , Corresponding to the figure below ：

* Highlight the gray range in [A,B] Area of , Reduces the gray level of other areas to a lower level

* Highlight the gray range in [A,B] Area of , Other areas remain unchanged

Example code above ( Here's what's shown ： Other areas remain the same gray level )

import cv2 import imutils import numpy as np # In a certain range (A, B) Highlight grayscale , Other gray values remain unchanged image

= cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/kidney.jpg') gray_img

= cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) r_left, r_right = 150, 230 r_min,

r_max = 0, 255 level_img = np.zeros((gray_img.shape[0], gray_img.shape[1]),

dtype=np.uint8) for i in range(gray_img.shape[0]): for j in

range(gray_img.shape[1]): if r_left <= gray_img[i, j] <= r_right: level_img[i,

j] = r_max else: level_img[i, j] = gray_img[i, j] cv2.imshow('origin image',

imutils.resize(image, 480)) cv2.imshow('level image', imutils.resize(level_img,

480)) if cv2.waitKey(0) == 27: cv2.destroyAllWindows()

The original image and effect picture are shown below ：

<>3, Logarithmic transformation

Logarithm transform extends the low gray value of the image , The high gray value part is compressed , To achieve the purpose of emphasizing the low gray part of the image ; At the same time, the dynamic range of the image can be compressed , The aim is to highlight the details we need . The difference between anti number transformation and logarithmic function is that , The emphasis is on the high gray part of the image , The logarithmic transformation formula is as follows ：

The following example demonstrates the logarithmic transformation ：

import cv2 import imutils import numpy as np image =

cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/DFT_no_log.jpg')

log_img = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32) for i

in range(image.shape[0]): for j in range(image.shape[1]): log_img[i, j, 0] =

math.log(1 + image[i, j, 0]) log_img[i, j, 1] = math.log(1 + image[i, j, 1])

log_img[i, j, 2] = math.log(1 + image[i, j, 2]) cv2.normalize(log_img, log_img,

0, 255, cv2.NORM_MINMAX) log_img = cv2.convertScaleAbs(log_img)

cv2.imshow('image', imutils.resize(image, 400)) cv2.imshow('log transform',

imutils.resize(log_img, 400)) if cv2.waitKey(0) == 27: cv2.destroyAllWindows()

Fourier spectrum and spectrum image enhanced by logarithmic transform

<>4, Power law transformation

Power law transform is mainly used for image correction , Correct the bleached or over black images , The formula of power law transformation is as follows ：

according to φ Size of , It can be divided into the following two situations ：

* φ > 1： Dealing with bleached pictures , Carry out gray level compression

* φ < 1： Processed black pictures , Contrast enhancement , Make the details more clear

4.1 When φ > 1 It is shown as below ：

# Power law transformation φ>1 image =

cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/aerial.jpg') gamma_img1

= np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32) for i in

range(image.shape[0]): for j in range(image.shape[1]): gamma_img1[i, j, 0] =

math.pow(image[i, j, 0], 5) gamma_img1[i, j, 1] = math.pow(image[i, j, 1], 5)

gamma_img1[i, j, 2] = math.pow(image[i, j, 2], 5) cv2.normalize(gamma_img1,

gamma_img1, 0, 255, cv2.NORM_MINMAX) gamma_img1 =

cv2.convertScaleAbs(gamma_img1) cv2.imshow('image', imutils.resize(image, 400))

cv2.imshow('gamma1 transform', imutils.resize(gamma_img1, 400)) if

cv2.waitKey(0) == 27: cv2.destroyAllWindows()

Contrast effect of bleached image and image after power law transformation ：

4.2 When φ< 1 It is shown as below ：

# Power law transformation ,φ<1 image =

cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/fractured_spine.jpg')

gamma_img2 = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32)

for i in range(image.shape[0]): for j in range(image.shape[1]): gamma_img2[i,

j, 0] = math.pow(image[i, j, 0], 0.4) gamma_img2[i, j, 1] = math.pow(image[i,

j, 1], 0.4) gamma_img2[i, j, 2] = math.pow(image[i, j, 2], 0.4)

cv2.normalize(gamma_img2, gamma_img2, 0, 255, cv2.NORM_MINMAX) gamma_img2 =

cv2.convertScaleAbs(gamma_img2) cv2.imshow('image', imutils.resize(image, 400))

cv2.imshow('gamma2 transform', imutils.resize(gamma_img2, 400)) if

cv2.waitKey(0) == 27: cv2.destroyAllWindows()

Over black image and effect display after power law transformation ：

<> Three , Histogram equalization

Say it in front of you ：

The purpose of histogram equalization of digital image is to improve the contrast of image , The input pixels of the brighter or darker regions are mapped to the output pixels of the entire region , It is a good and convenient way of image enhancement , Therefore, it is explained in a separate section

<>1, Recognize histogram of image

image histogram ： General concept of image intensity distribution , Broadly speaking, histogram gives the image contrast , Brightness and intensity distribution information . The following from the theoretical point of view on the image histogram formula definition

For the gray level range of [0,L-1] The histogram of digital image is a discrete function ：

among rk It's No k Grayscale value ,nk The gray level of the image is rk The number of pixels . Of course, if the length and width dimension of the digital image is MN, Then the normalized histogram formula is ：

Let's first feel the difference of histogram corresponding to different images from an intuitive point of view , It is very helpful to enhance image understanding by histogram equalization

We notice from the picture above ： In a dark image , The distribution of histogram is concentrated in the low gray level ( dark ) end ;

The distribution of the histogram of the bright image is concentrated at the high end of the gray level ; Low contrast images have narrow histograms , And they are all concentrated 在灰度级的中部;而高对比度的图像直方图的分量覆盖了很宽的灰度范围,且像素分布也相对均匀,此时图片的效果也相对很不错.于是我们可以得出结论：

若一幅图像的像素倾向于占据整个可能的灰度级并且分布均匀,则该图像有较高的对比度并且图像展示效果会相对好,于是便引出图像直方图均衡化,对图像会有很强的增强效果

<>2,图像增强之直方图均衡化

这里不详细介绍直方图均衡化原理,想了解请看博客： 直方图均衡化原理

<https://blog.csdn.net/rushkid02/article/details/9178117>

下面给出直方图均衡化的实现：

import cv2 import imutils import numpy as np import matplotlib.pyplot as plt

wiki_img = cv2.imread('E:/peking_rw/ocr_project/base_prehandle/img/wiki.jpg')

wiki_gray = cv2.cvtColor(wiki_img, cv2.COLOR_BGR2GRAY) #对图像进行均衡化处理,增强图像对比度

wiki_equ = cv2.equalizeHist(wiki_gray) hist = cv2.calcHist([wiki_gray], [0],

None, [256], [0, 256]) equ_hist = cv2.calcHist([wiki_equ], [0], None, [256],

[0, 256]) fig = plt.figure() ax1 = fig.add_subplot(1, 2, 1) ax1.plot(hist) ax2

= fig.add_subplot(1, 2, 2) ax2.plot(equ_hist) plt.show()

cv2.imshow('wiki_origin', imutils.resize(wiki_img, 400))

cv2.imshow('wiki_gray', imutils.resize(wiki_gray, 400)) cv2.imshow('wiki_equ',

imutils.resize(wiki_equ, 400)) if cv2.waitKey(0) == 27: cv2.destroyAllWindows()

直方图均衡化斥候：直方图前后对比图,图像前后对比图

<>四,总结

不总结了,本篇分享到此结束,码字码到眼睛疼,如果诸位看管觉得还可以帮忙点个赞,后续将持续更新数字图像处理和分析等操作,也欢迎关注博主微信公众号