繁体   English   中英

将函数应用于图像的每个像素的最快方法?

[英]Fastest way to apply a function to each pixel of image?

不到一周前开始学习python。 也许我的问题真的很奇怪,但我今天花了大约六个小时试图找到答案,但失败了。

我已经找到了将函数分别应用于图像(R、G 和 B)中 CHANNEL 中的每个点的多种解决方案,但我需要同时分析所有三个通道上的每个像素。 所以这个那个不合适,或者我严重不明白一些事情。

我有一个 RGB .png 图像(实际上,它是用 MSS 制作的屏幕截图,所以也许直接使用它比保存/加载更快?但我不知道如何做到这一点......)。 图像由不同亮度的彩色像素和灰色像素组成。

我需要将此图像过滤为“模式 1”图像,其中每个像素都根据以下规则设置为0 (纯色|黑色)或1 (空白|白色):如果源像素(所有像素都是 [R,G, B] ) 被着色(R != G 或 G != B 或 B != R),结果像素为1 (空白|白色),或者如果它没有着色但比 #eee 亮,则为1 (空白|白色) )。 仅当源像素未着色(R == G == B)并且比 #eee 更暗时,生成的像素为0 (纯色|黑色)。

仅通过阈值更改模式/过滤是行不通的,因为彩色像素可能非常暗。 实际上比灰色的更暗。

也许有一些库/函数已经可以满足我的需要,但我非常失败地找不到一个。

所以它是一个函数:

#accepts [R,G,B] or (R,G,B)
def process_pixel(pixel) :
  if (1 == len(set(pixel)) and (238 > pixel[0]) :
    return 0
  else 
    return 1

现在我需要将这个函数(好吧,也许是其他一些更好的函数,我只是无法用我非常有限的 python 知识来成像——但是)到图像的每个像素,并以此创建一个新图像。

今天我读了关于枕头/PIL 库并决定使用它(我也读过 openCV 库,但这是处理计算机视觉的某种怪物,这让我有点发抖......很多)脚本看起来像这样:

from PIL import Image

in_image = Image.open('guineapig.png')

in_pixels = in_image.getdata()

out_pixels = []
for pixel in in_pixels :
  out_pixels.append(process_pixel(pixel))

out_image = Image.new('1', (*in_image.size, ), (1))
out_image.putdata(out_pixels)
out_image.save('guineapig_1.png')

现在这有效,但有点慢。 至少可以说。 由于我使用 python 不到一周,这是我的第四个脚本,我什至不明白哪个部分最慢,以及如何处理它......

基本上,您只需要处理输入图像的 HSV 版本的饱和度和亮度通道,以便满足您的后一个条件,将深灰色阴影像素设置为 0(即那些饱和度 = 0 且亮度 <238 的像素)并使剩余像素 1. 这可以很容易地使用 OpenCV(或 Python Wand)完成。

输入:

在此处输入图片说明

import cv2
import numpy as np

# if source pixel not colored (R == G == B) i.e. saturation=0 
# and it's darker than #eee i.e. brightness<238, 
# then resulting pixel is 0 (solid|black); 
# else 1 (solid|white)

# load image and get dimensions
img = cv2.imread("krolik.png")

# convert to hsv
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

# separate out saturation and brightness channels
sat = hsv[:,:,1]
bri = hsv[:,:,2]

# saturation=0 indicates not colored pixels and saturation>0 indicates colored pixels
# do inverse threshold saturation image at 0 
# result is colored pixels will become 0 and those not-colored will become 1
sat_thresh = cv2.threshold(sat,0,255,cv2.THRESH_BINARY_INV)[1].astype("float32")/255

# inverse threshold brightness image at 238 (#eee)
# so pixels with brightness > 238 will become 0 and those less than 238 will become 1
bri_thresh = cv2.threshold(bri,238,255,cv2.THRESH_BINARY_INV)[1].astype("float32")/255

# multiply above two images to get dark not colored pixels as 1
dark_not_colored = sat_thresh*bri_thresh

# invert that result so that dark not colored pixels are 0 and others are 1
result = 1-dark_not_colored

# write result to disk
cv2.imwrite("krolik_processed.png", 255*result.astype("uint8"))

# display it
cv2.imshow("sat_thresh", sat_thresh)
cv2.imshow("bri_thresh", bri_thresh)
cv2.imshow("dark_not_colored", dark_not_colored)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()


结果:

在此处输入图片说明

添加:

这是在 Imagemagick(unix 语法)中完成的方法,它随大多数 Linux 系统一起提供,也可用于 Mac OSX 和 Windows。

convert krolik.png \
-colorspace HSV \
-separate -delete 0 \
\( -clone 0 -threshold 0 -negate \) \
\( -clone 1 -threshold 93.33% -negate \) \
-delete 0,1 \
-compose multiply -composite \
-negate \
krolick_processed_im.png


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM