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()

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






<>四,总结



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