OpenCV-Python-(4)-对比度增强

对比度增强

  • cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]])  #图像直方图
  • cv2.normalize(src[, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]]) → dst   #直方图归一化
  • cv2.equalizeHist(image)                                                                                           #直方图均衡化
  • cv2.createCLAHE(clipLimit, tileGridSize)                                                      #创建clahe对象,限制对比度

1.图像直方图

cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) 

  • images,必须用方括号括起来。
  • channels,是用于计算直方图的通道,这里使用灰度图计算直方图,所以就直接使用第一个通道。
  • Mask,图像掩模,没有使用则填写None。
  • histSize,表示这个直方图分成多少份(即多少个直方柱)。
  • ranges,表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。
  • accumulate,为一个布尔值,用来表示直方图是否叠加。

(1)灰度直方图

代码实现:

灰度直方图

import numpy as np
import cv2
import matplotlib.pyplot as plt
#定义caleGrayHist函数来计算灰度直方图
def caleGrayHist(image):
    #灰度图像的高、宽
    rows, cols = image.shape
    #存储灰度直方图
    grayHist = np.zeros([256], np.uint64) #图像的灰度级范围是0~255      
    for r in range(rows):
        for c in range(cols):
            
            grayHist[image[r][c]] +=1
            
    return grayHist

if __name__ == "__main__":
    img = cv2.imread(r'C:\Users\x\Desktop\2.jpg', cv2.IMREAD_GRAYSCALE)
    #计算灰度直方图
    grayHist = caleGrayHist(img)
    #画出直方图
    x_range = range(256)
    plt.plot(x_range, grayHist, 'r', linewidth=1.5, c='orange')
    #设置坐标轴的范围
    y_maxValue = np.max(grayHist)
    plt.axis([0, 255, 0, y_maxValue]) #画图范围
    plt.xlabel("gray Level")
    plt.ylabel("number of pixels")
    plt.show()

API实现:

from matplotlib import pyplot as plt
import cv2

img = cv2.imread(r'C:\Users\x\Desktop\2.jpg', cv2.IMREAD_GRAYSCALE)
plt.imshow(img, cmap=plt.cm.gray)

#images,必须用方括号括起来。
#channels,是用于计算直方图的通道,这里使用灰度图计算直方图,所以就直接使用第一个通道。
#Mask,图像掩模,没有使用则填写None。
#histSize,表示这个直方图分成多少份(即多少个直方柱)。
#ranges,表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。
#accumulate,为一个布尔值,用来表示直方图是否叠加。

hist = cv2.calcHist([img], [0], None, [256], [0, 256])

plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("gray Level")
plt.ylabel("number of pixels")

plt.plot(hist)
plt.xlim([0, 256])
plt.show()

(2)多颜色直方图

from matplotlib import pyplot as plt
import cv2

img = cv2.imread(r'C:\Users\x\Desktop\2.jpg', cv2.IMREAD_ANYCOLOR)

chans = cv2.split(img)
colors = ('b', 'g', 'r')

plt.figure()
plt.title("Color Histogram")
plt.xlabel("gray Level")
plt.ylabel("number of pixels")

for (chan, color) in zip(chans, colors):
    hist = cv2.calcHist([chan], [0], None, [256], [0, 256])
    plt.plot(hist, color = color)
    plt.xlim([0, 256])
plt.show()


2.直方图归一化

cv2.normalize(src[, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]]) → dst

src-输入数组

dst-输出数组,支持原地运算

alpha-range normalization模式的最小值

beta-range normalization模式的最大值,不用于norm normalization(范数归一化)模式。

normType-归一化的类型,可以有以下的取值:

  •     NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化,一般较常用。
  •     NORM_INF: 此类型的定义没有查到,根据OpenCV 1的对应项,可能是归一化数组的C-范数(绝对值的最大值)
  •     NORM_L1 :  归一化数组的L1-范数(绝对值的和)
  •     NORM_L2: 归一化数组的(欧几里德)L2-范数

dtype-dtype为负数时,输出数组的type与输入数组的type相同;否则,输出数组与输入数组只是通道数相同,而tpye=CV_MAT_DEPTH(dtype).

mask-操作掩膜,用于指示函数是否仅仅对指定的元素进行操作。

适用于:灰度级主要在0~150之间,造成图像对比度较低,可用直方图归一化将图像灰度级拉伸到0~255,使其更清晰。

#直方图正规化API
#灰度级主要在0~150之间,造成图像对比度较低,可用直方图正规化将图像灰度级拉伸到0~255,使其更清晰
import cv2
import numpy as np
import matplotlib.pyplot as plt

