[英]How can I quickly change pixels in a image from a color dictionary?
我有一個圖像,我想從顏色圖中更改圖像中的所有顏色,例如。 {(10,20,212):(60,40,112)...}
目前,我正在讀取圖像 OpenCV,然后遍歷圖像數組並更改每個像素,但這非常慢。
有什么辦法可以更快地做到這一點嗎?
我對這個問題提供兩個答案。 這個答案更基於 PIL/Pillow ,另一個更基於OpenCV 。 結合我的其他答案閱讀此答案,並可能混合搭配。
您可以使用調色板來完成。 如果您不熟悉調色圖像,而不是在每個像素位置都有一個 RGB 值,您可以在多達 256 種顏色的調色板中使用一個簡單的 8 位索引。
因此,我們可以做的是將您的圖像加載為 PIL 圖像,並將其量化為您擁有的一組輸入顏色。 然后每個像素將具有地圖中顏色的索引。 然后只需用您要映射到的顏色替換調色板。
#!/usr/bin/env python3
import numpy as np
from PIL import Image
def QuantizeToGivenPalette(im, palette):
"""Quantize image to a given palette.
The input image is expected to be a PIL Image.
The palette is expected to be a list of no more than 256 R,G,B values."""
e = len(palette)
assert e>0, "Palette unexpectedly short"
assert e<=768, "Palette unexpectedly long"
assert e%3==0, "Palette not multiple of 3, so not RGB"
# Make tiny, 1x1 new palette image
p = Image.new("P", (1,1))
# Zero-pad the palette to 256 RGB colours, i.e. 768 values and apply to image
palette += (768-e)*[0]
p.putpalette(palette)
# Now quantize input image to the same palette as our little image
return im.convert("RGB").quantize(palette=p)
# Open input image and palettise to "inPalette" so each pixel is replaced by palette index
# ... so all black pixels become 0, all red pixels become 1, all green pixels become 2...
im = Image.open('image.png').convert('RGB')
inPalette = [
0,0,0, # black
255,0,0, # red
0,255,0, # green
0,0,255, # blue
255,255,255 # white
]
r = QuantizeToGivenPalette(im,inPalette)
# Now simply replace the palette leaving the indices unchanged
newPalette = [
255,255,255, # white
0,255,255, # cyan
255,0,255, # magenta
255,255,0, # yellow
0,0,0 # black
]
# Zero-pad the palette to 256 RGB colours, i.e. 768 values
newPalette += (768-len(newPalette))*[0]
# And finally replace the palette with the new one
r.putpalette(newPalette)
# Save result
r.save('result.png')
輸入圖像
輸出圖像
所以,具體是什么,你問與舊的顏色值映射到新的字典做,你會想初始化oldPalette
你的詞典的按鍵newPalette
到您的字典的值。
關鍵詞:Python、PIL、枕頭、圖像、圖像處理、量化、量化、特定調色板、給定調色板、指定調色板、已知調色板、重新映射、重新映射、顏色映射、映射。
我對這個問題提供兩個答案。 這個答案更基於OpenCV ,另一個更基於 PIL/Pillow。 結合我的其他答案閱讀此答案,並可能混合搭配。
您可以使用 Numpy 的linalg.norm()
來查找顏色之間的距離,然后使用linalg.norm()
argmin()
來選擇最近的。 然后,您可以使用 LUT “查找表”根據圖像中的現有值查找新值。
#!/usr/bin/env python3
import numpy as np
import cv2
def QuantizeToGivenPalette(im, palette):
"""Quantize image to a given palette.
The input image is expected to be a Numpy array.
The palette is expected to be a list of R,G,B values."""
# Calculate the distance to each palette entry from each pixel
distance = np.linalg.norm(im[:,:,None] - palette[None,None,:], axis=3)
# Now choose whichever one of the palette colours is nearest for each pixel
palettised = np.argmin(distance, axis=2).astype(np.uint8)
return palettised
# Open input image and palettise to "inPalette" so each pixel is replaced by palette index
# ... so all black pixels become 0, all red pixels become 1, all green pixels become 2...
im=cv2.imread("image.png",cv2.IMREAD_COLOR)
inPalette = np.array([
[0,0,0], # black
[0,0,255], # red
[0,255,0], # green
[255,0,0], # blue
[255,255,255]], # white
dtype=np.uint8)
r = QuantizeToGivenPalette(im,inPalette)
# Now make LUT (Look Up Table) with the 5 new colours
LUT = np.zeros((5,3),dtype=np.uint8)
LUT[0]=[255,255,255] # white
LUT[1]=[255,255,0] # cyan
LUT[2]=[255,0,255] # magenta
LUT[3]=[0,255,255] # yellow
LUT[4]=[0,0,0] # black
# Look up each pixel in the LUT
result = LUT[r]
# Save result
cv2.imwrite('result.png', result)
輸入圖像
輸出圖像
關鍵詞:Python、PIL、枕頭、圖像、圖像處理、量化、量化、特定調色板、給定調色板、指定調色板、已知調色板、重新映射、重新映射、顏色圖、映射、LUT、linalg.norm。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.