ラベル OpenCV の投稿を表示しています。 すべての投稿を表示
ラベル OpenCV の投稿を表示しています。 すべての投稿を表示

2014年6月23日月曜日

OpenCV 4

Contourとは等高線を指しますが、輪郭という意味もあります。
OpenCVではcontourを輪郭情報という意味で使用しています。

cv2の中にはfindContoursというcontourを計算する関数があります。
つまり、画像から輪郭を抽出することができます。
たとえば、
ret, thresh = cv2.threshold( imgray, 127, 255, 0 )
c = cv2.findContours( thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE )
とすることによりimgrayの画像を閾値処理して輪郭抽出します。

ただし、imgrayというのは2値化された画像で、通常のカラー画像を入れるとエラーになります。
カラー画像imを2値画像gimに変換する場合は、
gim = cv2.cvtColor( im, cv2.cv.CV_BGR2GRAY )
とします。


contourを描画する場合、
cv2.drawContours( im, c, -1, (0,255,0), 3 )
とすると緑色で輪郭情報cを画像imに描画します。

輪郭情報を最小の長方形領域に納める場合
x,y,w,h = cv2.boundingRect(c)
とします。
この長方形領域は
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)

とすることによって描画できます。



以上を踏まえて、
WEBカメラから取得した画像から輪郭を抽出して描画するプログラムを作ってみました。
ENTERキーを押すと終了します。


import cv2
import numpy as nmp

cv2.namedWindow('CAMERA')
v = cv2.VideoCapture(0)
v.grab()
im = v.read()

### to binary
gim = cv2.cvtColor( im[1], cv2.cv.CV_BGR2GRAY )
### thresholded
ret, thresh = cv2.threshold( gim, 127, 255, 0 )

c = cv2.findContours( thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE )
for i, cc in enumerate(c[0]):
 cv2.drawContours( im[1], cc, -1, (50*i/255,255,i%255), 3 )
 print '%d,255,%d' % ( 20*i/255, i%255)


cv2.imshow( 'CAMERA', im[1] )
cv2.waitKey(0)


ラボの画像から輪郭抽出してみました。

たくさんの小さい輪郭ができてしまいました。
実際に使う場合は、いかにして目的とするものの輪郭を計算するかという工夫が重要だと思います。

2014年6月9日月曜日

フラクタル 第4回

フラクタルシリーズの4回めです。

今回も、マンデルブロのアレンジを作ってみました。
ただ、毎回関数を別に作るのは無駄なので、P乗で一般化してみました。
つまり、

z(n+1) = z(n)**p + c
z(0)=0

とした時のcと最終のzの値を出力します。


import numpy as np

def makeMandelbrotP( itrn, p=2, n=100, xrange=None, yrange=None ):
if xrange == None:
xrange = (-2.5, 2.5)
if yrange == None:
yrange = (-2.5, 2.5)
r = np.random.uniform( xrange[0], xrange[1], n) + 1j*np.random.uniform( yrange[0], yrange[1],n)

c = r.copy()
z = 0
for i in range(itrn):
z = z**p + c
return c, z

今回はp=4として4乗にした時、このzの値が発散しているかどうかを複素平面上に表示しました。


予想通り、120度の回転対称です。
前回の3乗で180度対称だったので、p乗で306/(p-1) 度の回転対称になるものと想像できます。
この図は16回の繰り返しです。


繰り返し回数については、8回ぐらいでだいたいフラクタルっぽくなります。


繰り返し2回

繰り返し3回

繰り返し4回

繰り返し5回

繰り返し6回

繰り返し7回
繰り返し8回
という感じです。
一枚あたりのデータ量が多く、リスト内表記を使うとメモリアロケーションのエラーになるので、
仕方なくforループを使いました。
通常書類作成用に使っているPC(Core2Quad 2.4GHz)で、上の画像作成時間は一枚あたり6分位かかりました。






2014年5月12日月曜日

フラクタル

pythonで複素数の練習を兼ねて
フラクタル図形を作ってみました。
マンデルブロ集合というものです。


フラクタルが何かについては専門書または他のサイトなどで調べてみてください。
マンデルブロ集合の定義は簡単な複素数漸化式で記述されます。
つまりマンデルブロ図形というのはある複素数cについて、

z(n+1) = z(n)*z(n) + c
z(0) = 0

とした場合、n→∞で発散するか否かを色分けして複素平面に表示したものです。

複素数平面の点をランダムに選び、n回漸化式を解いてz(n)を作ります。
その時の、
log |z(n)|
の値を画素の輝度値としました。
forループを2重に使うと時間がかかるので、numpy.arrayで一気に計算します。

m = 10000
c = numpy.random.uniform( -2.5,2.5,m ) + 1j * numpy.random.uniform( -2.5,2.5,m )
z = numpy.zeros( m, dtype=numpy.complex )
for i in range(16):
     z = z**2 + c

と言う感じです。

opencvを使って画像化します。
しかし、案外時間が掛かるので、zの漸化式計算と、画像化を分けて処理しました。

