Opencv_100问_第五章 (21-25)

21. 直方图归一化 (Histogram Normalization)

直方图会存在偏差.比如说,数据集中在0处(左侧)的图像会整体偏暗,数据集中在255处(右侧)的图像会偏亮.如果直方图有所偏向,那么其动态范围(dynamic range)就会较低.为什么使得人能够更好清除地看见图片,让直方图归一化,平坦化是十分必要的.

这种归一化直方图的操作被称为灰度变换(Grayscale Transformation). 像素点取值范围从[c,d]转换到[a,b]的过程由下面的式子定义.

outVal = {
	a                                 if(inVal <c)
	(b-a) / (d-c) * (inVal - c) + a   if(c <= inVal <=d)
	b                                 if(inVal > d)
}

实现代码:

# @Time   : 2022/6/11 10:15
# @Author : Fioman
# @Phone  : 13149920693
# @Tips   : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
import matplotlib.pyplot as plt

# histogram normalization
def hist_normalization(image, a=0, b=255):
    # get max and min
    c = image.min()
    d = image.max()
    out = image.copy()

    # normalization
    out = (b - a) / (d - c) * (out - c) + a
    out[out < a] = a
    out[out > b] = b
    out = out.astype(np.uint8)
    return out


if __name__ == '__main__':
    imagePath = os.path.join(OPENCV_100_Q_PATH,"gray_01.bmp")
    imageOriginal = cv.imread(imagePath,cv.IMREAD_GRAYSCALE)
    H,W = imageOriginal.shape[:2]
    out = hist_normalization(imageOriginal)

    # Dist histogram
    ax1 = plt.subplot(1,2,1)
    plt.hist(imageOriginal.ravel(),bins=255,rwidth=0.8,range=(0,255))
    # plt.hist(imageOriginal.ravel(),bins=255,rwidth=0.8,range=(0,255))
    ax2 = plt.subplot(1,2,2)
    plt.hist(out.ravel(),bins=255,rwidth=0.8,range=(0,255))
    plt.show()

22. 直方图操作(直方图平坦化)

这里的直方图操作不是变更直方图的动态范围,而是让直方图变得更加的平坦.
可以使用下面的公式将平均值为m标准差为s的直方图变成平均值为m0标准差为s0的直方图:

让直方图的平均值m0 = 128, 标准差 s0 = 52.

代码实现:

# @Time   : 2022/6/11 11:19
# @Author : Fioman
# @Phone  : 13149920693
# @Tips   : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
import matplotlib.pyplot as plt


# histogram manipulation
def hist_operate(image, m0=128, s0=52):
    m = np.mean(image)
    s = np.std(image)

    out = image.copy()

    # normalize
    out = s0 / s * (out - m) + m0
    out = np.clip(out, 0, 255)
    out = out.astype(np.uint8)
    return out


if __name__ == '__main__':
    imagePath = os.path.join(OPENCV_100_Q_PATH, "gray_01.bmp")
    image = cv.imread(imagePath, cv.IMREAD_GRAYSCALE)
    out = hist_operate(image)

    plt.subplot(1, 2, 1)
    plt.hist(image.ravel(), bins=255, rwidth=0.8, range=(0, 255))
    plt.subplot(1, 2, 2)
    plt.hist(out.ravel(), bins=255, rwidth=0.8, range=(0, 255))

    cv.imshow("Orginal", image)
    cv.imshow("NewImage", out)
    plt.show()
    cv.waitKey(0)

23. 直方图均衡化(Histogram Equalization)

直方图均衡化是使得直方图变得平坦的操作,是不需要计算上面的问题中的平均值,标准差等数据使得直方图变得均衡的操作.
均衡化的操作由以下的式子定义. S是总的像素数,Zmax是像素点的最大取值(在这里是255);h(z)表示取值为z的累积分布函数;


代码示例:

