【代码】遥感影像匀色

这里实现的是遥感影像匀色的功能——直方图匹配。

直方图匹配是一种用于图像处理的技术,它可以用来调整一幅图像的颜色或灰度分布,使其与另一幅图像的颜色或灰度分布相匹配。这种技术常常用于图像增强,例如改善图像的对比度或者进行颜色校正。

首先,让我们解释一下什么是直方图。在图像处理中,直方图是一个表,它显示了图像中各个颜色或灰度级别的像素数量。例如,一个灰度图像的直方图可能会显示有多少个像素是黑色的,有多少个像素是灰色的,有多少个像素是白色的,等等。

直方图匹配的过程大致如下:

  1. 计算两幅图像的直方图。这给了我们每幅图像的颜色或灰度分布。
  2. 计算两个直方图的累积分布函数(CDF)。CDF表示的是图像中小于或等于某个颜色或灰度级别的像素的累积比例。
  3. 对于原始图像中的每个像素,找到与其灰度级别相匹配的目标图像的灰度级别。这就是通过查找具有最接近CDF值的目标图像的灰度级别来完成的。
  4. 将原始图像中的每个像素替换为匹配的灰度级别。

通过这种方式,我们可以调整原始图像的颜色或灰度分布,使其看起来更像目标图像。

代码

import numpy as np
import matplotlib.pyplot as plt
import cv2
import time
import matplotlib
def arrayToHist(img, bins):
    hist, _ = np.histogram(img.flatten(), bins, [0,256])
    return hist / np.prod(img.shape)

def histMatch(img, hist_match):
    hist = arrayToHist(img, 256)
    cdf_img = hist.cumsum()
    cdf_match = hist_match.cumsum()
    M = np.interp(cdf_img, cdf_match, np.arange(256))
    return M[img.astype(np.uint8)]

def process_channel(img, img_match):
    hist_match = arrayToHist(img_match, 256)
    img_matched = histMatch(img, hist_match)
    return ((img_matched - img_matched.min()) / (img_matched.max() - img_matched.min()) * 255).astype(np.uint8)

def multi_channel_hist_match(img, img_match):
    if img.ndim == 3:
        result = np.zeros_like(img)
        for i in range(img.shape[2]):
            result[:,:,i] = process_channel(img[:,:,i], img_match[:,:,i])
    elif img.ndim == 2:
        result = process_channel(img, img_match)
    else:
        raise ValueError("Input images must be 2D or 3D arrays")
    return result

if __name__ == '__main__':
    start_time = time.time()

    imdir = "Colorbalance_1.jpg"
    imdir_match = "Colorbalance_2.jpg"

    img = cv2.imread(imdir)[..., ::-1]
    img_match = cv2.imread(imdir_match)[..., ::-1]
    img_matched = multi_channel_hist_match(img_match, img)
    matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 用黑体显示中文
    plt.figure()
    plt.subplot(1, 3, 1)
    plt.title("原始图片")
    plt.imshow(img)
    plt.subplot(1, 3, 2)
    plt.title("match图片")
    plt.imshow(img_match)
    plt.subplot(1, 3, 3)
    plt.title("match后的图片")
    plt.imshow(img_matched)
    plt.savefig('1.png', format='png', bbox_inches='tight', pad_inches=0, dpi=300)
    plt.show()

    print(f'耗时 {time.time() - start_time}秒')

结果展示

Colorbalance_1

Colorbalance_3

img_matched

image-20240327174314050

代码解释

这段代码实现了直方图匹配,也就是将一张图像的颜色分布调整为与另一张图像相同。主要步骤包括读取图片、计算直方图、匹配直方图、处理图像的每个通道(对于彩色图像),然后显示和保存结果。

以下是代码中函数的具体解释:

  1. arrayToHist(img, bins): 这个函数将图像转换为直方图。它使用numpy的histogram函数来计算直方图,然后将直方图归一化,使其总和为1。
  2. histMatch(img, hist_match): 这个函数实现了直方图匹配。它首先计算输入图像的直方图和累积分布函数(CDF),然后使用numpy的interp函数找到匹配图像的CDF与输入图像的CDF之间的映射关系。最后,它使用这个映射关系将输入图像的每个像素值替换为匹配的像素值。
  3. process_channel(img, img_match): 这个函数处理图像的每个通道。它首先计算匹配图像的直方图,然后使用histMatch函数将输入图像的直方图匹配到匹配图像的直方图。最后,它将匹配后的图像归一化到0-255的范围,并将其转换为8位无符号整数。
  4. multi_channel_hist_match(img, img_match): 这个函数处理多通道图像。如果输入图像是三维的(即,它有多个通道),那么它将对每个通道分别进行处理。如果输入图像是二维的(即,它只有一个通道),那么它将直接处理这个通道。

在主程序中,首先读取两张图像,然后使用multi_channel_hist_match函数将一张图像的直方图匹配到另一张图像的直方图。然后,它使用matplotlib来显示原始图像、匹配图像和匹配后的图像,并保存匹配后的图像为PNG文件。最后,它打印出程序的运行时间。

小结

这里的遥感影像匀色,本质上是对8bit的图片进行匀色。

即需要在匀色前,要把遥感影像的位深转换为8比特。