1. Home

  2. /
  3. プログラミング
  4. /
  5. pythonで簡単プログラミング
  6. /
  7. 【画像描画】pythonで多角形を描いてみる

【画像描画】pythonで多角形を描いてみる

グラデーション後の五角形 pythonで簡単プログラミング

#python #Pillow #画像 #多角形 #line #色 #RGB

この記事では、pythonのPILというモジュール(Pillow)で多角形(五角形)を描く方法について、わかりやすく解説します。

本記事では、主としてWindows、および、python3を前提にしています。

絵を描くための準備

本記事では、画像を描くための準備は、下記のプログラムで行います。

<ファイル名:pentagon.py>

from PIL import Image, ImageDraw # PILからImage, ImageDrawクラスを取り出す

im = Image.new('RGB', ( 500,  600), (255, 255, 255)) # 500 ✕ 600ドットで白(=(255,255,255)の
                                                     # キャンバスを準備する
draw = ImageDraw.Draw(im) # 絵を描き込むバケツ(ImageDraw.Drwオブジェクト)を準備する

im.show() # 画面に表示する

実行は以下のようにして行います。

python pentagon.py

結果は以下のとおり、真っ白な500✕600ドットのキャンバスが表示されます。
なお、小生のPCでは画像表示にXnViewというソフトを使っているため、プログラムで、im.show()関数を実行したときに、これが起動されました。
読者の方は、違うソフトが起動されると思います。

円を描くことに集中するため、この部分のプログラムの詳細な説明はここではしません。コメントに簡単な説明をしていますので、参照してください。
詳しい説明が必要な場合は、『【第4回】にっこちゃんを描いてやんわりと関数・モジュールを学ぶ(解説編)』の『画像を描くキャンバスの作成』以降を参照してください。

座標について

画像の表示で使う座標は、下図のように
左上が (x, y)=(0, 0) で、
左に行くにつれて x座標が増え、
下に行くにつれて y座標が増えます。
中学で学ぶ数学の座標では、y座標は下が0で、上に行くにつれて増えますが、コンピュータでは、逆になるため、注意が必要です。

五角形を描いてみる

Pillowで多角形を描くには、直線をつなげて描きます。
そのためline関数を使います。
以下の入力が必要です。

・ 直線の開始位置x座標, y座標 ✕ 多角形の辺の数
・ 直線の終了位置x座標, y座標 ✕ 多角形の辺の数
・ 直線の色の赤(Red)成分, 緑(Green)成分, 青(Blue)成分
・ 直線の幅
・ 直線の連結部分の形状

プログラム中に書くと、以下になります。

draw.line(   (  (直線の開始位置x座標, y座標),      (直線の終了位置x座標, y座標)
          (直線の開始位置x座標, y座標),      (直線の終了位置x座標, y座標)
               : (多角形の辺の数だけ繰り返し)
          (直線の開始位置x座標, y座標),      (直線の終了位置x座標, y座標)  ), 
             fill=(  直線の色のRed成分,    Green成分,     Blue成分),
             width=直線の幅,
             joint=直線の連結部分の形状   )

実は直線の座標の指定方法にはいくつかの書式がありますが、この記事では現時点で最も問題のない(Pillowのバグを発生させない)書式で記載しています

本記事では、多角形の中でも五角形を描画します。
では、まず五角形の1辺を描画します。
キャンバスの左上(250, 30)から、(468, 209)に黒い線を描いてみます。
以下の行を付け加えます。

draw.line((( 250,  30),( 468, 209)), fill=(  0,   0,   0))

line関数の最初の入力 (( 0, 0), ( 500, 500)) は、
直線の開始位置x座標, y座標, 直線の終了位置x座標, y座標
です。
括弧 ”(“, “)” が外側に余分についていますが、これについては後述します。

2つ目の入力 fill=( 0, 0, 0) は、
fill=(直線の色の赤(Red成分), 緑(Green成分), 青(Blue成分)),
です。
Red成分, Green成分, Blue成分の全てが0の場合に黒となります。

付け加えた後のプログラムは以下になります。

<ファイル名:pentagon.py>

from PIL import Image, ImageDraw # PILからImage, ImageDrawクラスを取り出す

im = Image.new('RGB', ( 500,  600), (255, 255, 255)) # 500 ✕ 600ドットで白(=(255,255,255)の
                                                     # キャンバスを準備する
draw = ImageDraw.Draw(im) # 絵を描き込むバケツ(ImageDraw.Drwオブジェクト)を準備する

draw.line((( 250,  30),( 468, 209)), fill=(  0,   0,   0))

im.show() # 画面に表示する

実行した結果は以下のとおりに表示されます。

では、残りの直線も描いてみます。
多角形は、1つのline関数に、x,y座標を下記のように複数つなげて書くことで、描画することができます。
なお、五角形の頂点の座標は、数学の計算が必要となり難しいので、ここでは割愛します。

<ファイル名:pentagon.py>

from PIL import Image, ImageDraw # PILからImage, ImageDrawクラスを取り出す

im = Image.new('RGB', ( 500,  600), (255, 255, 255)) # 500 ✕ 600ドットで白(=(255,255,255)の
                                                     # キャンバスを準備する
draw = ImageDraw.Draw(im) # 絵を描き込むバケツ(ImageDraw.Drwオブジェクト)を準備する

draw.line((( 250,  30),( 468, 209),( 385, 466),( 115, 466),(  32, 209),( 250,  30),( 468, 209)), fill=(  0,   0,   0))

