GIMP具有方便的功能,允许您将任意颜色转换为Alpha通道。
基本上所有像素相对于它们所选颜色的距离变得透明。
我想用opencv复制这个功能。
我尝试迭代图像:
for x in range(rows):
for y in range(cols):
mask_img[y, x][3] = cv2.norm(img[y, x] - (255, 255, 255, 255))
但这非常昂贵,迭代所需的时间比将字段设置为0(6分钟与一小时)相比需要大约10倍
这似乎是一个python问题而不是算法问题。我在C ++中做过类似的事情,但在性能方面并没有那么糟糕。
有没有人有这方面的建议?
这是我尝试仅使用numpy
矩阵运算。
我的输入图像colortrans.png
看起来像这样:
我想使对角紫色部分(128, 0, 128)
透明,左右两侧有一些公差+/- (25, 0, 25)
,产生一些透明度渐变。
代码如下:
import cv2
import numpy as np
# Input image
input = cv2.imread('images/colortrans.png', cv2.IMREAD_COLOR)
# Convert to RGB with alpha channel
output = cv2.cvtColor(input, cv2.COLOR_BGR2RGBA)
# Color to make transparent
col = (128, 0, 128)
# Color tolerance
tol = (25, 0, 25)
# Temporary array (subtract color)
temp = np.subtract(input, col)
# Tolerance mask
mask = (np.abs(temp) <= tol)
mask = (mask[:, :, 0] & mask[:, :, 1] & mask[:, :, 2])
# Generate alpha channel
temp[temp < 0] = 0 # Remove negative values
alpha = (temp[:, :, 0] + temp[:, :, 1] + temp[:, :, 2]) / 3 # Generate mean gradient over all channels
alpha[mask] = alpha[mask] / np.max(alpha[mask]) * 255 # Gradual transparency within tolerance mask
alpha[~mask] = 255 # No transparency outside tolerance mask
# Set alpha channel in output
output[:, :, 3] = alpha
# Output images
cv2.imwrite('images/colortrans_alpha.png', alpha)
cv2.imwrite('images/colortrans_output.png', output)
得到的alpha通道colortrans_alpha.png
看起来像这样:
并且,最终输出图像colortrans_output.png
看起来像这样:
那是你想要实现的目标吗?
我做了一个项目,使用PIL
(python图像库)模块将所有接近白色的像素转换为透明像素。我不确定如何实现你的算法“相对于它们离选择的颜色有多远”,但我的代码看起来像:
from PIL import Image
planeIm = Image.open('InputImage.png')
planeIm = planeIm.convert('RGBA')
datas = planeIm.getdata()
newData = []
for item in datas:
if item[0] > 240 and item[1] > 240 and item[2] > 240:
newData.append((255, 255, 255, 0)) # transparent pixel
else:
newData.append(item) # unedited pixel
planeIm.putdata(newData)
planeIm.save('output.png', "PNG")
这是在1.605秒内为我拍摄的1920 X 1080图像,所以如果你将逻辑实现到这里,你会看到你想要的速度改进吗?
如果newData
被初始化而不是每次都被.append()
ed可能会更快!就像是:
planeIm = Image.open('EGGW spider.png')
planeIm = planeIm.convert('RGBA')
datas = planeIm.getdata()
newData = [(255, 255, 255, 0)] * len(datas)
for i in range(len(datas)):
if datas[i][0] > 240 and datas[i][1] > 240 and datas[i][2] > 240:
pass # we already have (255, 255, 255, 0) there
else:
newData[i] = datas[i]
planeIm.putdata(newData)
planeIm.save('output.png', "PNG")
虽然对我来说这第二种方法运行在2.067秒......
计算不同图像的线程示例如下所示:
from PIL import Image
from threading import Thread
from queue import Queue
import time
start = time.time()
q = Queue()
planeIm = Image.open('InputImage.png')
planeIm = planeIm.convert('RGBA')
datas = planeIm.getdata()
new_data = [0] * len(datas)
print('putting image into queue')
for count, item in enumerate(datas):
q.put((count, item))
def worker_function():
while True:
# print("Items in queue: {}".format(q.qsize()))
index, pixel = q.get()
if pixel[0] > 240 and pixel[1] > 240 and pixel[2] > 240:
out_pixel = (0, 0, 0, 0)
else:
out_pixel = pixel
new_data[index] = out_pixel
q.task_done()
print('starting workers')
worker_count = 100
for i in range(worker_count):
t = Thread(target=worker_function)
t.daemon = True
t.start()
print('main thread waiting')
q.join()
print('Queue has been joined')
planeIm.putdata(new_data)
planeIm.save('output.png', "PNG")
end = time.time()
elapsed = end - start
print('{:3.3} seconds elapsed'.format(elapsed))
对我来说现在需要58.1秒!一个可怕的速度差异!我认为这是:
new_data
列表。我去了pyvips。
此版本计算文件中每个RGB像素与目标颜色之间的毕达哥拉斯距离,然后通过按公差缩放该距离度量来生成alpha。
import sys
import pyvips
image = pyvips.Image.new_from_file(sys.argv[1], access='sequential')
# Color to make transparent
col = [128, 0, 128]
# Tolerance ... ie., how close to target before we become solid
tol = 25
# for each pixel, pythagorean distance from target colour
d = sum(((image - col) ** 2).bandsplit()) ** 0.5
# scale d so that distances > tol become 255
alpha = 255 * d / tol
# attach the alpha and save
image.bandjoin(alpha).write_to_file(sys.argv[2])
关于@ HansHirse的漂亮测试图像:
我可以像这样运行它:
$ ./mktrans.py ~/pics/colortrans.png x.png
要做:
为了测试速度,我尝试了一个1920x1080像素的jpg:
$ time ./mktrans.py ~/pics/horse1920x1080.jpg x.png
real 0m0.708s
user 0m1.020s
sys 0m0.029s
这款双核2015笔记本电脑的尺寸为0.7秒。