Mandelbrot set

30Mポイントのサンプリングをして、そこから画像化しましたが、埋め切れていません。画像を拡大してみるとポツポツと黒い点が見えます。
実は細くつながっています。が、データ点数(サンプリング)で埋め切れていないのと画像化の解像度が荒いため、つながっているようには見えません。






2014年3月10日月曜日

OpenCV3: WEBカメラ画像の取得

pythonでOpenCVライブラリを利用し、画像処理をします。
今回は単純にWEBカメラ画像を取得して表示するプログラムを書いてみます。


import cv2

cv2.namedWindow('CAMERA')
v = cv2.VideoCapture(0)
v.grab()
im = v.read()
cv2.imshow( 'CAMERA', im[1] )
key = cv2.waitKey(0)


以上で終了です。
C言語などに比べると驚くほど短いです。

これを実行すると、WEBカメラから取得した画像をウィンドウに表示します。
ウィンドウ上でエンターキー入力するとウィンドウが消えてプログラムが終了します。


継続的にカメラ画像を取得して表示したい場合はgrabからwaitKeyまでをループさせてください。
waitKey命令を入れないと画面が更新されません。
waitKeyの引数はキーの入力待ち時間[msec]です。
ループさせると、カメラ画像を継続的に取得表示します。
つまりカメラの映像を、そのまま表示する事ができます。

ソースコードは

import cv2

cv2.namedWindow('CAMERA')
v = cv2.VideoCapture(0)
key = 0
while key != 32:
  v.grab()
  im = v.read()
  cv2.imshow( 'CAMERA', im[1] )
  key = cv2.waitKey(1000)


こんな感じです。
今度はスペースキーで終了します。

スペースキーに32という番号が振られているので、key=32になったらループから抜け出すようになっています。


実行すると
指定したCAMERAと言う名前のウィンドウが出てきます。







2014年3月4日火曜日

OpenCV2 画像の変換


pythonはライブラリが豊富ですが、ライブラリ間のフォーマットは同じであるとは限りません。
画像処理ライブラリに関しても主なものでOpenCVとPILというライブラリがあります。
その間の変換方法について解説します。
この機能、実際使う人がどのくらいいるのかは不明ですが、自分の備忘録も兼ねています。
もし、お役にたつならどうぞ。


CVからPIL
pim = Image.fromarray( cv2.cvtColor( cvim, cv2.cv.CV_BGR2RGB ) )


CVにおけるHSVとRGB,BGRの変換
xx = cv2.cvtColor( x, cv2.cv.RGB2HSV )

実際のところ、画像はnumpy.arrayとして表現されているので、
numpyのスライス機能を使えば同様の処理が可能なことがあります。
たとえば、RGBとBGRの変換では1層目と3層目を入れ替えるので、


tmp = x[:,:,0]
x[:,:,0] = x[:,:,2]
x[:,:,2] = tmp


とします。

反転もnumpy.arrayなら簡単にできます。
y = x[:,range(x.shape[1]-1,0,-1),:]
とすると左右反転します。
スライス機能を使うとなぜかうまくいかなかったのでrange関数使いました。

あと、ロボット用ソフトウェアのためにOpenRTミドルウェアというものを使っています。
pythonでロボットのモジュールが記述できます。
そのなかで使用する画像形式への変換方法についても載せておきます。


RTC.CameraImageからCVへの変更
## ci : cameraImage
### x : numpy.array


ci = RTC.CameraImage( tm, .... )
x = numpy.fromstring( ci.pixels, dtype=numpy.uint8 ).reshape( ci.height, ci.width, -1 )

CVからRTC.CameraImageへの変換
ci.pixels = x.tostring()
ci.width = x.shape[1]
ci.height = x.shape[0]

RTC.CameraImageからPILへの変換cam = RTC.CameraImage(...)
cvim = nmp.fromstring( cam.pixels, dtype=nmp.uint8 ).reshape( cam.height, cam.width, 3 )
pim = Image.fromarray( cv2.cvtColor( cvim, cv2.cv.CV_BGR2RGB ) )

2014年3月3日月曜日

OpenCV 1



pythonにはPILとOpenCVという画像関連ライブラリがあります。

GUIとしてはWxやTkがあり、グラフなどに特化したmatplotlibがあります。

ここでは、OpenCVを中心に説明します。




OpenCV

OpenCVはオープンソースで開発される画像処理ライブラリです。

従来はC++のみであったが、最近C#やPythonにも対応しています。

画像データの形式はnumpyのarray型を使用しています。

numpyは数値計算用のライブラリでいくつも便利な関数が定義されています。

なので、実際C++版よりも使いやすいです。




まだ、windowsインストーラのみでは完全にインストールはされないので、

インストール後手動でcv2.pyd(ダイナミックリンクライブラリ)をコピーする必要があります。

python2.6なら

c:\Python26\lib\site-packages\にコピー

python2.7なら

c:\Python27\lib\site-packages

という具合です。