#灰度图像转化为ndarray类型
if __name__ == "__main__":
    src = cv2.imread(r'C:\Users\x\Desktop\OpenCV-Pic\4\img6.jpg', cv2.IMREAD_ANYCOLOR)
    dst = np.zeros_like(src)
    cv2.normalize(src, dst, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U) #公式
    cv2.imshow("src", src)
    cv2.imshow("dst", dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    #计算灰度直方图
    grayHist = cv2.calcHist([src], [0], None, [256], [0, 256])
    grayHist1 = cv2.calcHist([dst], [0], None, [256], [0, 256])
    #画出直方图
    x_range = range(256)
    plt.plot(x_range, grayHist, 'r', linewidth=1.5, c='black')
    plt.plot(x_range, grayHist1, 'r', linewidth=1.5, c='b')
    #设置坐标轴的范围
    y_maxValue = np.max(grayHist)
    plt.axis([0, 255, 0, y_maxValue]) #画图范围
    plt.xlabel("gray Level")
    plt.ylabel("number of pixels")
    plt.show()


3.直方图均衡化HE

cv2.equalizeHist(image)

直方图均衡化是将原始的直方图拉伸,使之均匀分布在全部灰度范围内,从而增强图像的对比度。
直方图均衡化的中心思想是把原始图像的的灰度直方图从比较集中的某个区域变成在全部灰度范围内的均匀分布。旨在使得图像整体效果均匀,黑与白之间的各个像素级之间的点更均匀一点。

(1)灰度直方图均衡

import cv2
import numpy as np
import math

if __name__ == "__main__":
    I = cv2.imread(r'C:\Users\x\Desktop\OpenCV-Pic\4\img1.jpg', cv2.IMREAD_GRAYSCALE)

    O = cv2.equalizeHist(I)
    
    cv2.namedWindow("I", cv2.WINDOW_NORMAL)
    cv2.namedWindow("O", cv2.WINDOW_NORMAL)
    cv2.imshow("I", I)
    cv2.imshow("O", O)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

(2)彩色直方图均衡

import cv2

I = cv2.imread(r'C:\Users\x\Desktop\47.jpg', cv2.IMREAD_ANYCOLOR)

b, g, r = cv2.split(I)

b1 = cv2.equalizeHist(b)
g1 = cv2.equalizeHist(g)
r1 = cv2.equalizeHist(r)

O = cv2.merge([b1,g1,r1])
    
cv2.namedWindow("I", cv2.WINDOW_NORMAL)
cv2.namedWindow("O", cv2.WINDOW_NORMAL)
cv2.imshow("I", I)
cv2.imshow("O", O)
cv2.waitKey(0)
cv2.destroyAllWindows()


4.限制对比度自适应直方图均衡化(Contrast Limited Adaptive histgram equalization/CLAHE)


cv2.createCLAHE(clipLimit, tileGridSize)

创建CLAHE对象 clipLimit限制对比度,tileGridSize块的大小

CLAHE同普通的自适应直方图均衡不同的地方主要是其对比度限幅。

这个特性也可以应用到全局直方图均衡化中,即构成所谓的限制对比度直方图均衡(CLHE),但这在实际中很少使用。在CLAHE中,对于每个小区域都必须使用对比度限幅。CLAHE主要是用来克服AHE的过度放大噪音的问题。 

#限制对比度的自适应直方图均衡化
import cv2

src = cv2.imread(r'C:\Users\x\Desktop\OpenCV-Pic\4\img3.jpg', cv2.IMREAD_ANYCOLOR)
#创建CLAHE对象 clipLimit限制对比度,tileGridSize块的大小
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
#限制对比度的自适应阈值
dst = clahe.apply(src)
    
cv2.namedWindow("src", cv2.WINDOW_NORMAL)
cv2.namedWindow("clahe", cv2.WINDOW_NORMAL)
cv2.imshow("src", src)
cv2.imshow("clahe",dst)
cv2.waitKey(0)
cv2.destroyAllWindows()


5.线性变换

拉伸灰度级,提高对比度
压缩灰度级,降低对比度

import cv2
import numpy as np
import matplotlib.pyplot as plt
    
img = cv2.imread(r'C:\Users\x\Desktop\OpenCV-Pic\4\img4.jpg', cv2.IMREAD_GRAYSCALE)#GRAYSCALE

#线性变换
a = 2
O = float(a) * img
O[O>255] = 255 #大于255要截断为255
    
#数据类型的转换
O = np.round(O)
O = O.astype(np.uint8)
    
#显示原图与变换后的图的效果
cv2.imshow("img", img)
cv2.imshow("O", O)
cv2.waitKey(0)
cv2.destroyAllWindows()


6.伽马变换

伽马变换(非线性变换)实际上就是对矩阵的每个值进行幂运算
适用于:灰度值主要集中在灰度直方图两侧,即灰度值较低和较高的范围内,可用伽马变换修正

import cv2
import numpy as np


#灰度图像转化为ndarray类型
I = cv2.imread(r'C:\Users\x\Desktop\OpenCV-Pic\4\img8.jpg', cv2.IMREAD_ANYCOLOR)
#图像归一化
fI = I/255.0
#伽马变化
gamma = 0.4
O = np.power(fI, gamma)

#显示伽马变化后的结果
cv2.namedWindow("I", cv2.WINDOW_NORMAL)
cv2.namedWindow("O", cv2.WINDOW_NORMAL)
cv2.imshow("I", I)
cv2.imshow("O", O)
cv2.waitKey(0)
cv2.destroyAllWindows()

猜你喜欢

转载自blog.csdn.net/qq_40755643/article/details/84032773
今日推荐