【问题标题】:Is there way to invert only specific pixels with Pillow?有没有办法用 Pillow 只反转特定的像素?
【发布时间】:2020-01-02 02:16:51
【问题描述】:

我正在制作一个程序,您可以在其中选择图像和颜色,它只会反转与该颜色匹配的像素。我一直在浏览 stackoverflow 和 reddit 以寻求解决方案,但到目前为止还没有运气。

我首先尝试做这样的事情:

img = Image.open('past.png')
pixels = img.load()
for i in goodpixels:
    ImageOps.invert(pixels[i])

AttributeError: 'tuple' 对象没有属性 'mode'

不走运,因为 ImageOps.invert 只反转完整图像。接下来我尝试使用 ImageOps.polarize 但意识到我不能使用它,因为它需要灰度阈值而不是 rgb 值。

img = Image.open('past.png')
pixels = img.load()
for i in goodpixels:
    ImageOps.solarize(img, threshold=pixels[i])

TypeError: 'int' 和 'tuple' 的实例之间不支持'

这是我的问题,我不知道这是否可能。如果工作量太大,我可能会放弃这个项目,因为我只是让自己忙起来,这不是为了分数/工作。

更多代码:

def checkpixels():
    img = Image.open('past.png')
    height, width = img.size
    img = img.convert('RGB')
    targetcolor = input('What color do you want to search for, you can use RGB format or common names like \'red\', \'black\', e.t.c. Leave this blank to invert all pixels. ')
    print('Processing image. This could take several minutes.')
    isrgb = re.match(r'\d+, \d+, \d+|\(\d+, \d+, \d+\)', targetcolor)
    if type(isrgb) == re.Match:
        targetcolor = targetcolor.strip('()')
        targetcolor = targetcolor.split(', ')
        targetcolor = tuple(map(int, targetcolor))
        print(str(targetcolor))
        for x in range(width):
            for y in range(height):
                color = img.getpixel((y-1, x-1))
                if color == targetcolor:
                    goodpixels.append((y-1, x-1))
    else:
        try:
            targetcolor = ImageColor.getcolor(targetcolor.lower(), 'RGB')
            print(targetcolor)
            for x in range(width):
                for y in range(height):
                    color = img.getpixel((y-1, x-1))
                    if color == targetcolor:
                        goodpixels.append((y-1, x-1))
        except:
            print('Not a valid color smh.')

    return goodpixels
goodpixels = []
goodpixels = checkpixels()

编辑:我想通了!感谢 Mark Setchell 令人难以置信的大脑!我最终使用 numpy 将图像和目标颜色转换为数组,制作图像的反转副本,并使用 numpy.where() 来决定是否切换像素。我还计划将目标颜色设为一个范围,这样选择的颜色就不必那么具体。总而言之,我的代码如下所示:

goodpixels = []
targetcolor = inputcolor()
img = Image.open('past.png')
invertimage = img.copy().convert('RGB')
invertimage = ImageOps.invert(invertimage)
invertimage.save('invert.png')
pastarray = np.array(img)
targetcolorarray = np.array(targetcolor)
pixels = img.load()
inverse = np.array(invertimage)
result = np.where((pastarray==targetcolorarray).all(axis=-1)[...,None], inverse, pastarray)
Image.fromarray(result.astype(np.uint8)).save('result.png')

当然,inputcolor() 是一个离屏函数,它只是决定输入是颜色名称还是 rgb 值。在这个例子中我也使用了import numpy as np

我遇到的一个问题是我原来的 .where 方法看起来像这样:

result = np.where((pastarray==[0, 0, 0]).all(axis=-1)[...,None], inverse, pastarray)

这引发了错误:AttributeError: 'bool' object has no attribute 'all' 事实证明,我所要做的就是将我的颜色转换为数组!

【问题讨论】:

  • Numpy 只需要几行代码,这是您应该对图像使用的,因为它有很多算法并且速度非常快。因此,将您的 PIL Image 转换为 Numpy 数组制作整个内容的副本并将其全部反转。然后使用np.where()来选择,对于每个像素位置是使用原始图像还是倒置图像。
  • @MarkSetchell 谢谢!我会研究 numpy。
  • 看起来应该差不多...stackoverflow.com/a/59322460/2836621
  • 抱歉,我没有靠近电脑,无法提供更详细的帮助。如果你知道如何去做,你可以把它写下来作为其他人使用的答案,并接受它是正确的,并获得积分。祝你好运!如果遇到困难就回来 - 问题是免费的????
  • 继续努力!如果您有一些新代码,请点击您的问题下方的edit 并添加!

标签: python python-3.x python-imaging-library


【解决方案1】:

许多库允许您将图像作为 numpy 数组导入 Python。 PILopencv2 是用于处理图像的文档库:

pip install opencv2

示例 numpy.where() 选择,满足一组标准,在这种情况下反转所有低于THRESHOLD 的像素值:

import cv2
import numpy as np
import matplotlib.pyplot as plt

# cut off thereshold
THRESHOLD = 230

pixel_data = cv2.imread('filename.png')
pixel_data = np.where(pixel_data < THRESHOLD, 1/pixel_data, pixel_data)

# display the edited image using matplotlib
plt.imshow(pixel_data)

numpy.where() 函数将条件应用于您的 numpy 数组。更多详情请访问:numpy official documentation

【讨论】:

    猜你喜欢
    • 2011-11-28
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    • 2015-12-22
    • 2016-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多