2013-04-15 39 views
3

我想通過使用Python的主成分分析(PCA)實現人臉識別。其中一個步驟是通過減去平均面向量mn = T - m來標準化輸入(測試)圖像TPython - ValueError:操作數無法與形狀廣播

這裏是我的代碼:

#Step1: put database images into a 2D array 
filenames = glob.glob('C:\\Users\\Karim\\Downloads\\att_faces\\New folder/*.pgm') 
filenames.sort() 
img = [Image.open(fn).convert('L').resize((90, 90)) for fn in filenames] 
images = np.asarray([np.array(im).flatten() for im in img]) 

#Step 2: find the mean image and the mean-shifted input images 
m = images.mean(axis=0) 
shifted_images = images - m 

#Step 7: input image 
input_image = Image.open('C:\\Users\\Karim\\Downloads\\att_faces\\1.pgm').convert('L').resize((90, 90)) 
T = np.asarray(input_image) 
n = T - mean_image 

但我得到一個錯誤Traceback (most recent call last): File "C:/Users/Karim/Desktop/Bachelor 2/New folder/new3.py", line 46, in <module> n = T - m ValueError: operands could not be broadcast together with shapes (90,90) (8100)

回答

3

mean_image被計算爲扁平陣列:

images = np.asarray([np.array(im).flatten() for im in img]) 
mean_image = images.mean(axis=0) 

input_image是90x90。因此錯誤。您也應該將輸入圖像變平,或者不要將原始圖像變平(我不太明白爲什麼要這麼做),或者將mean_image更改爲90x90,僅用於此操作。

+0

圖像必須展平爲二維數組而不是三維圖像,才能計算均值,協方差,特徵值和特徵向量。另一方面,如果輸入圖像變平坦,它將是一維數組,我也不能計算均值,協方差,特徵值和特徵向量。 – user2229953

+2

@ user2229953 @askewchan指出,我認爲任何接受'axis'參數的函數都不需要它。無論如何,現在你要從90x90陣列中減去8100 1D陣列,這個陣列必須以某種方式固定。 –

3

正如@Lev所說的,你已經扁平化了你的數組。你實際上並不需要這樣做來表達意思。假設你有2個3x4的圖像陣列,那麼你就會有這樣的事情:

In [291]: b = np.random.rand(2,3,4) 

In [292]: b.shape 
Out[292]: (2, 3, 4) 

In [293]: b 
Out[293]: 
array([[[ 0.18827554, 0.11340471, 0.45185287, 0.47889188], 
     [ 0.35961448, 0.38316556, 0.73464482, 0.37597429], 
     [ 0.81647845, 0.28128797, 0.33138755, 0.55403119]], 

     [[ 0.92025024, 0.55916671, 0.23892798, 0.59253267], 
     [ 0.15664109, 0.12457157, 0.28139198, 0.31634361], 
     [ 0.33420446, 0.27599807, 0.40336601, 0.67738928]]]) 

在第一軸進行平均,留下陣列的形狀:

In [300]: b.mean(0) 
Out[300]: 
array([[ 0.55426289, 0.33628571, 0.34539042, 0.53571227], 
     [ 0.25812778, 0.25386857, 0.5080184 , 0.34615895], 
     [ 0.57534146, 0.27864302, 0.36737678, 0.61571023]]) 

In [301]: b - b.mean(0) 
Out[301]: 
array([[[-0.36598735, -0.222881 , 0.10646245, -0.0568204 ], 
     [ 0.10148669, 0.129297 , 0.22662642, 0.02981534], 
     [ 0.24113699, 0.00264495, -0.03598923, -0.06167904]], 

     [[ 0.36598735, 0.222881 , -0.10646245, 0.0568204 ], 
     [-0.10148669, -0.129297 , -0.22662642, -0.02981534], 
     [-0.24113699, -0.00264495, 0.03598923, 0.06167904]]]) 

對於許多使用,這也會比將圖像保存爲數組列表更快,因爲numpy操作是在一個數組上完成的,而不是通過數組列表完成的。大多數方法(如mean,cov等)接受axis參數,並且您可以列出所有尺寸以在不需要展平的情況下執行它。

若要將此你的腳本,我會做這樣的事情,保持了原有的維度:

images = np.asarray([Image.open(fn).convert('L').resize((90, 90)) for fn in filenames]) 
# so images.shape = (len(filenames), 90, 90) 

m = images.mean(0) 
# numpy broadcasting will automatically subract the (90, 90) mean image from each of the `images` 
# m.shape = (90, 90) 
# shifted_images.shape = images.shape = (len(filenames), 90, 90) 
shifted_images = images - m 

#Step 7: input image 
input_image = Image.open(...).convert('L').resize((90, 90)) 
T = np.asarray(input_image) 
n = T - m 

作爲最後的評論,如果速度是一個問題,這將是更快地使用np.dstack加入你的圖片:

In [354]: timeit b = np.asarray([np.empty((50,100)) for i in xrange(1000)]) 
1 loops, best of 3: 824 ms per loop 

In [355]: timeit b = np.dstack([np.empty((50,100)) for i in xrange(1000)]).transpose(2,0,1) 
10 loops, best of 3: 118 ms per loop 

但它很可能是加載圖像需要大部分的時間,如果是這樣的話,你可以忽略這一點。

+1

我想你的建議,但我蓋特錯誤'回溯(最近最後一次通話): 文件「C:/用戶/卡里姆/桌面/本科2 /新建文件夾/ new4.py」,第12行,在 圖像= np.asarray([。Image.open(FN).convert( 'L')調整((90,90)),用於在文件名中FN]) 文件「C:\ Python27 \ lib中\站點包\ numpy的\核心\ numeric.py」,線320,在asarray 回報陣列(A,D型,複製=假order =序列) 關於SystemError:無異常錯誤返回set' – user2229953

+0

OK,我不明白的錯誤,但嘗試將'np.asarray'改爲'np.array'。 – askewchan

+0

另外,嘗試你有什麼,但擺脫'.flatten':'imgs = [Image.open(fn).convert('L')。resize((90,90))爲fn在文件名]'; 'image = np.asarray([img] img in imgs])' – askewchan

相關問題