# @Time   : 2022/6/11 11:49
# @Author : Fioman
# @Phone  : 13149920693
# @Tips   : Talk is Cheap,Show me the code! ^_^^_^
from settings import *
import matplotlib.pyplot as plt

# histogram equalization
def hist_equal(image, zMax=255):
    H, W = image.shape[:2]
    S = H * W
    out = image.copy()
    sumH = 0
    for i in range(1, 255):
        ind = np.where(image == i)
        sumH += len(image[ind]) 
        zPrime = zMax / S * sumH
        out[ind] = zPrime

    out = out.astype(np.uint8)
    return out

if __name__ == '__main__':
    imagePath = os.path.join(OPENCV_100_Q_PATH,"gray_01.bmp")
    imageOriginal = cv.imread(imagePath,cv.IMREAD_GRAYSCALE)
    histEqual = hist_equal(imageOriginal)

    plt.subplot(1,2,1)
    plt.hist(imageOriginal.ravel(),bins=255,rwidth=0.8,range = (0,255))
    plt.subplot(1,2,2)
    plt.hist(histEqual.ravel(),bins=255,rwidth=0.8,range=(0,255))
    plt.show(())

    cv.imshow("Original",imageOriginal)
    cv.imshow("HistEqual",histEqual)
    cv.waitKey(0)

24. 伽马校正(Gamma Correction)

伽马校正用来对照相机等电子设备传感器的非线性光电转换特性进行校正.如果图像原样显示在显示器等上,画面就会显得很暗.伽马校正通过预先增大RGB的值来排除显示器的影响,达到图像修正的目的.

由于下式引起非线性变换,在该式中,x被归一化,限定在[0,1]范围内.c是常数,g为伽马变量(通常取2.2):

# @Time   : 2022/6/11 11:58
# @Author : Fioman
# @Phone  : 13149920693
# @Tips   : Talk is Cheap,Show me the code! ^_^^_^
from settings import *

# gamma correction
def gamma_correction(image,c=1,g=2.2):
    out = image.copy()
    out  = out / 255
    out = (1/c * out) ** (1/g)

    out *= 255
    out = out.astype(np.uint8)
    return out

if __name__ == '__main__':
    imagePath = os.path.join(OPENCV_100_Q_PATH,"gray_01.bmp")
    imageOriginal = cv.imread(imagePath,cv.IMREAD_GRAYSCALE)
    gammaRes = gamma_correction(imageOriginal,1,2.2)
    cv.imshow("Original",imageOriginal)
    cv.imshow("GammaRes",gammaRes)
    cv.waitKey(0)

25. 最近邻插值 (Nearest-neighbor Interpolation)

使用最近邻插值算法将图像放大1.5倍

最近邻插值在图像放大时补充的像素取最邻近的像素的值.由于方法简单,所以处理速度很快,但是放大图像画质劣化明显.
使用下面的公式放大图像吧! I'为放大后图像,I为发达前图像,a为放大率,方括号是四色五入操作:

# @Time   : 2022/6/11 15:43
# @Author : Fioman
# @Phone  : 13149920693
# @Tips   : Talk is Cheap,Show me the code! ^_^^_^
from settings import *


def nearest_interpolate(image, ax=1.0, ay=1.0):
    H, W, C = image.shape

    aH = int(ay * H)
    aW = int(ax * W)

    y = np.arange(aH).repeat(aW).reshape(aH, -1)
    x = np.tile(np.arange(aW), (aH, 1))
    y = np.round(y / ay).astype(np.int64)
    x = np.round(x / ax).astype(np.int64)

    out = image[y, x]

    out = out.astype(np.uint8)

    return out


if __name__ == '__main__':
    imagePath = os.path.join(OPENCV_100_Q_PATH, "color_02.bmp")
    imageOriginal = cv.imread(imagePath,cv.IMREAD_COLOR)
    cv.imshow("Original", imageOriginal)
    out = nearest_interpolate(imageOriginal, ax=1.5, ay=1.5)

    cv.imshow("NearestInterpolation",out)
    cv.waitKey(0)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值