2009-10-24 24 views
14

Ben ancak bunun yanı sıra ben umduğumuz gibi çalışmıyor benim görüntüden belli bir renk kaldırmak için çalışıyorum. Bunun kaldırıldı nerede ne etrafında garip renkli piksel küçük bir hayalet bırakır böylece görüntü kalitesi biraz kayıplı olduğu ancak burada Using PIL to make all white pixels transparent? görüldüğü gibi aynı şeyi yapmaya çalıştı. Üç değerin 100'ün altında olması durumunda değişim pikselleri gibi bir şey yapmayı denedim, ancak görüntü kalitesiz olduğundan, etraftaki pikseller bile siyah değildi.PIL Rengi Değiştirmenin En İyi Yolu

herkes onu çevreleyen bir renk ve bir şey değiştirmek için Python PIL ile daha iyi bir yol biliyor mu? Bu, nesneleri tamamen kaldırmak için düşünebildiğim tek kesin ateş yoludur, ancak bunu yapmanın bir yolunu düşünemiyorum.

resim siyah beyaz arka plan ve metin var. Diyelim ki metni arkamda hiçbir eser bırakmadan tamamen görüntüden kaldırmak istiyorum.

gerçekten birilerinin yardımına takdir ediyorum! Teşekkür

cevap

5

Sen 2 boyutlu bir dizi olarak görüntüyü temsil etmek gerekir. Bu piksel listelerin bir listesini yapmak, ya da bazı akıllı matematik 2d olarak 1-boyutlu bir dizi görüntüleme ya da anlamına gelir. Ardından, hedeflenen her piksel için tüm çevreleyen pikselleri bulmanız gerekir. Böyle kullanmak istiyorsunuz, Yani

def targets(x,y): 
    yield (x,y) # Center 
    yield (x+1,y) # Left 
    yield (x-1,y) # Right 
    yield (x,y+1) # Above 
    yield (x,y-1) # Below 
    yield (x+1,y+1) # Above and to the right 
    yield (x+1,y-1) # Below and to the right 
    yield (x-1,y+1) # Above and to the left 
    yield (x-1,y-1) # Below and to the left 

: Böylece bir piton jeneratör ile bu yapabileceğini piksel diyorsunuz mesela kolayca tanımlanabilir değilseniz

for x in range(width): 
    for y in range(height): 
     px = pixels[x][y] 
     if px[0] == 255 and px[1] == 255 and px[2] == 255: 
      for i,j in targets(x,y): 
       newpixels[i][j] = replacementColor 
4

(r < 100 ve g < 100 b < 100) da doğru siyah bölgeyle eşleşmiyor, bu çok gürültü var demektir.

bir bölge tanımlamak ve istediğiniz renk ile doldurun olacaktır, el bölge tanımlayabilir veya örneğin kenar algılama yoluyla olabilir

en iyi yolu http://bitecode.co.uk/2008/07/edge-detection-in-python/

veya daha karmaşık bir yaklaşım, nesneleri tanımlamak için opencv (http://opencv.willowgarage.com/wiki/) gibi kitaplık kullanmak olacaktır.

22

bunu yapmanın en iyi yolu bir renk yerine Gimp kullanılan "renkli alfa" algoritmasını kullanmaktır. Davanızda mükemmel çalışır. Ben bir açık kaynak piton fotoğraf işlemcisi phatch için PIL kullanarak bu algoritma reimplemented. Uygulamanın tamamını here bulabilirsiniz. Bu saf bir PIL uygulamasıdır ve başka bağımlılıkları yoktur. İşlev kodunu kopyalayabilir ve kullanabilirsiniz. İşte Gimp kullanarak bir örnek:

alt text

alt text için Sen renk olarak siyah kullanılarak görüntü üzerinde color_to_alpha fonksiyonunu uygulayabilirsiniz. Ardından, değiştirmeyi yapmak için resmi farklı bir arka plan rengine yapıştırın. Bu arada

bu uygulama PIL ImageMath modülünü kullanır. Getdata'yı kullanarak piksellere erişmekten çok daha verimlidir.

DÜZENLEME:

from PIL import Image, ImageMath 

def difference1(source, color): 
    """When source is bigger than color""" 
    return (source - color)/(255.0 - color) 

def difference2(source, color): 
    """When color is bigger than source""" 
    return (color - source)/color 


def color_to_alpha(image, color=None): 
    image = image.convert('RGBA') 
    width, height = image.size 

    color = map(float, color) 
    img_bands = [band.convert("F") for band in image.split()] 

    # Find the maximum difference rate between source and color. I had to use two 
    # difference functions because ImageMath.eval only evaluates the expression 
    # once. 
    alpha = ImageMath.eval(
     """float(
      max(
       max(
        max(
         difference1(red_band, cred_band), 
         difference1(green_band, cgreen_band) 
        ), 
        difference1(blue_band, cblue_band) 
       ), 
       max(
        max(
         difference2(red_band, cred_band), 
         difference2(green_band, cgreen_band) 
        ), 
        difference2(blue_band, cblue_band) 
       ) 
      ) 
     )""", 
     difference1=difference1, 
     difference2=difference2, 
     red_band = img_bands[0], 
     green_band = img_bands[1], 
     blue_band = img_bands[2], 
     cred_band = color[0], 
     cgreen_band = color[1], 
     cblue_band = color[2] 
    ) 

    # Calculate the new image colors after the removal of the selected color 
    new_bands = [ 
     ImageMath.eval(
      "convert((image - color)/alpha + color, 'L')", 
      image = img_bands[i], 
      color = color[i], 
      alpha = alpha 
     ) 
     for i in xrange(3) 
    ] 

    # Add the new alpha band 
    new_bands.append(ImageMath.eval(
     "convert(alpha_band * alpha, 'L')", 
     alpha = alpha, 
     alpha_band = img_bands[3] 
    )) 

    return Image.merge('RGBA', new_bands) 

image = color_to_alpha(image, (0, 0, 0, 255)) 
background = Image.new('RGB', image.size, (255, 255, 255)) 
background.paste(image.convert('RGB'), mask=image) 
+0

ama söylenmesi böyle hiçbir modül adlı çekirdek ve işler Bu sadece bir karmaşaydı. Muhtemelen bir aptalım ama işe yaramadı. Yine de teşekkürler, cevabın, başkalarına yardım edeceğinden eminim. – Cookies

+0

Tüm dosyayı çalıştırmayı denememelisiniz. Sadece color_to_alpha işlevinin kendisini kopyalayın. Her neyse, senin için çalışan bir çözüm bulmana sevindim. Daha verimli bir çözüme ihtiyacınız varsa, nereye bakacağınızı biliyorsunuz;) –

