图像直方图匹配

  当我们谈到图像直方图匹配,我们实际上是在讨论一种图像处理技术,它的目标是将一张图像的像素值分布调整到与另一张图像的像素值分布相匹配。这对于图像处理中的许多任务是有用的,如图像增强、颜色校正等。
原理:
  灰度图像直方图匹配的原理基于直方图变换。每张图像的直方图表示了像素值的分布情况。直方图匹配通过调整图像的像素值,使得两张图像的直方图尽可能相似。这通常涉及到将输入图像的像素值映射到输出图像的像素值,以实现两者之间的分布匹配。
意义:
  直方图匹配可以用来改善图像的对比度、颜色平衡和细节。通过将图像的像素值映射到更合适的范围,可以使图像在视觉上更加吸引人。它也可以用于将图像从一种颜色空间转换到另一种颜色空间,或者用于匹配图像以匹配某种标准。
适用场景:
  1. 图像增强:当图像的对比度较低或细节不明显时,可以使用直方图匹配来增强图像的视觉效果。
  2. 颜色校正:当图像受到光照条件的影响或者摄像设备的色彩偏差时,可以使用直方图匹配来校正颜色。
  3. 风格迁移:在计算机视觉中,可以使用直方图匹配来实现图像的风格迁移,将一个图像的风格应用于另一个图像。
数学表示:
  直方图匹配可以表示为一个像素值的映射函数。假设我们有一个输入图像 I I I和一个目标图像 T T T,我们希望将输入图像的像素值映射到输出图像的像素值。这可以表示为:
O ( x , y ) = round ( T I ⋅ I ( x , y ) ) O(x, y) = \text{round}\left(\frac{T}{I} \cdot I(x, y)\right) O(x,y)=round(ITI(x,y))
  其中, O ( x , y ) O(x, y) O(x,y)是输出图像中的像素值, I ( x , y ) I(x, y) I(x,y)是输入图像中的像素值, T T T是目标图像的像素值范围。函数 round \text{round} round将结果四舍五入到最近的整数。
示例代码(Python):
  下面是一个使用OpenCV进行灰度图像直方图匹配的示例代码:

import cv2
import numpy as np

def HistMatch(input_image,target_image):
    input_image=cv2.imread(input_image,flags=0)
    target_image=cv2.imread(target_image,flags=0)

    if input_image is None or target_image is None:
        print('Unable to load input_image or target_image!')
        return
    else:
        # 计算输入图像和目标图像的直方图
        input_hist = cv2.calcHist([input_image], [0], None, [256], [0, 256])
        target_hist = cv2.calcHist([target_image], [0], None, [256], [0, 256])
        # 归一化直方图
        input_hist /= input_hist.sum()
        target_hist /= target_hist.sum()
        # 计算累积分布函数(CDF)
        input_cdf = input_hist.cumsum()
        target_cdf = target_hist.cumsum()
        # 计算映射函数
        mapping = np.interp(input_cdf, target_cdf, np.arange(256))
        # 将映射应用于输入图像
        output_image = mapping[input_image]
        # 转换回8位图像
        output_image = np.uint8(output_image)

        # 显示图像
        cv2.imshow('input_image', input_image)
        cv2.imshow('target_image', target_image)
        cv2.imshow('output_image', output_image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

imgfile1='./Images/cat.jpg'
imgfile2='./Images/Atest1.jpg'
HistMatch(imgfile1,imgfile2)

  上述代码假设输入图像和目标图像都是灰度图像。要在彩色图像上进行直方图匹配,需要对各个颜色通道分别进行处理。在彩色图像上的实现与灰度图像类似,但是需要将操作扩展到每个颜色通道(红色、绿色和蓝色通道)。以下是对彩色图像进行直方图匹配的代码示例:

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

def HistMatch(input_image,target_image):
    input_image=cv2.imread(input_image)
    target_image=cv2.imread(target_image)

    if input_image is None or target_image is None:
        print('Unable to load input_image or target_image!')
        return
    else:
        #先将输入图像和目标图像的通道进行分离
        input_channels=cv2.split(input_image)
        target_channels=cv2.split(target_image)
        # print(input_channels)

        output_channels=[]

        # zip 函数将每个输入可迭代对象中相同位置的元素组合在一起,生成一个新的元组,然后将这些元组组合成一个新的可迭代对象。
        for input_channel,target_channel in zip(input_channels,target_channels):

            # 计算输入图像和目标图像的直方图
            input_hist = cv2.calcHist([input_channel], [0], None, [256], [0, 256])
            target_hist = cv2.calcHist([target_channel], [0], None, [256], [0, 256])

            # 归一化直方图
            input_hist /= input_hist.sum()
            target_hist /= target_hist.sum()

            # 计算累积分布函数(CDF)
            input_cdf = input_hist.cumsum()
            target_cdf = target_hist.cumsum()

            # 计算映射函数
            mapping = np.interp(input_cdf, target_cdf, np.arange(256))

            # 将映射应用于输入通道
            output_channel = mapping[input_channel]

            # 转换回8位图像
            output_channel = np.uint8(output_channel)

            output_channels.append(output_channel)

        # 获得通道以获得输出图像
        output_image=cv2.merge(output_channels)

        plt.figure(figsize=(10, 7))
        plt.subplot(231), plt.title("Original image"), plt.axis('off')
        plt.imshow(cv2.cvtColor(input_image, cv2.COLOR_BGR2RGB))  # 显示原始图像

        plt.subplot(232), plt.title("Matching template"), plt.axis('off')
        plt.imshow(cv2.cvtColor(target_image, cv2.COLOR_BGR2RGB))  # 显示匹配模板

        plt.subplot(233), plt.title("Matching output"), plt.axis('off')
        plt.imshow(cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB))  # 显示匹配结果

        histImg, bins = np.histogram(input_image.flatten(), 256)  # 计算原始图像直方图
        plt.subplot(234, yticks=[]), plt.bar(bins[:-1], histImg)

        histRef, bins = np.histogram(target_image.flatten(), 256)  # 计算匹配模板直方图
        plt.subplot(235, yticks=[]), plt.bar(bins[:-1], histRef)

        histOut, bins = np.histogram(output_image.flatten(), 256)  # 计算匹配结果直方图
        plt.subplot(236, yticks=[]), plt.bar(bins[:-1], histOut)

        plt.show()



imgfile1='./Images/cat.jpg'
imgfile2='./Images/Atest1.jpg'
HistMatch(imgfile1,imgfile2)

Supongo que te gusta

Origin blog.csdn.net/qq_50993557/article/details/132462797
Recomendado
Clasificación