im.show() # 画面に表示する

実行すると以下となります。

さて、ここで、直線の幅を操作してみます。
line関数の入力に、widthを追加します。
“width=50″で、直線の幅を50ドットにします。

<ファイル名:pentagon.py>

from PIL import Image, ImageDraw # PILからImage, ImageDrawクラスを取り出す

im = Image.new('RGB', ( 500,  600), (255, 255, 255)) # 500 ✕ 600ドットで白(=(255,255,255)の
                                                     # キャンバスを準備する
draw = ImageDraw.Draw(im) # 絵を描き込むバケツ(ImageDraw.Drwオブジェクト)を準備する

draw.line((( 250,  30),( 468, 209),( 385, 466),( 115, 466),(  32, 209),( 250,  30),( 468, 209)), fill=(  0,   0,   0), width=50)

im.show() # 画面に表示する

実行すると以下になりました。
予想に反して、線のつなぎ目が離れてしまっています。

線のつなぎ目を綺麗に連結させます。
line関数の入力に、”joint=’curve'”を追加します。
‘curve’なので、丸みのある連結を行います。

<ファイル名:pentagon.py>

from PIL import Image, ImageDraw # PILからImage, ImageDrawクラスを取り出す

im = Image.new('RGB', ( 500,  600), (255, 255, 255)) # 500 ✕ 600ドットで白(=(255,255,255)の
                                                     # キャンバスを準備する
draw = ImageDraw.Draw(im) # 絵を描き込むバケツ(ImageDraw.Drwオブジェクト)を準備する

draw.line((( 250,  30),( 468, 209),( 385, 466),( 115, 466),(  32, 209),( 250,  30),( 468, 209)), fill=(  0,   0,   0), width=50, joint='curve')

im.show() # 画面に表示する

実行すると以下になります。

グラデーションで塗りつぶしてしまう

ここまで来ると、色が黒のままでは地味ですので、この際、中をグラデーションで塗りつぶしてみます。
しかし、そのためには、五角形をいくつも中に描いていくことになります。
ですので、書くのを避けていた計算式をプログラムしてしまいます。

<ファイル名:pentagon.py>

from PIL import Image, ImageDraw # PILからImage, ImageDrawクラスを取り出す
import math as m                 # 三角関数含む数学計算モジュール

im = Image.new('RGB', ( 500,  600), (255, 255, 255)) # 500 ✕ 600ドットで白(=(255,255,255)の
                                                     # キャンバスを準備する
draw = ImageDraw.Draw(im) # 絵を描き込むバケツ(ImageDraw.Drwオブジェクト)を準備する

xoffset = 250               # 五角形中心のx座標
yoffset = 30                # 五角形の天井のy座標
delta = 10                  # 五角形のサイズの増減ドット数

red = 200                   # 赤要素
green = 50                  # 緑要素
blue = 0                    # 青要素

# spoke_len ... 五角形のスポーク(中心から頂点までの長さ)

for spoke_len in range(230, 0, -delta) :            # 230から0まで-deltaでspoke_lenを減らす

    cos18 = int(spoke_len * m.cos(18/180 * m.pi))   # スポークをcos 18°傾けたx座標成分
    sin18 = int(spoke_len * m.sin(18/180 * m.pi))   # スポークをsin 18°傾けたy座標成分
    cos54 = int(spoke_len * m.cos(54/180 * m.pi))   # スポークをcos 54°傾けたx座標成分
    sin54 = int(spoke_len * m.sin(54/180 * m.pi))   # スポークをsin 54°傾けたy座標成分

    # 五角形の各頂点の座標
    x1 = xoffset
    y1 = yoffset
    x2 = xoffset + cos18
    y2 = spoke_len - sin18 + yoffset
    x3 = xoffset + cos54
    y3 = spoke_len + sin54 + yoffset
    x4 = xoffset - cos54
    y4 = spoke_len + sin54 + yoffset
    x5 = xoffset - cos18
    y5 = spoke_len - sin18 + yoffset
 
    draw.line(((x1,  y1),(x2, y2),(x3, y3),(x4, y4),(x5, y5),(x1, y1),(x2, y2)), 
        fill=(red, green, blue), width=50, joint='curve')

    # 黄色に変化させる
    red = red + 10
    green = green + 10
    
    # スポークが短くなる分、五角形の天井を下へ移動する
    yoffset = yoffset + delta

im.show() # 画面に表示する

上記のプログラムはおおよそ、以下の処理を行っています。
詳細についてはプログラム中のコメントを参照してください。

1.for文で五角形のスポーク(中心から頂点までの長さ)をだんだん小さくしていく
2.五角形の中心を一定にしたまま、頂点の座標を三角関数(cos,sin)を使って計算する
3.五角形を描画する
4.色値を変化させる
5.スポークが短くなる分、五角形の天井を下へ移動させる

実行結果は以下になります。

最後に

いかがでしたでしょうか?
五角形などの多角形は直線を描画するline関数で描画することができます。
また、今回は、line関数に以下のオプションが指定できることが分かりました。

  • 直線の幅
  • 直線の連結部分の形状

また、

  • for文
  • range関数
  • 三角関数(cos,sin)を使った計算

など、プログラミングならではの特別な処理についても解説しました。

ということで、また別の描画方法を解説しますので、ご期待ください!

この記事へのお問い合わせや、無料のサポート、一歩踏み込んだ有料サポートが必要な場合は、ホームページからメールで受け付けています。お気軽にご連絡ください。

コメント

タイトルとURLをコピーしました