2016-10-16 66 views
1

我想編寫能夠在不使用內置Matplotlib hist函數的情況下顯示圖像直方圖的代碼。在Python中手動高效地創建圖像直方圖

這裏是我的代碼:

import cv2 as cv 
import numpy as np 
from matplotlib import pyplot as plt 

def manHist(img): 
    row, col = img.shape # img is a grayscale image 
    y = np.zeros((256), np.uint64) 
    for i in range(0,row): 
     for j in range(0,col): 
     y[img[i,j]] += 1 
    x = np.arange(0,256) 
    plt.bar(x,y,color="gray",align="center") 
    plt.show() 

def main(): 
    img = cv.imread("C:/Users/Kadek/Documents/MATLAB/2GS.jpg") 
    manHist(img) 

main() 

我的問題是,有沒有比較有效的方式,使像素值頻率的陣列,而不使用循環?

+0

沒有其他的比遍歷圖像中的每個值,儘管是矢量化的numpy的解決方案將快一些數量級 –

+0

因此,您沒有使用第三軸通道:'y [img [i,j]]'? – Divakar

+0

你可以使用'collections.Counter'來做這件事,儘管這可能對你來說不夠「手動」。 – kindall

回答

1

一個NumPy的基於矢量的解決辦法是用np.bincount -

out = np.bincount(img.ravel(),minlength=256) 

另一種量化方法基於.sum() -

out = (img.ravel() == np.arange(256)[:,None]).sum(1) 

採樣運行來驗證結果 -

In [155]: # Input image (512x512) as array 
    ...: img = np.random.randint(0,255,(512,512)) 
    ...: 
    ...: # Original code 
    ...: row, col = img.shape 
    ...: y = np.zeros((256), np.uint64) 
    ...: for i in range(0,row): 
    ...:  for j in range(0,col): 
    ...:   y[img[i,j]] += 1 
    ...:   

In [156]: out1 = np.bincount(img.ravel(),minlength=256) 

In [157]: out2 = (img.ravel() == np.arange(256)[:,None]).sum(1) 

In [158]: np.allclose(y,out1) 
Out[158]: True 

In [159]: np.allclose(y,out2) 
Out[159]: True 
+0

都在我的代碼中返回false。我寫的和你的完全一樣。 –

+0

@KadekDwiBudiUtama你在評論中沒有通過問題回答,是否應該是'row,col = img.shape'而不是? – Divakar

+0

哦,對不起。這隻在使用1個頻道後才起作用!謝謝! –