2017-04-25 71 views
0

グリッドをイメージにスーパーインポーズして、テキストの配置に使用できるようにしようとしています。私はグリッドを描画するためにPIL(Python)を使用しています。理想的には、私は画像に透けて見えるように、破線と合理的に透明な小さなグリッドラインを持っていました。Python PIL - 透明で破線?

私がしようとしていることの実際の例は以下のとおりです。

私の質問は、(提示のために簡略化し)、次の行を参照してください。

draw.line((10, 0, 10, imgHeight), fill = (180, 180, 255, 1)) 
draw.line((10, 0, 10, imgHeight), fill = (180, 180, 255, 200)) 

1)Iは、充填物の第四パラメータが0で完全に透明であり、かつ255が完全であると、線の透明度を制御理解不透明しかし、私は値と1と200の間の違いを検出することはできません。実際には、1を使用すると、それを見ることができると思ったら、その下のテキストが隠れてしまいます。

2)どうやってPILで破線を作ることができますか?私はどのように見ていない。出来ますか?

最後に、プログラミングとPythonには比較的新しいので、以下のMWEでより良い標準にするためのヒントがあれば、私は最も感謝しています。

注:下の例では、主要なグリッド線に赤い線を使用していますが、マイナーなグリッド線と同じ色にしたいと思います。マイナーグリッド線は透明で破線です。

import PIL 
from PIL import Image, ImageFont, ImageDraw 

grid = 'on' 
minor = 5 
major = 50 

font = ImageFont.truetype('arial.ttf', 10) 
textColor = (38, 23, 255) 

img = Image.open('2013MCS7.jpg') 
draw = ImageDraw.Draw(img) 


def gridlines(img, gridWidth, color, lineWidth=1, direction='b', label='n', labelRepeat=None, LabelFont='arial', labelFontSize=10): 
    ''' 
    Draws gridlines on an image. 
     img : the image to be modified 
     gridwith : (int > 0) : size of gridlines in pixels 
     color : tuple of length 3 or 4 (4th argument controls transparency) : color of gridlines and labels 
     lineWidth : (int > 0) : width of gridlines 
     direction : ('v','h','b') : specifies either vetical gridlines, horizontal gridlines or both 
     label : ('y','n') : turns grid labels on or off 
     labelRepeat : 
    ''' 
    imgWidth, imgHeight = img.size 
    draw = ImageDraw.Draw(img) 
    textColor = (color[0], color[1], color[2]) 
    textFont = ImageFont.truetype(LabelFont+'.ttf', labelFontSize) 

    # add gridlines 
    if direction.lower() == 'b' or direction.lower() == 'v': 
     for v in range(1, int(imgWidth/gridWidth)+1): 
      draw.line((v*gridWidth, 0, v*gridWidth, imgHeight), fill = color, width = lineWidth) 

    if direction.lower() == 'b' or direction.lower() == 'h': 
     for h in range(1, int(imgHeight/gridWidth)+1): 
      draw.line((0, h*gridWidth, imgWidth, h*gridWidth), fill = color, width = lineWidth) 

    # add labels 
    if label.lower() == 'y': 
     for v in range(1, int(imgWidth/gridWidth)+1): 
      for h in range(1, int(imgHeight/gridWidth)+1): 
       if v == 1: 
        draw.text((3, 1+h*gridWidth), str(h), fill = textColor, font = textFont) 
       if h == 1: 
        draw.text((1+v*gridWidth, 3), str(v), fill = textColor, font = textFont) 
       if labelRepeat is not None: 
        if (h % labelRepeat == 0) and (v % labelRepeat == 0): 
         draw.text((1+v*gridWidth, 1+h*gridWidth), '('+str(h)+','+str(v)+')', fill = textColor, font = textFont) 



# draw gridlines 

if grid == 'on': 
    gridlines(img, minor, (180, 180, 255, 1)) 
    gridlines(img, major, (255, 0, 0, 100), label='Y', labelRepeat=3) 

# populate form 

draw.text((6*major+2*minor+3, 6*major+5*minor+2), 'econ_total', fill=textColor, font=font) 
draw.text((6*major+2*minor+3, 7*major+1*minor+2), 'notional_taxed', fill=textColor, font=font) 
draw.text((6*major+2*minor+3, 7*major+7*minor+2), 'notional_employer', fill=textColor, font=font) 
draw.text((6*major+2*minor+3, 8*major+4*minor+3), 'supca_total', fill=textColor, font=font) 
draw.text((6*major+2*minor+3, 9*major+2*minor-1), 'cgt_exempt_sb_ret', fill=textColor, font=font) 
draw.text((6*major+2*minor+3, 9*major+7*minor+0), 'cgt_exempt_sb_15yr', fill=textColor, font=font) 


del draw 
img.save('marked-up - 2013MCS7.jpg') 

答えて

1

最初に、grid = 'on'をブール値に置き換えます。文字列の比較ではなくTrueまたはFalseを使用して、if grid:で有効になっているかどうかを確認する必要があります。

第2に、PILにはデフォルトで破線を描く機能がありません。破線を描画するには、互いに間隔を置いていくつかの小さな線を描く必要があります。しかし、あなたがしようとしていることについては、破線は必要ではありません。線の不透明度を設定するには、高度な制御が必要です。

最後に、あなたのアプローチでは、線の不透明度を非常に細かく制御できるはずです。 gridlines()関数は、余分な作業をたくさん行っています。理由なく画像を再描画したり、テキストを描画したりします。そのため、グリッドラインが互いに何度か描画されているため、不透明になることがあります。

グリッドの描画がうまくいく場合、画像はJPEGでなくPNG形式で保存する必要があります。 JPEGは、写真の画像を保存するように設計されているので、赤色をうまく表現しません。つまり、より多くの情報を緑色や青色に保存することになります。

+0

ありがとうございます。 True/Falseでオン/オフを置き換え、提案したようにPNG形式で保存します。 2つの簡単な質問。 (1)あなたが「画像を何も理由なく再描画」と言うときは、関数内で 'draw = ImageDraw.Draw(img)'というステートメントを参照しているのか、それとも別の場所で起こっているのか(私が気づいていない) ?私はこれを描画にパスすることなく自己完結させる機能に入れましたが、私は再加工します。 (2)私は理解していない 'だから、最も起こりそうなことは、あなたのグリッド線が互いに何度か描かれているということだ。私はこれがどうなるか見ることができません。あなたは精緻化できますか? – apotheosied

+0

問題を解決した場合は、この問題を正しくマークすることを忘れないでください。 – Soviut

+0

これは私の問題を上記のコメント通りに解決しませんでした。私は透明性を得ることができません(それはまだ私のために不透明です)、私はどのように私のコードは、グリッド線が複数回(ループは、異なる間隔でそれらを描画する)描画される結果を見ることができません。私はこれが何の理由もなく画像を再描画することを意味していると仮定して、「draw = ImageDraw.Draw(img)」という2番目の参照を取り出しました。しかし、これを実行すると、私はこれがもっと良いと思ったので議論が引き出されますが、私はこれを2回描くコストを確信していません。 – apotheosied

関連する問題