您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關基于OpenCV如何生成圖像直方圖,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
在開始定義直方圖之前,為簡單起見我們先使用灰度圖像,稍后再解釋彩色圖像的處理過程。
圖像直方圖表示圖像的像素分布情況。換言之,圖像直方圖顯示具有特定像素值的圖像點數量。例如,假設正常圖像的像素強度在0到255之間變化。為了生成其直方圖,我們只需要計算像素值為0的像素數量,然后計算1并繼續到255即可。在圖1中,我們有一個5 * 5的樣本圖像,我們通過計算每個像素強度的數量來創建直方圖表。
圖1:生成圖像直方圖的過程
在python中,我們可以使用以下兩個函數來創建然后顯示圖像的直方圖。
import matplotlib.pyplot as plt import numpy as np def generate_histogram(img, do_print): """ @params: img: can be a grayscale or color image. We calculate the Normalized histogram of this image. @params: do_print: if or not print the result histogram @return: will return both histogram and the grayscale image """ if len(img.shape) == 3: # img is colorful, so we convert it to grayscale gr_img = np.mean(img, axis=-1) else: gr_img = img '''now we calc grayscale histogram''' gr_hist = np.zeros([256]) for x_pixel in range(gr_img.shape[0]): for y_pixel in range(gr_img.shape[1]): pixel_value = int(gr_img[x_pixel, y_pixel]) gr_hist[pixel_value] += 1 '''normalizing the Histogram''' gr_hist /= (gr_img.shape[0] * gr_img.shape[1]) if do_print: print_histogram(gr_hist, name="n_h_img", title="Normalized Histogram") return gr_hist, gr_img def print_histogram(_histrogram, name, title): plt.figure() plt.title(title) plt.plot(_histrogram, color='#ef476f') plt.bar(np.arange(len(_histrogram)), _histrogram, color='#b7b7a4') plt.ylabel('Number of Pixels') plt.xlabel('Pixel Value') plt.savefig("hist_" + name)
在大多數情況下,當我們創建直方圖時,我們通過將每個強度值的像素數除以歸一化因子(即圖像寬度和圖像高度的乘積)來對直方圖進行歸一化。為了便于使用,如果generate_histogram函數的輸入圖像是彩色圖像,我們首先將其轉換為灰度圖像(請參見第6行)。
直方圖均衡化通常用于增強圖像的對比度。因此,該技術不能保證始終提高圖像質量。計算CDF(累積分布函數)是均衡圖像直方圖的常用方法。在圖2中,我們計算了在圖1中創建的樣本圖像的CDF。此外,在圖3中,我們顯示了先前樣本的均衡直方圖。
圖2:計算CDF。
圖3:均方圖。
為了計算python中的均衡直方圖,我們創建了以下代碼:
def equalize_histogram(img, histo, L): eq_histo = np.zeros_like(histo) en_img = np.zeros_like(img) for i in range(len(histo)): eq_histo[i] = int((L - 1) * np.sum(histo[0:i])) print_histogram(eq_histo, name="eq_"+str(index), title="Equalized Histogram") '''enhance image as well:''' for x_pixel in range(img.shape[0]): for y_pixel in range(img.shape[1]): pixel_val = int(img[x_pixel, y_pixel]) en_img[x_pixel, y_pixel] = eq_histo[pixel_val] '''creating new histogram''' hist_img, _ = generate_histogram(en_img, print=False, index=index) print_img(img=en_img, histo_new=hist_img, histo_old=histo, index=str(index), L=L) return eq_histo
這是我們拍攝的3張不同圖片,并用作示例。如圖4所示,對于第一個圖像,直方圖顯示低強度像素的數量多于明亮像素。對于第二張圖像,情況完全相反,其中較亮像素的密度遠大于較暗像素的密度。第三張圖片似乎具有半正態直方圖。
圖4:三種不同類型的圖像及其直方圖和均等的直方圖。
如前所述,我們可以使用圖像的均衡直方圖修改圖像的對比度。如代碼2第12行所示,對于輸入圖像中的每個像素,我們可以使用其均等值。結果可能比原始圖像更好,但不能保證。在圖5中,我們描述了3張圖像的修改版本。如圖所示,使用其均等的直方圖修改圖像會產生對比度更高的圖像。此功能在許多計算機視覺任務中很有用。
圖5:使用均衡直方圖的對比度修改。最左列是原始圖像。中間一欄是對比度修改的結果。
最右邊的列是修改后的圖像的直方圖。
假設我們有兩個圖像,每個圖像都有其特定的直方圖。因此,我們想在進一步解決此問題之前,是否可以根據另一幅圖像的對比度來修改一幅圖像?答案是肯定的。實際上,這就是直方圖匹配的定義。換句話說,給定圖像A和B,可以根據B修改A的對比度。
當我們要統一一組圖像的對比度時,直方圖匹配非常有用。實際上,直方圖均衡也可以視為直方圖匹配,因為我們將輸入圖像的直方圖修改為與正態分布相似。
為了匹配圖像A和B的直方圖,我們需要首先均衡兩個圖像的直方圖。然后,我們需要使用均衡后的直方圖將A的每個像素映射到B。然后,我們基于B修改A的每個像素。
讓我們使用圖6中的以下示例來闡明以上段落。
圖6:直方圖匹配
在圖6中,我們將圖像A作為輸入圖像,將圖像B作為目標圖像。我們要基于B的分布來修改A的直方圖。第一步,我們計算A和B的直方圖和均等直方圖。然后,我們需要根據該值映射A的每個像素它的均衡直方圖求B的值。因此,例如,對于A中強度級別為0的像素,A均衡直方圖的對應值為4。現在,我們看一下B均衡直方圖并找到強度值對應于4,即0。因此我們將0強度從A映射到0 從B開始。對于A的所有強度值,我們繼續進行。如果從A到B的均衡直方圖中沒有映射,我們只需要選擇最接近的值即可。
def find_value_target(val, target_arr): key = np.where(target_arr == val)[0] if len(key) == 0: key = find_value_target(val+1, target_arr) if len(key) == 0: key = find_value_target(val-1, target_arr) vvv = key[0] return vvv def match_histogram(inp_img, hist_input, e_hist_input, e_hist_target, _print=True): '''map from e_inp_hist to 'target_hist ''' en_img = np.zeros_like(inp_img) tran_hist = np.zeros_like(e_hist_input) for i in range(len(e_hist_input)): tran_hist[i] = find_value_target(val=e_hist_input[i], target_arr=e_hist_target) print_histogram(tran_hist, name="trans_hist_", title="Transferred Histogram") '''enhance image as well:''' for x_pixel in range(inp_img.shape[0]): for y_pixel in range(inp_img.shape[1]): pixel_val = int(inp_img[x_pixel, y_pixel]) en_img[x_pixel, y_pixel] = tran_hist[pixel_val] '''creating new histogram''' hist_img, _ = generate_histogram(en_img, print=False, index=3) print_img(img=en_img, histo_new=hist_img, histo_old=hist_input, index=str(3), L=L)
圖7:直方圖匹配示例。我們修改了左圖像的直方圖以匹配中心圖像的直方圖。
圖7示出了直方圖匹配的示例。如大家所見,盡管最左邊的圖像是明亮的圖像,但就對比度級別而言,可以將中心圖像視為更好的圖像。因此,我們決定使用中心圖像的收縮來修改最左邊的圖像。結果,即最右邊的圖像已得到改善。
關于“基于OpenCV如何生成圖像直方圖”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。