web-dev-qa-db-ja.com

PILで暗い線でテキストの輪郭を描く方法はありますか?

PNG画像のセットにテキストを書き込むためにpython/PILを使用しています。必要なフォントを取得できましたが、テキストの輪郭を黒で示したいと思います。

これは私が持っているものです:ご覧のとおり、背景が白の場合は読みにくいです。

enter image description here

これが目標です:

enter image description here

PILでこれを達成する方法はありますか?そうでない場合は、他の提案を聞くことはできますが、PILを使用してpythonで大規模なプロジェクトをすでに開始しているため、約束はありません。

画像への描画を扱うコードのセクション:

for i in range(0,max_frame_int + 1):
    writeimg = Image.open("frameinstance" + str(i) + ".png")
    newimg = Image.new("RGB", writeimg.size)
    newimg.paste(writeimg)
    width_image = newimg.size[0]
    height_image = newimg.size[1]
    draw = ImageDraw.Draw(newimg)
    # font = ImageFont.truetype(<font-file>, <font-size>)
    for font_size in range(50, 0, -1):
        font = ImageFont.truetype("impact.ttf", font_size)
        if font.getsize(meme_text)[0] <= width_image:
            break
    else:
        print('no fonts fit!')

    # draw.text((x, y),"Sample Text",(r,g,b))
    draw.text((int(0.05*width_image), int(0.7*height_image)),meme_text,(255,255,255),font=font)
    newimg.save("newimg" + str(i) +".png")
13
user7389351

これを見ることができます PILを使用したテキストのアウトライン

11
jackotonye

したがって、これが、フレームカウンターに対して行う必要があるときにこの問題を処理した方法です。これをプッシュして厚みを調整し始めた場合は、足りない領域をカバーするためにさらにドローが必要になります。

from PIL import Image,ImageDraw,ImageFont
import os

#setting varibles
imgFile = "frame_0.jpg"
output = "frame_edit_0.jpg"
font = ImageFont.truetype("arial.ttf", 30)
text = "SEQ_00100_SHOT_0004_FR_0001"
textColor = 'white'
shadowColor = 'black'
outlineAmount = 3

#open image
img = Image.open(imgFile)
draw = ImageDraw.Draw(img)

#get the size of the image
imgWidth,imgHeight = img.size

#get text size
txtWidth, txtHeight = draw.textsize(text, font=font)

#get location to place text
x = imgWidth - txtWidth - 100
y = imgHeight - txtHeight - 100

#create outline text
for adj in range(outlineAmount):
    #move right
    draw.text((x-adj, y), text, font=font, fill=shadowColor)
    #move left
    draw.text((x+adj, y), text, font=font, fill=shadowColor)
    #move up
    draw.text((x, y+adj), text, font=font, fill=shadowColor)
    #move down
    draw.text((x, y-adj), text, font=font, fill=shadowColor)
    #diagnal left up
    draw.text((x-adj, y+adj), text, font=font, fill=shadowColor)
    #diagnal right up
    draw.text((x+adj, y+adj), text, font=font, fill=shadowColor)
    #diagnal left down
    draw.text((x-adj, y-adj), text, font=font, fill=shadowColor)
    #diagnal right down
    draw.text((x+adj, y-adj), text, font=font, fill=shadowColor)

#create normal text on image
draw.text((x,y), text, font=font, fill=textColor)

img.save(output)
print 'Finished'
os.startfile(output)
6
Mark C
import Image, ImageFont, ImageDraw

import win32api, os

x, y = 10, 10

fname1 = "c:/test.jpg"
im = Image.open(fname1)
pointsize = 30
fillcolor = "red"
shadowcolor = "yellow"

text = "hi there"

font = win32api.GetWindowsDirectory() + "\\Fonts\\ARIALBD.TTF"
draw = ImageDraw.Draw(im)
font = ImageFont.truetype(font, pointsize)

