我正在尝试使用Pillow(python-imaging-library)Python库,以便在.png图像周围创建轮廓/笔触/边框(具有选择的任何颜色和宽度)。您可以在此处看到原始图像和我想要的结果(通过电话应用创建):https://i.stack.imgur.com/4x4qh.png
您可以在此处下载原始图像的png文件:https://pixabay.com/illustrations/brain-character-organ-smart-eyes-1773885/
我已经以中等尺寸(1280x1138)做到了,但最好以最小尺寸(640x569)来做。
我试图用两种方法解决问题。
方法一
[第一种方法是创建brain.png图像的全黑图像,将其放大,然后将原始的彩色脑图像粘贴在其顶部。这是我的代码:
brain_black = Image.open("brain.png") #load brain image
width = brain_black.width #in order not to type a lot
height = brain_black.height #in order not to type a lot
rectangle = Image.new("RGBA", (width, height), "black") #creating a black rectangle in the size of the brain image
brain_black.paste(rectangle, mask=brain_black) #pasting on the brain image the black rectangle, and masking it with the brain picture
#now brain_black is the brain.png image, but all its pixels are black. Let's continue:
brain_black = brain_black.resize((width+180, height+180)) #resizing the brain_black by some factor
brain_regular = Image.open("brain.png") #load the brain image in order to paste later on
brain_black.paste(brain_regular,(90,90), mask=brain_regular) #paste the regular (colored) brain on top of the enlarged black brain (in x=90, y=90, the middle of the black brain)
brain_black.save("brain_method_resize.png") #saving the image
如上图所示,此方法无效。它可能适用于简单的几何形状,但不适用于像这样的复杂形状。
方法二
第二种方法是将脑图像像素数据加载到二维数组中,然后遍历所有像素。检查每个像素的颜色,并检查每个不透明的像素的颜色(在rgbA形式中,A(或Alpha)不为0),在像素的上,下,右,左,主对角线下方绘制一个黑色像素,主对角线向上,辅助对角线(/)向下,辅助对角线(/)向上。然后在上方的第二个像素,下方的第二个像素等等中绘制一个像素,这是通过“ for循环”完成的,其中重复次数是所需的笔划宽度(在此示例中为30)。这是我的代码:
brain=Image.open("brain.png") #load brain image
background=Image.new("RGBA", (brain.size[0]+400, brain.size[1]+400), (0, 0, 0, 0)) #crate a background transparent image to create the stroke in it
background.paste(brain, (200,200), brain) #paste the brain image in the middle of the background
pixelsBrain = brain.load() #load the pixels array of brain
pixelsBack=background.load() #load the pixels array of background
for i in range(brain.size[0]):
for j in range(brain.size[1]):
r, c = i+200, j+200 #height and width offset
if(pixelsBrain[i,j][3]!=0): #checking if the opacity is not 0, if the alpha is not 0.
for k in range(30): #the loop
pixelsBack[r, c + k] = (0, 0, 0, 255)
pixelsBack[r, c - k] = (0, 0, 0, 255)
pixelsBack[r + k, c] = (0, 0, 0, 255)
pixelsBack[r - k, c] = (0, 0, 0, 255)
pixelsBack[r + k, c + k] = (0, 0, 0, 255)
pixelsBack[r - k, c - k] = (0, 0, 0, 255)
pixelsBack[r + k, c - k] =(0, 0, 0, 255)
pixelsBack[r - k, c + k] = (0, 0, 0, 255)
background.paste(brain, (200,200), brain) #pasting the colored brain onto the background, because the loop "destroyed" the picture.
background.save("brain_method_loop.png")
此方法确实有效,但是非常耗时(仅一张照片和30像素笔画需要30秒的时间)。我想对很多图片都这样做,所以这种方法对我不好。
是否有使用Python Pillow库更轻松,更好的方法来达到想要的结果。我该怎么做?而且,如何固定循环代码(我了解有关Numpy和OpenCV的一些知识,对于此目的而言更好?)
[我知道,如果电话应用程序可以在几毫秒内完成,python也可以,但是我找不到任何方法。
谢谢。
由于我还有其他承诺,目前我无法为您提供经过全面测试的Python解决方案,但是我可以肯定地向您展示如何在几毫秒内完成该操作,并为您提供一些指导。
我刚刚在命令行上使用了ImageMagick。它可以在Linux和macOS(使用brew install imagemagick
)和Windows上运行。因此,我提取了alpha / transparency通道并丢弃了所有颜色信息。然后,使用形态学“ edge out”操作在alpha通道中的形状边缘周围生成粗线。然后,我反转白色边缘,使它们变为黑色,并使所有白色像素透明。然后叠加在原始图像的顶部。
这是完整的命令:
magick baby.png \( +clone -alpha extract -morphology edgeout octagon:9 -threshold 10% -negate -transparent white \) -flatten result.png
这样就基本上打开了图像,将括号内的alpha层的克隆副本弄乱了,然后将产生的黑色轮廓变平回到原始图像并保存。让我们一次执行一个步骤:
将alpha层提取为alpha.png
:
magick baby.png -alpha extract alpha.png
现在加宽边缘,反转并使所有非黑色的东西变为透明并另存为overlay.png
:
magick alpha.png -morphology edgeout octagon:9 -threshold 10% -negate -transparent white overlay.png
这是最终结果,对于较粗的行,将octagon:9
更改为octagon:19
:
因此,使用PIL ...,您需要打开图像并转换为RGBA
,然后分割通道。您无需触摸RGB,只需触摸A通道即可。
im = Image.open('baby.png').convert('RGBA')
R, G, B, A = im.split()
这里需要一些形态-参见here。
将原始RGB通道与新的A通道合并并保存:
result = Image.merge((R,G,B,modifiedA))
result.save('result.png')