بيل أفضل طريقة لاستبدال اللون ؟
-
06-07-2019 - |
سؤال
أنا أحاول إزالة لون معين من الصورة ومع ذلك فإنه لا يعمل كما تمنيت.حاولت أن تفعل الشيء نفسه كما رأينا هنا باستخدام بيل لجعل كل بكسل بيضاء شفافة ؟ ومع ذلك فإن جودة الصورة قليلا الضياع لذلك يترك قليلا شبح الغريب بكسل الملونة حول أين ما تمت إزالته.حاولت أن تفعل شيئا مثل تغيير بكسل إذا كان كل ثلاث قيم هي أقل من 100 ولكن لأن الصورة كانت رديئة الجودة البيكسلات المحيطة لم تكن حتى الأسود.
لا أحد يعرف من طريقة أفضل مع بيل في بيثون لاستبدال لون و أي شيء المحيطة به ؟ وربما هذا هو فقط متأكد النار طريقة يمكن إزالة الكائنات تماما ومع ذلك لا أستطيع التفكير في وسيلة للقيام بذلك.
صورة خلفية بيضاء و نص الأسود.دعنا نقول فقط أريد أن إزالة النص تماما من الصورة دون ترك أي القطع الأثرية خلف.
حقا نقدر مساعدة شخص ما!شكرا
المحلول
وستحتاج لتمثيل الصورة كما مجموعة 2 الأبعاد. وهذا يعني إما وضع قائمة من قوائم بكسل، أو عرض مجموعة 1 الأبعاد باعتبارها واحدة 2D مع بعض الرياضيات ذكية. ثم، لكل بكسل هي المستهدفة، ستحتاج إلى العثور على كل بكسل المحيطة بها. هل يمكن أن تفعل هذا مع مولد الثعبان على النحو التالي:
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
نصائح أخرى
أفضل طريقة للقيام بذلك هو استخدام "لون ألفا" الخوارزمية المستخدمة في Gimp لاستبدال اللون.أنه سوف يعمل تماما في حالتك.أنا ل reimplemented هذه الخوارزمية باستخدام بيل مفتوحة المصدر بيثون صورة المعالج phatch.يمكنك العثور على التنفيذ الكامل هنا.هذا محض بيل تنفيذ وأنه لا يجب الأخرى الإعتماد.يمكنك نسخ رمز وظيفة واستخدامها.هنا عينة باستخدام Gimp:
إلى
يمكنك تطبيق color_to_alpha
الدالة على الصورة باستخدام أسود اللون.ثم لصق الصورة على لون خلفية مختلفة للقيام استبدال.
بالمناسبة, هذا التطبيق يستخدم ImageMath وحدة في PIL.هو أكثر كفاءة من الوصول إلى بكسل باستخدام 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)
وعن طريق نمباي وPIL:
وهذا تحميل الصورة إلى مجموعة نمباي الشكل (W,H,3)
، حيث 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
هو الصفوف (tuple) بطول 3، وdata
له
تشكيل (W,H,3)
، نمباي
البث
orig_color
إلى مجموعة من شكل (W,H,3)
لأداء data ==
orig_color
المقارنة. النتيجة في مجموعة منطقية من شكل (W,H,3)
.
و(data == orig_color).all(axis = -1)
هو مجموعة منطقية من شكل (W,H)
التي
غير صحيح أينما لون RGB في data
هو original_color
.
#!/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)
إذا بكسل هي لا يسهل التعرف عليها منها مثلا تقول (ص <100 و ز <100 و ب <100) أيضا لا يتطابق بشكل صحيح المنطقة السوداء، فهذا يعني أنك لديك الكثير من الضوضاء.
وأفضل طريقة ستكون للتعرف على المنطقة وملء مع اللون الذي تريده، يمكنك تحديد المنطقة يدويا أو قد تكون من خلال الكشف عن حافة مثلا http://bitecode.co.uk/2008/07/edge -detection في والثعبان /
وأو أكثر تطورا النهج من شأنه أن يكون لاستخدام مكتبة مثل مكتبة برمجية مفتوحة للرؤية الحاسوبية ( http://opencv.willowgarage.com/ ويكي / ) لتحديد الكائنات.
وهذا هو جزء من قانون بلدي، فإن النتيجة مثل:
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")