画像処理。OpenCV が出回り始めたころに中身のソースを見てギョッとしたがその内部の複雑さとは裏腹に Python からも容易に使えることが受けたのか確実にその地位を築いた。いかに簡便に使えるかというのは広まるうえで重要なのだろう。
Polyphony でも画像処理をしたい。1ラインの簡単な画像エッジを検出するフィルターを作ろう。
ここでは 9bit のデータを入出力する。最上位ビットはラインの終わりを指す。8bit が実際のピクセル。3x3 のフィルタだとラインバッファを持たないといけないがこの簡単なフィルタは、前後のピクセル差でエッジを検出する。最初は 1x3 にとおもったのだが、こちらの方がよいと思ってそう変えた。
line_edge.py
from polyphony import testbench
from polyphony import rule
from polyphony import module
from polyphony.typing import bit8, bit9
from polyphony.io import Queue
from polyphony import is_worker_running
from polyphony.timing import clksleep
@module
class line_edge:
def __init__(self, width):
self.img_in_q = Queue(bit9, 'in', maxsize=4)
self.img_out_q = Queue(bit9, 'out', maxsize=4)
self.append_worker(self.worker)
def worker(self):
with rule(scheduling='pipeline'):
last_pixel:bit8 = 0
out_eol_pixel:bit9 = 0
while is_worker_running():
eol_pixel:bit9 = self.img_in_q.rd()
eol:bit9 = eol_pixel & 0x100
pixel:bit8 = eol_pixel & 0xFF
out_eol_pixel = eol | (pixel - last_pixel if (pixel > last_pixel) else last_pixel - pixel)
self.img_out_q.wr(out_eol_pixel)
last_pixel = 0 if eol else pixel
@testbench
def test(m):
line_buf = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100 | 0x100]
for p in line_buf:
m.img_in_q.wr(p)
print(m.img_out_q.rd())
m = line_edge(1920)
test(m)
ここで注目してほしいのが pipeline を指定していること。python の with をつかって pipeline 化が(次のバージョンの0.3.3 以降あるいは現行の devel)出来る。
with
with rule(scheduling='pipeline'):
....
....
画像処理というからにはちゃんと画像処理しないといけない。Lenna の画像を処理してみよう。テストベンチで PIL は使えないので list を使う。
testbench
@testbench
def test(m):
i = 0
eol = 0
for p in LENNA:
if (i % 400) == 399 :
eol = 0x100
m.img_in_q.wr(eol | p)
eol = 0;
print(m.img_out_q.rd())
i += 1
m = line_edge(400) # 400x225 (LENNA)
test(m)