2009-10-24 13 views
14

मैं अपनी छवि से एक निश्चित रंग को हटाने की कोशिश कर रहा हूं, हालांकि यह काम नहीं कर रहा है और साथ ही मैं आशा करता हूं। मैंने Using PIL to make all white pixels transparent? पर देखी गई वही काम करने की कोशिश की, हालांकि छवि की गुणवत्ता थोड़ा हानिकारक है, इसलिए यह हटाए गए स्थान के आस-पास के रंगीन पिक्सेल के छोटे भूत को छोड़ देता है। मैंने कुछ पिक्सल बदलने की कोशिश की, यदि सभी तीन मान 100 से कम हैं लेकिन क्योंकि छवि खराब गुणवत्ता थी, आसपास के पिक्सेल काले भी नहीं थे।पीआईएल रंग बदलने के लिए सबसे अच्छा तरीका?

क्या किसी को रंग और उसके आस-पास के किसी भी चीज़ को बदलने के लिए पाइथन में पीआईएल के साथ बेहतर तरीका पता है? यह शायद एकमात्र निश्चित अग्नि तरीका है जिसे मैं पूरी तरह से वस्तुओं को हटाने के बारे में सोच सकता हूं, हालांकि मैं ऐसा करने का तरीका नहीं सोच सकता।

तस्वीर में एक सफेद पृष्ठभूमि और पाठ है जो काला है। आइए बस कहना है कि मैं बिना किसी कलाकृतियों को छोड़े बिना पूरी तरह से छवि से पाठ को हटाना चाहता हूं।

वास्तव में किसी की मदद की सराहना करेंगे! धन्यवाद

उत्तर

5

आपको छवि को 2-आयामी सरणी के रूप में प्रस्तुत करने की आवश्यकता होगी। इसका मतलब है या तो पिक्सल की सूचियों की सूची बनाना, या 1-आयामी सरणी को कुछ चालाक गणित के साथ 2 डी के रूप में देखना। फिर, लक्षित प्रत्येक पिक्सेल के लिए, आपको सभी आस-पास के पिक्सल ढूंढना होगा। आप इस तरह एक अजगर जनरेटर के साथ ऐसा कर सकता है:

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 

तो, तो आप इसे इस का प्रयोग करेंगे:

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

पिक्सल आसानी से पहचाने जाने आप जैसे कहते हैं कि नहीं कर रहे हैं (आर < 100 और जी < 100 और बी < 100) भी काले क्षेत्र से सही ढंग से मेल नहीं खाता है, इसका मतलब है कि आपके पास बहुत शोर है।

सबसे अच्छा तरीका एक क्षेत्र की पहचान करना होगा और इसे इच्छित रंग से भरना होगा, आप क्षेत्र को मैन्युअल रूप से पहचान सकते हैं या किनारे का पता लगा सकते हैं उदा। http://bitecode.co.uk/2008/07/edge-detection-in-python/

या ऑब्जेक्ट की पहचान करने के लिए ओपनसीवी (http://opencv.willowgarage.com/wiki/) जैसी लाइब्रेरी का उपयोग करने के लिए अधिक परिष्कृत दृष्टिकोण होगा।

22

ऐसा करने का सबसे अच्छा तरीका रंग को बदलने के लिए Gimp में "रंग से अल्फा" एल्गोरिदम का उपयोग करना है। यह आपके मामले में पूरी तरह से काम करेगा। मैंने ओएल सोर्स पायथन फोटो प्रोसेसर phatch के लिए पीआईएल का उपयोग करके इस एल्गोरिदम को फिर से कार्यान्वित किया। आप पूर्ण कार्यान्वयन here पा सकते हैं। यह एक शुद्ध पीआईएल कार्यान्वयन है और इसमें अन्य निर्भरता नहीं है। आप फ़ंक्शन कोड कॉपी कर सकते हैं और इसका उपयोग कर सकते हैं। आप रंग के रूप में काले का उपयोग कर छवि पर color_to_alpha समारोह लागू कर सकते हैं

alt textalt text

लिए: यहाँ Gimp का उपयोग कर एक नमूना है। फिर प्रतिस्थापन करने के लिए छवि को एक अलग पृष्ठभूमि रंग पर पेस्ट करें।

वैसे, यह कार्यान्वयन पीआईएल में ImageMath मॉड्यूल का उपयोग करता है। यह Getdata का उपयोग कर पिक्सल तक पहुंचने से कहीं अधिक कुशल है।

संपादित करें:

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

मैं इस काम करने के लिए प्राप्त करने की कोशिश, लेकिन यह कहा नहीं मॉड्यूल नामित कोर और उस तरह बातें , यह सिर्फ एक गड़बड़ था। मैं शायद बेवकूफ हूं लेकिन मैं इसे काम करने के लिए नहीं मिला। धन्यवाद वैसे भी मुझे यकीन है कि आपका जवाब किसी और की मदद करेगा। – Cookies

+0

आपको पूरी फाइल चलाने की कोशिश नहीं करनी चाहिए। बस color_to_alpha फ़ंक्शन को कॉपी करें। वैसे भी, मुझे खुशी है कि आपको एक समाधान मिला जो आपके लिए काम करता है। यदि आपको अधिक कुशल समाधान की आवश्यकता है, तो आप जानते हैं कि कहां देखना है;) –

+0

मैंने किया, और पहले यह कहा गया कि वैश्विक नाम 'विकल्प' परिभाषित नहीं किया गया है, इसलिए मैंने उस भाग को कॉपी किया और फिर कहा कि यह परिभाषित नहीं है, लेकिन यह था एक मॉड्यूल मेरे पास नहीं था। मैं गड़बड़ी से यही मतलब था, मैंने इसे काम करने की कोशिश की लेकिन वह नहीं कर सका, नीचे दी गई विधि जो मेरे लिए काम करती है ठीक है, लेकिन अगर आपका काम वास्तव में छवि में सभी पृष्ठभूमि पिक्सेल निकाल सकता है जो बहुत अच्छा होगा। अभी भी कुछ बाएं हैं जो टेसरेक्ट को भ्रमित करते हैं। – Cookies

11

numpy और जनहित याचिका का उपयोग करना::

यह आकार (W,H,3), की एक numpy सरणी जहां W चौड़ाई और H है में छवि लोड यहाँ पूर्ण कोड है ऊंचाई है सरणी का तीसरा धुरी 3 रंग चैनल, R,G,B का प्रतिनिधित्व करता है।

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() 

orig_color के बाद से लंबाई 3 के एक टपल है, और data आकार (W,H,3), NumPy broadcasts orig_color आकार (W,H,3) की एक सरणी की तुलना data == orig_color पालन किया है। परिणाम (W,H,3) आकार के एक बुलियन सरणी में परिणाम।

(data == orig_color).all(axis = -1) आकार (W,H) की एक बूलियन सरणी जो यह सच है जहाँ भी data में आरजीबी रंग original_color है।

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

यह मेरा कोड का हिस्सा है, परिणाम चाहते हैं: 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") 
संबंधित मुद्दे