+0

Yaptım ve ilk önce 'OPTIONS' küresel isminin tanımlanmadığını söyledi, bu yüzden o kısmı kopyaladım ve sonra _t tanımlanmadığını söyledi, ama sahip olmadığım bir modül. Dağınıklık demek istediğim buydu, çalışmayı denedim ama yapamadım, benim için işe yarayan aşağıda önerilen yöntem iyi değil, fakat eğer işlevin gerçekten de görüntüdeki tüm arka plan piksellerini çıkarabiliyor olsaydı. Hala tesseract karıştırmak bazı sol vardır. – Cookies

11

numpy ve PIL kullanarak:

Bu W genişlik ve H olan şekil (W,H,3), bir numpy diziye görüntü yükler burada tam kod yüksekliktir. Dizinin üçüncü ekseni, R,G,B numaralı kanalını temsil eder. orig_color yana


import Image 
import numpy as np 

orig_color = (255,255,255) 
replacement_color = (0,0,0) 
img = Image.open(filename).convert('RGB') 
data = np.array(img) 
data[(data == orig_color).all(axis = -1)] = replacement_color 
img2 = Image.fromarray(data, mode='RGB') 
img2.show() 

uzunluğu 3 bir demet ve data karşılaştırma data == orig_color gerçekleştirmek için şekil (W,H,3) bir dizi için şekil (W,H,3), numpy broadcasts orig_color sahiptir. Sonuç, (W,H,3) biçimindeki bir boole dizisinde.

(data == orig_color).all(axis = -1)data RGB renk original_color her yerde Doğru şekil (W,H) bir Boole dizidir.

8
#!/usr/bin/python 
from PIL import Image 
import sys 

img = Image.open(sys.argv[1]) 
img = img.convert("RGBA") 

pixdata = img.load() 

# Clean the background noise, if color != white, then set to black. 
# change with your color 
for y in xrange(img.size[1]): 
    for x in xrange(img.size[0]): 
     if pixdata[x, y] == (255, 255, 255, 255): 
      pixdata[x, y] = (0, 0, 0, 255) 
0

Bu benim kod parçası olan, sonuç istiyorum: Ben bu işe almaya çalıştı source

target

import os 
import struct 
from PIL import Image 
def changePNGColor(sourceFile, fromRgb, toRgb, deltaRank = 10): 
    fromRgb = fromRgb.replace('#', '') 
    toRgb = toRgb.replace('#', '') 

    fromColor = struct.unpack('BBB', bytes.fromhex(fromRgb)) 
    toColor = struct.unpack('BBB', bytes.fromhex(toRgb)) 

    img = Image.open(sourceFile) 
    img = img.convert("RGBA") 
    pixdata = img.load() 

    for x in range(0, img.size[0]): 
     for y in range(0, img.size[1]): 
      rdelta = pixdata[x, y][0] - fromColor[0] 
      gdelta = pixdata[x, y][0] - fromColor[0] 
      bdelta = pixdata[x, y][0] - fromColor[0] 
      if abs(rdelta) <= deltaRank and abs(gdelta) <= deltaRank and abs(bdelta) <= deltaRank: 
       pixdata[x, y] = (toColor[0] + rdelta, toColor[1] + gdelta, toColor[2] + bdelta, pixdata[x, y][3]) 

    img.save(os.path.dirname(sourceFile) + os.sep + "changeColor" + os.path.splitext(sourceFile)[1]) 

if __name__ == '__main__': 
    changePNGColor("./ok_1.png", "#000000", "#ff0000") 
İlgili konular