2012-09-28 77 views
2

我是Python新手,嘗試使用PIL來執行我需要的Arduino項目的解析任務。這個問題適用於Image.convert()方法和調色板,抖動等選項PIL - 想要抖動,但限制調色板導致問題

我有一些硬件能夠顯示一次只有16種顏色的圖像(但他們可以指定RGB三胞胎)。所以,我想自動完成一個任意的真彩色PNG圖像,選擇一個「最佳」16色調色板來表示它,並將圖像轉換爲僅包含16種顏色的調色板。

我想使用抖動。問題是,image.convert()方法似乎有點時髦。它的論點沒有完全記錄(PIL documentation for Image.convert()),所以我不知道是否是我的錯,或者如果方法是越野車。

我的代碼的簡化版本如下:基於某些搜索我做

import Image 
MyImageTrueColor = Image.new('RGB',100,100) # or whatever dimension... 

# I paste some images from several other PNG files in using MyImageTrueColor.paste() 

MyImageDithered = MyImageTrueColor.convert(mode='P', 
    colors=16, 
    dither=1 
    ) 

(例如:​​)我認爲這方法應該做我想做的,但沒有運氣。它會讓圖像變得更加銳利,但會產生超過16種顏色的圖像。

爲了確保,我刪除了「抖動」參數。相同的輸出。

我重新添加了「dither = 1」參數,並拋出Image.ADAPTIVE參數(如上面的鏈接所示),以查看發生了什麼。這導致了包含16種顏色的圖像,但沒有抖動。

我在這裏錯過了什麼嗎? PIL越野車?我提出的解決方案是執行2個步驟,但似乎是sl and和不必要的。我想弄清楚如何做到這一點:-)爲了完整性,這裏是我的代碼版本,可以產生正確的結果 - 但它是以一種馬虎的方式做到的。 (第一步導致抖動圖像> 16色,第二步導致圖像僅包含16色。)

MyImage_intermediate = MyImageTrueColor.convert(mode='P', 
    colors=16 
    ) 
MyImageDithered = MyImage_intermediate.convert(mode='P', 
    colors=16, 
    dither=1, 
    palette=Image.ADAPTIVE 
    ) 

謝謝!

+0

上面顯示的鏈接明確指出「我使用Image.ADAPTIVE避免抖動」,所以我不確定您是否驚訝於投入Image.ADAPTIVE避免抖動... – abarnert

+0

順便說一下,我懷疑抖動到216種網頁顏色,然後量化爲網頁調色板的最佳16種顏色,通常會給您帶來比僅爲您的原始圖像量化最佳16種顏色更糟糕的效果。你的測試是否顯示其他?如果是這樣,也許你的解決方法是可以接受的。 – abarnert

回答

5

呃,你沒有正確地調用事物,所以它不應該工作......但即使我們正確地調用事情,我也不確定它會起作用。

首先,PIL手冊的「官方」免費版本既不完整也過時; http://effbot.org/imagingbook/image.htm的草案版本不夠完整並且過時。

im.convert(「P」,**選項)⇒圖像

相同,但轉換的「RGB」圖像到 8比特調色圖像時提供了更好的控制。可用的選項有:

抖動=。控制抖動。默認爲FLOYDSTEINBERG,其中 將錯誤分配給相鄰像素。要禁用抖動,請使用 NONE。

palette =。控制調色板的生成。默認是WEB,這是 標準的216色「網頁調色板」。要使用優化的調色板,請使用 ADAPTIVE。

colors =。當調色板爲ADAPTIVE時,控制用於調色板的顏色數量。默認爲最大值,256色。

所以,首先,你不能沒有ADAPTIVE使用colors - 因爲顯而易見的原因:唯一的其他選擇是WEB,只處理一個固定的216色調色板。

第二,你不能通過1dither。如果碰巧是FLOYDSTEINBERG的值,那可能會有效,但那是3。所以,你傳遞了一個無證的值;誰知道會做什麼?特別是因爲,通過尋找一切聽起來可能名稱,抖動算法的常量,他們都沒有值1

所以,你可以嘗試將其更改爲dither=Image.FLOYDSTEINBERG(與palette=Image.ADAPTIVE一起),看看是否是有區別。

但是,看代碼,它看起來像這樣是不會有什麼好處:

if mode == "P" and palette == ADAPTIVE: 
    im = self.im.quantize(colors) 
    return self._new(im) 

這發生之前,我們得到的抖動碼。所以和調用(現在已被棄用/私有)方法量化完全一樣。

多個線程表明高層次convert函數僅用於展示「抖動到網頁調色板」或「映射到最近的N種顏色」。這似乎與1.1.6及更高版本略有變化,但文檔和實現都還不完整。在http://comments.gmane.org/gmane.comp.python.image/2947其中一位開發人員建議閱讀PIL/Image.py源文件。

所以,它看起來就是你需要做的。不管Image.convertImage.WEB模式中做了什麼,您都希望這樣做 - 但使用由Image.quantize(colors)生成的調色板,而不是網頁調色板。

當然大部分的膽量發生在C代碼(self.im.quantize下,self.im.convert等),但你可以做一些這樣的僞代碼:

dummy = img.convert(mode='P', paletter='ADAPTIVE', colors=16) 
intermediate = img.copy() 
intermediate.setpalette(dummy.palette) 
dithered = intermediate._new(intermediate.im.convert('P', Image.FLOYDSTEINBERG)) 

話又說回來,你不得。您可能需要查看C頭文件或甚至是源代碼才能找到。或者可以在PIL郵件列表上詢問。 PS,如果您不熟悉PIL的膽量,img.im是PIL圖像對象img下面的C圖像對象。從我過去的經驗來看,前三次你不能通過PIL代碼瀏覽清楚,然後突然一切都變得更有意義。

+0

有沒有辦法將圖像映射到任意調色板?如果是這樣,你可以通過兩遍來完成,首先生成一個調色板,然後用抖動重新映射。 –

+0

@MarkRansom:問題是image.convert只會抖動到web調色板,所以只能完成16種顏色的量化,然後抖動到216,與他想要的相反。但我認爲底層C庫_can_可以做到這一點,這就是最終的僞代碼。 – abarnert