2010-06-23 24 views
4

我需要一個像這裏找到的函數:http://effbot.org/zone/pil-comparing-images.htm計算兩幅圖像之間的均方根差。代碼如下所示:使用Python和PIL的兩幅圖像之間的均方根差異

import ImageChops 
import math, operator 

def rmsdiff(im1, im2): 
    "Calculate the root-mean-square difference between two images" 

    h = ImageChops.difference(im1, im2).histogram() 

    # calculate rms 
    return math.sqrt(reduce(operator.add, 
     map(lambda h, i: h*(i**2), h, range(256)) 
     )/(float(im1.size[0]) * im1.size[1])) 

試圖運行該代碼將導致以下錯誤:類型錯誤:不支持的操作類型爲**或POW():「NoneType」和「INT」。這是它的問題?

回答

2

胡亂猜測在這裏,但在你上線試試這個,看看它的工作原理:

return math.sqrt(sum(h*(i**2) for i, h in enumerate(h)))/(float(im1.size[0]) * im1.size[1])) 

我不知道隨便你爲什麼會得到TypeError你所描述的,但是如果你使用上面的代碼行,並繼續得到它,嚴重奇怪的事情正在進行。

3

問題是,它創建的直方圖沒有值(或者真的是無值),沒有相應的像素值。

即,當您找到兩幅圖像的差異時,得到的圖像沒有任何像素,例如相差43個單位,所以h [43] =無。

稍後,您嘗試訪問範圍(256)中每個亮度處的像素數量並對其進行平方,這導致它對無** 2應該是什麼感到困惑。

考慮將range(256)更改爲h.keys()

另外,您使用h表示兩個不同的事物,請考慮將其中一個的名稱更改爲更有意義的名稱。

0

請看這裏https://gist.github.com/bo858585/5377492。 該腳本使用均方根(不分割爲sqrt(3) - 像素是3號RGB矢量)將每個對應的相應區域的所有jpg圖像從用戶目錄(指定它) (由矩陣20 * 20處的位置)兩個比較圖像的像素。腳本總結這些像素對之間的距離,並將這個總和劃分爲最大可能的距離 - 這樣腳本就可以得到兩幅圖像的相似度。在比較調整到20 * 20的所有圖像之前。您可能會改變MAX_DISTANCE(從0到400),腳本會將或多或少相似的圖像分組到一個組。

2

看來mapreduce在這裏並不是真的需要。

rmsdiff的改進版本可以是:

def rmsdiff(im1, im2): 
    "Calculate the root-mean-square difference between two images" 
    diff = ImageChops.difference(im1, im2) 
    h = diff.histogram() 
    sq = (value*((idx%256)**2) for idx, value in enumerate(h)) 
    sum_of_squares = sum(sq) 
    rms = math.sqrt(sum_of_squares/float(im1.size[0] * im1.size[1])) 
    return rms 

這裏是source。根據我的測試,Mark Krautheim提出的改進至少有一個重要原因:與原始版本相反,在將圖像與自身進行比較時,返回值爲0.0。短自己使用NumPy

from PIL import Image # No need for ImageChops 
import math 
from skimage import img_as_float 
from skimage.measure import compare_mse as mse 

def rmsdiff(im1, im2): 
    """Calculates the root mean square error (RSME) between two images""" 
    return math.sqrt(mse(img_as_float(im1), img_as_float(im2))) 

可選地寫一些東西:

0

請考慮解決該使用現有的解決方案,如scikit-image

from PIL import Image, ImageChops 
import math 
import numpy as np 

def rmsdiff(im1, im2): 
    """Calculates the root mean square error (RSME) between two images""" 
    errors = np.asarray(ImageChops.difference(im1, im2))/255 
    return math.sqrt(np.mean(np.square(errors))) 

注意,這兩種方法在範圍[0.0治療像素強度作爲,1.0]而不是[0,255]。