문제

내 이미지에서 특정 색상을 제거하려고하지만 기대했던 것만 큼 작동하지 않습니다. 나는 여기서 본 것과 똑같은 일을하려고 노력했다 PIL을 사용하여 모든 흰색 픽셀을 투명하게 만들 수 있습니까? 그러나 이미지 품질은 약간 손실이므로 제거 된 곳 주위에 홀수 컬러 픽셀의 약간의 유령이 남습니다. 세 값이 모두 100 미만이면 Change Pixel과 같은 작업을 시도했지만 이미지가 열악했기 때문에 주변 픽셀도 검은 색이 아니 었습니다.

색상과 주변을 대체하기 위해 Python의 Pil과 더 나은 방법을 알고 있습니까? 이것은 아마도 물체를 완전히 제거 할 수있는 유일한 불의 방식 일 것입니다. 그러나 나는 이것을 할 방법을 생각할 수 없습니다.

그림에는 흰색 배경과 텍스트가 검은 색입니다. 인공물을 남기지 않고 이미지에서 텍스트를 완전히 제거하고 싶다고 가정 해 봅시다.

누군가의 도움에 정말 감사합니다! 감사

도움이 되었습니까?

해결책

이미지를 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

다른 팁

가장 좋은 방법은 사용 된 "색상으로 알파"알고리즘을 사용하는 것입니다. 색상을 교체합니다. 그것은 당신의 경우에 완벽하게 작동합니다. 오픈 소스 파이썬 사진 프로세서를 위해 PIL을 사용 하여이 알고리즘을 다시 구현했습니다. phatch. 전체 구현을 찾을 수 있습니다 여기. 이것은 순수한 PIL 구현이며 다른 의존성이 없습니다. 함수 코드를 복사하여 사용할 수 있습니다. 다음은 김프를 사용하는 샘플입니다.

alt text 에게 alt text

당신은 신청할 수 있습니다 color_to_alpha 검은 색을 색상으로 사용하여 이미지에서 기능합니다. 그런 다음 다른 배경색에 이미지를 붙여 넣어 교체를 수행하십시오.

그건 그렇고,이 구현은 PIL에서 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)

Numpy와 Pil 사용 :

이것은 이미지를 numpy 모양의 배열로로드합니다. (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 길이 3의 튜플입니다 data 모양이 있습니다 (W,H,3), Numpy방송 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)

픽셀을 쉽게 식별 할 수없는 경우 (R <100 및 G <100 및 B <100)도 검은 색 영역과 일치하지 않으므로 소음이 많습니다.

가장 좋은 방법은 영역을 식별하고 원하는 색상으로 채우는 것입니다. 영역을 수동으로 식별하거나 가장자리 감지에 의해 가능할 수 있습니다. http://bitecode.co.uk/2008/07/edge-detection-in-python/

또는 더 정교한 접근 방식은 OpenCV와 같은 라이브러리를 사용하는 것입니다.http://opencv.willowgarage.com/wiki/) 개체를 식별합니다.

이것은 내 코드의 일부이며 결과는 다음과 같습니다.원천

표적

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")
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top