python2.x中两幅图像的直方图匹配?

发布于 2021-01-29 18:20:47

我正在尝试匹配两个图像的直方图(在MATLAB中,这是可以做到的)
使用
imhistmatch).
标准Python库中是否有可用的等效函数?我已经
查看了OpenCV、scipy和numpy,但没有看到任何类似的功能。

关注者
0
被浏览
226
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    我以前写过一个答案
    这里解释如何做
    图像直方图的分段线性插值
    高光/中音/阴影的特定比率。
    相同的基本原则是[直方图]的基础
    匹配两人之间
    图像。基本上,你要计算出你的源和目标的累积直方图
    模板图像,然后线性插值,以找到唯一的像素值
    与唯一像素的分位数最接近的模板图像
    源图像中的值:

    import numpy as np
    
    def hist_match(source, template):
        """
        Adjust the pixel values of a grayscale image such that its histogram
        matches that of a target image
    
        Arguments:
        -----------
            source: np.ndarray
                Image to transform; the histogram is computed over the flattened
                array
            template: np.ndarray
                Template image; can have different dimensions to source
        Returns:
        -----------
            matched: np.ndarray
                The transformed output image
        """
    
        oldshape = source.shape
        source = source.ravel()
        template = template.ravel()
    
        # get the set of unique pixel values and their corresponding indices and
        # counts
        s_values, bin_idx, s_counts = np.unique(source, return_inverse=True,
                                                return_counts=True)
        t_values, t_counts = np.unique(template, return_counts=True)
    
        # take the cumsum of the counts and normalize by the number of pixels to
        # get the empirical cumulative distribution functions for the source and
        # template images (maps pixel value --> quantile)
        s_quantiles = np.cumsum(s_counts).astype(np.float64)
        s_quantiles /= s_quantiles[-1]
        t_quantiles = np.cumsum(t_counts).astype(np.float64)
        t_quantiles /= t_quantiles[-1]
    
        # interpolate linearly to find the pixel values in the template image
        # that correspond most closely to the quantiles in the source image
        interp_t_values = np.interp(s_quantiles, t_quantiles, t_values)
    
        return interp_t_values[bin_idx].reshape(oldshape)
    

    For example:

    from matplotlib import pyplot as plt
    from scipy.misc import lena, ascent
    
    source = lena()
    template = ascent()
    matched = hist_match(source, template)
    
    def ecdf(x):
        """convenience function for computing the empirical CDF"""
        vals, counts = np.unique(x, return_counts=True)
        ecdf = np.cumsum(counts).astype(np.float64)
        ecdf /= ecdf[-1]
        return vals, ecdf
    
    x1, y1 = ecdf(source.ravel())
    x2, y2 = ecdf(template.ravel())
    x3, y3 = ecdf(matched.ravel())
    
    fig = plt.figure()
    gs = plt.GridSpec(2, 3)
    ax1 = fig.add_subplot(gs[0, 0])
    ax2 = fig.add_subplot(gs[0, 1], sharex=ax1, sharey=ax1)
    ax3 = fig.add_subplot(gs[0, 2], sharex=ax1, sharey=ax1)
    ax4 = fig.add_subplot(gs[1, :])
    for aa in (ax1, ax2, ax3):
        aa.set_axis_off()
    
    ax1.imshow(source, cmap=plt.cm.gray)
    ax1.set_title('Source')
    ax2.imshow(template, cmap=plt.cm.gray)
    ax2.set_title('template')
    ax3.imshow(matched, cmap=plt.cm.gray)
    ax3.set_title('Matched')
    
    ax4.plot(x1, y1 * 100, '-r', lw=3, label='Source')
    ax4.plot(x2, y2 * 100, '-k', lw=3, label='Template')
    ax4.plot(x3, y3 * 100, '--r', lw=3, label='Matched')
    ax4.set_xlim(x1[0], x1[-1])
    ax4.set_xlabel('Pixel value')
    ax4.set_ylabel('Cumulative %')
    ax4.legend(loc=5)
    

    对于一对RGB图像,您可以将此函数分别应用于每个图像频道。根据你想要达到的效果,你可能想要
    首先将图像转换为不同的颜色空间。例如,你可以转换成HSV空间然后呢如果你想匹配亮度,就在V频道上进行匹配,但不是色调或饱和度。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看