2016/11/26(土) [n年前の日記]
#1 [python] 塗りつぶし処理(floodfill)について
お絵かきアプリでよくある、閉じた範囲の中でクリックすると指定色で塗り潰す処理を、Python + PySide (+ PIL(Pillow)) を使って試したい。どうやら、その手の処理を、
_Flood fill
と呼ぶらしいけど。
Ruby + DXRuby を使った版なら、昔書いたことがあったようで。 _2015/12/24の日記 にメモしてあった。Flood fill の一つ、Scanline Seed Fill を試していた模様。
コレを Python + PySide に移植してもいいのだけど、もしかしてこの手の処理は既に用意されているんじゃないか、と思ってググっていたら、どうやら PIL (Pillow) に、そのものズバリの floodfill というメソッドがあるようで。ただ、文書化はされていない模様。
_python - How to flood-fill part of a bitmap enclosed by a black border with my chosen color? - Stack Overflow
_floodfill_test.py
以下の画像を渡してみる。
以下の結果が得られた。
塗りつぶしができてる。
3回塗り潰してみたけど、手元の環境で時間を測ってみたら 0.433000秒だった。そんなに遅くはない、かな…。
ググってみたら、以下のページが。
_python-imaging 1.1.7 - namespace_p_i_l_1_1_image_draw.html
この floodfill() は Python で書かれてる、ということかな…。上下左右を1ドットずつ見ていく、という比較的シンプルなアルゴリズムっぽい。
Ruby + DXRuby を使った版なら、昔書いたことがあったようで。 _2015/12/24の日記 にメモしてあった。Flood fill の一つ、Scanline Seed Fill を試していた模様。
コレを Python + PySide に移植してもいいのだけど、もしかしてこの手の処理は既に用意されているんじゃないか、と思ってググっていたら、どうやら PIL (Pillow) に、そのものズバリの floodfill というメソッドがあるようで。ただ、文書化はされていない模様。
_python - How to flood-fill part of a bitmap enclosed by a black border with my chosen color? - Stack Overflow
>>> from PIL import Image, ImageDraw >>> help(ImageDraw.floodfill) Help on function floodfill in module PIL.ImageDraw: floodfill(image, xy, value, border=None) (experimental) Fills a bounded region with a given color. :param image: Target image. :param xy: Seed position (a 2-item coordinate tuple). :param value: Fill color. :param border: Optional border value. If given, the region consists of pixels with a color different from the border color. If not given, the region consists of pixels having the same color as the seed pixel.たしかに入っているっぽい。だったら、コレを使わせてもらおうか…。
_floodfill_test.py
u""" PIL(Pillow)のfloodfillを試す. PIL(Pillow)には、文書化されていないが floodfill という関数があって、 塗りつぶし処理ができるらしい。 動作確認環境 : Windows10 x64 + Python 2.7.12 + Pillow 3.4.2 """ from PIL import Image from PIL import ImageDraw import time im = Image.open("./tmp_image.png") start = time.time() ImageDraw.floodfill(im, (64, 64), (255, 0, 0, 255), border=None) ImageDraw.floodfill(im, (200, 240), (0, 255, 0, 255), border=None) ImageDraw.floodfill(im, (480, 400), (0, 0, 255, 255), border=None) etime = time.time() - start print("%f" % etime) im.save("./tmp_image_result.png")
以下の画像を渡してみる。
以下の結果が得られた。
塗りつぶしができてる。
3回塗り潰してみたけど、手元の環境で時間を測ってみたら 0.433000秒だった。そんなに遅くはない、かな…。
ググってみたら、以下のページが。
_python-imaging 1.1.7 - namespace_p_i_l_1_1_image_draw.html
この floodfill() は Python で書かれてる、ということかな…。上下左右を1ドットずつ見ていく、という比較的シンプルなアルゴリズムっぽい。
◎ QImageからPIL Imageへの変換。 :
塗りつぶしは PIL の floodfill() を利用させてもらうとして。PySide上で使おうとするなら…。
PIL Image から QImage への変換は、PIL の ImageQt を使えばできるはず、ということになってるけど。逆はどうすれば…。
ググったら以下のページが。
_setting python, eclipse, opencv and QT in linux: Converting from qimage to pil image
_PIL.Image と PyQt4.QtGui.QImageの相互変換 - None is None is None
バッファとやらを使って、一旦画像ファイルにして記録してから、また画像ファイルとして読み込む、ということをすれば変換できなくもないらしい。
ただ、PIL の ImageQt にも似たような処理をしてる部分があるような…。
_Pillow/ImageQt.py at master - python-pillow/Pillow
fromqimage() てのがあるけど、やってることが似ている…。が、pil_im = ImageQt.fromqimage(qim) とかやってみたらエラーが。
アレコレ試してたら、そもそも PySide + Pillow の組み合わせで ImageQt を使うと Python が不正終了・crash することに気が付いた。PIL Image から QImage への変換すらできないのでは困る。コレは別項でメモしたほうがいいかな…。
- QImage から PIL Image への変換。
- PIL Image から QImage への変換。
PIL Image から QImage への変換は、PIL の ImageQt を使えばできるはず、ということになってるけど。逆はどうすれば…。
ググったら以下のページが。
_setting python, eclipse, opencv and QT in linux: Converting from qimage to pil image
_PIL.Image と PyQt4.QtGui.QImageの相互変換 - None is None is None
バッファとやらを使って、一旦画像ファイルにして記録してから、また画像ファイルとして読み込む、ということをすれば変換できなくもないらしい。
ただ、PIL の ImageQt にも似たような処理をしてる部分があるような…。
_Pillow/ImageQt.py at master - python-pillow/Pillow
fromqimage() てのがあるけど、やってることが似ている…。が、pil_im = ImageQt.fromqimage(qim) とかやってみたらエラーが。
アレコレ試してたら、そもそも PySide + Pillow の組み合わせで ImageQt を使うと Python が不正終了・crash することに気が付いた。PIL Image から QImage への変換すらできないのでは困る。コレは別項でメモしたほうがいいかな…。
[ ツッコむ ]
以上です。