2015-09-18 8 views
9

İki görüntünün histogramlarını eşleştirmeye çalışıyorum (MATLAB uygulamasında bu imhistmatch kullanılarak yapılabilir). Standart bir Python kitaplığından eşdeğer bir işlev var mı? OpenCV, scipy ve numpy'ye baktım ama benzer bir işlev görmüyorum.Python 2.x'deki iki görüntünün histogram eşlemesi mi?

+0

PIL'i denediniz mi? – nln

+0

Evet. Bu bir utanç, python görüntü işleme gerçekten iyi bir şekil değil. – nln

+1

PIL ölmüyor - yeni 'yastık' paketi güncellenmiş bir uygulama – holdenweb

cevap

29

Daha önce belirli bir vurgu/orta ton/gölgelik oranını uygulamak için görüntü histogramında parçalı doğrusal enterpolasyonun nasıl yapılacağını açıklayan bir here cevabını yazdım.

İki görüntü arasında aynı temel ilkeler histogram matching'un altındadır. İçin

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) 

: Esasen en yakından kaynak görüntüdeki benzersiz piksel değerlerinin quantiles maç şablon görüntüdeki benzersiz piksel değerlerini bulmak için doğrusal enterpolasyon sonra, kaynak ve şablon görüntüler için kümülatif histogramlar hesaplamak örnek:

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) 

enter image description here

RGB görüntülerin bir çift için her bir renk kanalına ayrı ayrı bu işlevi geçerli olabilir.

+0

Giriş görüntülerine sahip olmadan emin olmak benim için zor, ancak kaynak görüntüde hedefle karşılaştırıldığında çok daha az ton varyasyonu olduğunda, açıkladığınız şey beklenen bir sonuç gibi geliyor. Kaynak resminizdeki "katı" alanlar içinde meydana gelebilecek olan şey, histogramı şablonunkiyle aynı olacak şekilde "genişletmek" için az miktarda rastgele varyasyonun yükseltilmesidir. Yardımcı olabilecek birkaç şey düşünebilirdim, ama genel olarak, kaynak ve şablon histogramları arasındaki fark ne kadar büyük olursa, "güzel" bir sonuç elde etmek de o kadar zor olur. –

+0

Bu konuşmaları okuyan diğerleri için, Ali'nin cevabı benim için iyi çalıştı. – ConfusinglyCuriousTheThird

+0

@ali_m: Bu yaklaşımı bir görüntünün görüntüsünde ve gölgeli bir versiyonunda denedim, ancak garip sonuçlar elde ediyor gibi görünüyor. Bunun neden olabileceğine dair bir ipucu var mı? – Megha