#python #Pillow #画像 #円 #楕円 #ellipse #色 #RGB
この記事では、pythonのPILというモジュール(Pillow)で円・楕円を描く方法についてわかりやすく解説します。
絵を描くための準備
本記事では、画像を描くための準備は、下記のプログラムで行います。
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() # 画面に表示する
<ファイル名:ellipse.py>
実行は以下のようにして行います。
python ellipse.py
結果は以下のとおり、真っ白な500✕600ドットのキャンバスが表示されます。
なお、小生のPCでは画像表示にXnViewというソフトを使っているため、プログラムで、im.show()関数を実行したときに、これが起動されました。
読者の方は、違うソフトが起動されると思います。
円を描くことに集中するため、この部分のプログラムの詳細な説明はここではしません。コメントに簡単な説明をしていますので、参照してください。
詳しい説明が必要な場合は、『【第4回】にっこちゃんを描いてやんわりと関数・モジュールを学ぶ(解説編)』の『画像を描くキャンバスの作成』以降を参照してください。
座標について
画像の表示で使う座標は、下図のように
左上が (x, y)=(0, 0) で、
左に行くにつれて x座標が増え、
下に行くにつれて y座標が増えます。
中学で学ぶ数学の座標では、y座標は下が0で、上に行くにつれて増えますが、コンピュータでは、逆になるため、注意が必要です。
円を描いてみる
Pillowで円を描くには、ellipse関数を使います。
以下の入力が必要です。
・ 円の開始位置x座標, y座標
・ 円の終了位置x座標, y座標
・ 円の中を塗りつぶす色の赤(Red)成分, 緑(Greeen)成分, 青(Blue)成分
・ 円の枠の色の赤(Red)成分, 緑(Greeen)成分, 青(Blue)成分
プログラム中に書くと、以下になります。
draw.ellipse( (円の開始位置x座標, y座標, 円の終了位置x座標, y座標),
fill=( 円の中を塗りつぶす色のRed成分, Greeen成分, Blue成分),
outline=( 円の枠の色のRed成分, Greeen成分, Blue成分))
では、まずオーソドックスに、
500✕600ドットのキャンバスの左上に、100✕100の大きさで、黒で塗りつぶした円を描いてみます。
以下の行を付け加えます。
draw.ellipse(( 0, 0, 100, 100), fill=( 0, 0, 0), outline=( 0, 0, 0))
ellipse関数の最初の入力 ( 0, 0, 100, 100) は、
円の開始位置x座標, y座標, 円の終了位置x座標, y座標
です。
2つ目の入力 fill=( 0, 0, 0), outline=( 0, 0, 0)) は、
fill=(円の中を塗りつぶす色の赤(Red成分), 緑(Greeen成分), 青(Blue成分)),
outline=(円の枠の色の赤(Red成分), 緑(Greeen成分), 青(Blue成分)))
です。
黒はRed成分, Greeen成分, Blue成分の全てが0の場合に黒となります。
付け加えた後のプログラムは以下になります。
<ファイル名:ellipse.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.ellipse(( 0, 0, 100, 100), fill=( 0, 0, 0), outline=( 0, 0, 0))
im.show() # 画面に表示する
実行した結果は以下のとおりに表示されます。
円をいくつか並べてみる
円をいくつか並べてみます。
座標をずらして5つ追加して並べます。
<ファイル名:ellipse.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.ellipse(( 0, 0, 100, 100), fill=( 0, 0, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 100, 100, 200), fill=( 0, 0, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 200, 100, 300), fill=( 0, 0, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 300, 100, 400), fill=( 0, 0, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 400, 100, 500), fill=( 0, 0, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 500, 100, 600), fill=( 0, 0, 0), outline=( 0, 0, 0))
im.show() # 画面に表示する
プログラムの着色部分を見るとわかりますが、y座標を100ずつずらしました。
結果は以下のとおりになります。
色を変える
黒では面白くないので、色を変えてみます。
色は、赤(Red), 緑(Green), 青(Blue)の3色を指定して混ぜた色になります。
それぞれ、0 ~ 255の数値で濃さを指定します。
ただしこの色は、光を重ね合わせて混ぜる色になるため、絵の具で混ぜた色とは異なります。たとえば、絵の具の場合は、赤、緑、青を全て混ぜると黒くなりますが、パソコンのモニタやスマホの画面では、白になります。
この色の指定形式をRGB形式といい、pythonに限らず、どのような言語で使用する場合でも共通です。
では、色を0か255にして順に変えてみます。
枠の色は黒のままにします。
<ファイル名:ellipse.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.ellipse(( 0, 0, 100, 100), fill=( 0, 0, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 100, 100, 200), fill=(255, 0, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 200, 100, 300), fill=( 0, 255, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 300, 100, 400), fill=( 0, 0, 255), outline=( 0, 0, 0))
draw.ellipse(( 0, 400, 100, 500), fill=(255, 255, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 500, 100, 600), fill=( 0, 255, 255), outline=( 0, 0, 0))
draw.ellipse(( 100, 0, 200, 100), fill=(255, 255, 255), outline=( 0, 0, 0))
im.show() # 画面に表示する
結果は以下となります。
キャンバスにまだ余りがありますし、せっかくなので、0と255だけではなく、中間の色も表示してみます。
枠(outline)は同じ色にします。
量が多くなるので、プログラムが見にくくなりますが、受け入れてください。
<ファイル名:ellipse.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.ellipse(( 0, 0, 100, 100), fill=( 0, 0, 0), outline=( 0, 0, 0))
draw.ellipse(( 0, 100, 100, 200), fill=( 50, 0, 0), outline=( 50, 0, 0))
draw.ellipse(( 0, 200, 100, 300), fill=(100, 0, 0), outline=(100, 0, 0))
draw.ellipse(( 0, 300, 100, 400), fill=(150, 0, 0), outline=(150, 0, 0))
draw.ellipse(( 0, 400, 100, 500), fill=(200, 0, 0), outline=(200, 0, 0))
draw.ellipse(( 0, 500, 100, 600), fill=(250, 0, 0), outline=(250, 0, 0))
draw.ellipse(( 100, 0, 200, 100), fill=(250, 0, 0), outline=(250, 0, 0))
draw.ellipse(( 100, 100, 200, 200), fill=(250, 50, 0), outline=(250, 50, 0))
draw.ellipse(( 100, 200, 200, 300), fill=(250, 100, 0), outline=(250, 100, 0))
draw.ellipse(( 100, 300, 200, 400), fill=(250, 150, 0), outline=(250, 150, 0))
draw.ellipse(( 100, 400, 200, 500), fill=(250, 200, 0), outline=(250, 200, 0))
draw.ellipse(( 100, 500, 200, 600), fill=(250, 250, 0), outline=(250, 250, 0))
draw.ellipse(( 200, 0, 300, 100), fill=(250, 250, 0), outline=(250, 250, 0))
draw.ellipse(( 200, 100, 300, 200), fill=(200, 250, 0), outline=(200, 250, 0))
draw.ellipse(( 200, 200, 300, 300), fill=(150, 250, 0), outline=(150, 250, 0))
draw.ellipse(( 200, 300, 300, 400), fill=(100, 250, 0), outline=(100, 250, 0))
draw.ellipse(( 200, 400, 300, 500), fill=( 50, 250, 0), outline=( 50, 250, 0))
draw.ellipse(( 200, 500, 300, 600), fill=( 0, 250, 0), outline=( 0, 250, 0))
draw.ellipse(( 300, 0, 400, 100), fill=( 0, 250, 0), outline=( 0, 250, 0))
draw.ellipse(( 300, 100, 400, 200), fill=( 0, 200, 50), outline=( 0, 200, 50))
draw.ellipse(( 300, 200, 400, 300), fill=( 0, 150, 100), outline=( 0, 150, 100))
draw.ellipse(( 300, 300, 400, 400), fill=( 0, 100, 150), outline=( 0, 100, 150))
draw.ellipse(( 300, 400, 400, 500), fill=( 0, 50, 200), outline=( 0, 50, 200))
draw.ellipse(( 300, 500, 400, 600), fill=( 0, 0, 250), outline=( 0, 0, 250))
draw.ellipse(( 400, 0, 500, 100), fill=( 0, 0, 250), outline=( 0, 0, 250))
draw.ellipse(( 400, 100, 500, 200), fill=( 50, 0, 250), outline=( 50, 0, 250))
draw.ellipse(( 400, 200, 500, 300), fill=(100, 0, 250), outline=(100, 0, 250))
draw.ellipse(( 400, 300, 500, 400), fill=(150, 0, 250), outline=(150, 0, 250))
draw.ellipse(( 400, 400, 500, 500), fill=(200, 0, 250), outline=(200, 0, 250))
draw.ellipse(( 400, 500, 500, 600), fill=(250, 0, 250), outline=(250, 0, 250))
im.show() # 画面に表示する
実行結果です。
虹色である赤橙黄緑青藍紫のグラデーションになりました。
楕円を描く
ellipse関数は ellipse=楕円 であることから、実は楕円を描く関数です。
円は楕円の1つであるため、ellipse関数でどちらも描画ができます。
最後に、楕円を描いてみます。
楕円は、x, y座標のどちらかを大きくまたは小さくすることで描画できます。
<ファイル名:ellipse_rainbow.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.ellipse(( 0, 0, 500, 500), fill=( 0, 0, 0), outline=( 0, 0, 0))
draw.ellipse(( 10, 0, 490, 500), fill=( 50, 0, 0), outline=( 50, 0, 0))
draw.ellipse(( 20, 0, 480, 500), fill=(100, 0, 0), outline=(100, 0, 0))
draw.ellipse(( 30, 0, 470, 500), fill=(150, 0, 0), outline=(150, 0, 0))
draw.ellipse(( 40, 0, 460, 500), fill=(200, 0, 0), outline=(200, 0, 0))
draw.ellipse(( 50, 0, 450, 500), fill=(250, 0, 0), outline=(250, 0, 0))
draw.ellipse(( 60, 0, 440, 500), fill=(250, 50, 0), outline=(250, 50, 0))
draw.ellipse(( 70, 0, 430, 500), fill=(250, 100, 0), outline=(250, 100, 0))
draw.ellipse(( 80, 0, 420, 500), fill=(250, 150, 0), outline=(250, 150, 0))
draw.ellipse(( 90, 0, 410, 500), fill=(250, 200, 0), outline=(250, 200, 0))
draw.ellipse(( 100, 0, 400, 500), fill=(250, 250, 0), outline=(250, 250, 0))
draw.ellipse(( 110, 0, 390, 500), fill=(200, 250, 0), outline=(200, 250, 0))
draw.ellipse(( 120, 0, 380, 500), fill=(150, 250, 0), outline=(150, 250, 0))
draw.ellipse(( 130, 0, 370, 500), fill=(100, 250, 0), outline=(100, 250, 0))
draw.ellipse(( 140, 0, 360, 500), fill=( 50, 250, 0), outline=( 50, 250, 0))
draw.ellipse(( 150, 0, 350, 500), fill=( 0, 250, 0), outline=( 0, 250, 0))
draw.ellipse(( 160, 0, 340, 500), fill=( 0, 200, 50), outline=( 0, 200, 50))
draw.ellipse(( 170, 0, 330, 500), fill=( 0, 150, 100), outline=( 0, 150, 100))
draw.ellipse(( 180, 0, 320, 500), fill=( 0, 100, 150), outline=( 0, 100, 150))
draw.ellipse(( 190, 0, 310, 500), fill=( 0, 50, 200), outline=( 0, 50, 200))
draw.ellipse(( 200, 1, 300, 500), fill=( 0, 0, 250), outline=( 0, 0, 250))
draw.ellipse(( 210, 0, 290, 500), fill=( 50, 0, 250), outline=( 50, 0, 250))
draw.ellipse(( 220, 0, 280, 500), fill=(100, 0, 250), outline=(100, 0, 250))
draw.ellipse(( 230, 0, 270, 500), fill=(150, 0, 250), outline=(150, 0, 250))
draw.ellipse(( 240, 0, 260, 500), fill=(200, 0, 250), outline=(200, 0, 250))
draw.ellipse(( 250, 0, 250, 500), fill=(250, 0, 250), outline=(250, 0, 250))
im.show() # 画面に表示する
このプログラムでは、楕円をいくつも重ねていって、虹色グラデーションの楕円を描きます。
ellipse関数の y座標は、0と500に固定していて、x座標を左右の端から10ドットずつ縮めていって順番に楕円を重ねています。
最後に
いかがでしたでしょうか?
円、楕円を描くだけでも、以下を知る必要がありました。
- 座標の指定方法
- 色の指定方法
- 追加の指定方法(枠の色)
これらの要素は、円、楕円以外の描画をおこなうときにも基本的に同じです。
ということで、また別の描画方法を解説しますので、ご期待ください!
この記事へのお問い合わせや、一歩踏み込んだサポートが必要な場合は、
ホームページからメールで受け付けています。お気軽にご連絡ください。
コメント