# thin border
draw.text((x-1, y), text, font=font, fill=shadowcolor)
draw.text((x+1, y), text, font=font, fill=shadowcolor)
draw.text((x, y-1), text, font=font, fill=shadowcolor)
draw.text((x, y+1), text, font=font, fill=shadowcolor)

# thicker border
draw.text((x-1, y-1), text, font=font, fill=shadowcolor)
draw.text((x+1, y-1), text, font=font, fill=shadowcolor)
draw.text((x-1, y+1), text, font=font, fill=shadowcolor)
draw.text((x+1, y+1), text, font=font, fill=shadowcolor)

# now draw the text over it
draw.text((x, y), text, font=font, fill=fillcolor)

fname2 = "c:/test2.jpg"
im.save(fname2)

os.startfile(fname2)
0
DaWe

この回答は他の回答に基づいていますが、tkinterの.create_text ((x1, y1), ...)関数を使用しています。さらに、シャドウ効果を回避しながら、必要に応じて大きなアウトラインを実現することに重点を置いています。

shadow font.png

これがクローズアップです:

shadow font closeup2.png

主な機能は次のとおりです。

def create_text((x1, y1), **kwargs):
#    mycanvas.create_text((X1, Y1 + PanelHgt/Scale), text=str(Mon[MonN]) + \
#                             "  [" + str(Mon[MonW]) + " x " + \
#                             str(Mon[MonH]) +"]", \
#                            fill="white", shawdowfill="black", thick=0, \
#                            anchor="nw", font=(None, MonFont))
    if 'thick' in kwargs:
        thick = kwargs.pop('thick')
        if thick > 5 : thick = 0
    else :
        thick = 0

    if 'shadowfill' in kwargs:
        shadowfill = kwargs.pop('shadowfill')
    else:
        mycanvas.create_text((x1, y1), **kwargs)
        return

    if 'fill' in kwargs:
        fill = kwargs.pop('fill')
    else:
        fill = "black"

    x = x1 + 1 + thick
    y = y1 + 1 + thick
    if thick>1: thickless=thick-1 
    else: thickless=1
    while thickless > 0:
        mycanvas.create_text((x-thickless, y+thick), fill=shadowfill, **kwargs)
        mycanvas.create_text((x+thickless, y+thick), fill=shadowfill, **kwargs)
        mycanvas.create_text((x-thick, y-thickless), fill=shadowfill, **kwargs)
        mycanvas.create_text((x+thick, y+thickless), fill=shadowfill, **kwargs)
        thickless-=1
        thick-=1
    mycanvas.create_text((x, y), fill=fill, **kwargs)

関数を呼び出すためのサンプルコードは次のとおりです。

    InvertColor="white"
    ShadowColor="black"
    String=str(Win[WinN][0:30]) + "\n " \
           + str(Win[WinW]) + " x " + str(Win[WinH])
    # if top appliciton indicadtor pannel special formtting
    if ( Win[WinH] == PanelHgt ) : 
        color="light grey"
        InvertColor="black"
        String=Win[WinN]
        mycanvas.create_rectangle(X1, Y1, X2, Y2, fill=color)
        mycanvas.create_text((CentX, CentY), text=String, fill=InvertColor, \
                              font=(None, 11))
    else :
        color=Colors[j]
        j+=1
        if j==ColorCnt : j=0
        create_rectangle(X1, Y1, X2, Y2, fill=color, alpha=.6)
        create_text((CentX, CentY), text=String, fill=InvertColor, \
                     shadowfill=ShadowColor, thick=4, \
                     font=(None, 11))

重要な行は次のとおりです。

shadowfill=ShadowColor, thick=4
  • thickを省略すると、デフォルトで0これは薄い影であり、ほとんどの状況でおそらく最適です。
  • サニティチェック購入の最大シャドウ厚は5に設定されており、次の行を変更するだけです。if thick > 5 : thick = 0
  • shadowfillを省略すると、影はまったく描画されません。

コードが理解できない場合は、コメントで質問することを躊躇しないでください。

OTOHこれは私の最初のpythonプロジェクト(まだWIP)なので、建設的な批判は大歓迎です!

0