ハフ変換
ruby-opencvでハフ変換をして、画像の線分抽出をする。
require "opencv" include OpenCV original_window = GUI::Window.new "original" hough_windowS = GUI::Window.new "hough(standard)" hough_windowP = GUI::Window.new "hough(probabilistic)" img = IplImage::load(ARGV.shift) gry = img.BGR2GRAY resultS = gry.GRAY2BGR resultP = resultS.clone linesS = gry.canny(50,200,3).hough_lines(CV_HOUGH_STANDARD, 1, Math::PI/180, 50, 0, 0) linesP = gry.canny(50,200,3).hough_lines(CV_HOUGH_PROBABILISTIC, 1, Math::PI/180, 50, 50, 10) cnt = 250 linesS.each do |l| cos,sin = Math::cos(l.theta), Math::sin(l.theta) x0,y0 = l.rho*cos,l.rho*sin # puts "#{l.rho},#{l.theta}, #{cos},#{sin}" resultS.line!(CvPoint.new(x0-1000*sin,y0+1000*cos), CvPoint.new(x0+1000*sin,y0-1000*cos), {:color=>CvColor::Red,:thickness=>1}) cnt-=1;break if cnt<0 end puts linesS.size linesP.each do |l| # puts "#{l.point1},#{l.point2}" resultP.line!(l.point1, l.point2, {:color=>CvColor::Red,:thickness=>1}) end puts linesP.size original_window.show img hough_windowS.show resultS hough_windowP.show resultP GUI::wait_key
シングルプレーンの取り出しとマージ
OpenCV 2.4.11(VS10), ActiveScriptRuby 2.2(32bit), ruby-opencv-0.0.14
RGB画像から、Gプレーンのみ取り出し、RとBをゼロで埋めた画像を作成したいのだけど、感覚的に書いたコードだとエラーが出る。
b,g,r = img.split
b2 = IplImage.merge(b)
g2 = IplImage.merge(nil, g)
r2 = IplImage.merge(nil, nil, r)
で動いて欲しいのだけど、うまく動かない。
まず、merge(b)だと「array.cpp:1238: error: (-5) Array should be CvMat or IplImage in function cvGetSize」となる。
merge(b.to_CvMat)だとエラーが出ないが、RGB全てのプレーンが、B画像で埋まってしまう。
merge(b.to_CvMat, nil, nil)とすると、意図した通りに動く。(Bプレーンのみ取り出され、R/Gプレーンはゼロで埋まった画像)
同様に merge(nil, g.to_CvMat, nil)としたら Gプレーン だけ取り出されて R/Bがゼロで埋まった画像ができそうな気がするのだけど、うまく行かない。
あらかじめ全てがゼロで埋まったB画像を作成して、 merge(b0.to_CvMat, g.to_CvMat, nil) とすると意図通りに動く。
結局、以下の様にすると、RGB画像からRプレーンのみ画像/Gプレーンのみ画像/Bプレーンのみ画像を作成できる。
require 'opencv' include OpenCV W,H = 340,200 win = GUI::Window.new("win") rwin = GUI::Window.new("rwin") gwin = GUI::Window.new("gwin") bwin = GUI::Window.new("bwin") img = IplImage.new(W, H, CV_8U, 3).fill(CvColor::White) # 真白なキャンバスを作成 # blk = IplImage.new(W, H, CV_8U, 3).fill(CvColor::Black) # 赤線を引いたり、四角形を描画したり、文字を描画したりする # img.line!(CvPoint.new(10,140),CvPoint.new(330,190), {:color=>CvColor::Red,:thickness=>6}) img.rectangle!(CvPoint.new(200,40),CvPoint.new(280,180), {:color=>CvColor::Green,:thickness=>9}) 9.times do |i| # 塗り潰し(-1)を指定して、青色の円を描く # img.circle!(CvPoint.new(i*40,i*20), 2+i*2, {:color=>CvColor::Blue,:thickness=>-1}) end font = CvFont.new(:plain, :hscale => 5.0, :vscale => 4.5, :shear => 1.0, :thickness => 3, :line_type => 5, :italic => true) img.put_text!('Ruby', CvPoint.new(2, 60), font, CvColor::Black) img.put_text!('OpenCV', CvPoint.new(2, 120), font, CvColor::Black) win.show img b,g,r = img.split b0,g0,r0 = blk.split # 全てがゼロで埋まった R画像/G画像/B画像を作成する # b2 = IplImage.merge(b.to_CvMat, nil, nil) g2 = IplImage.merge(b0.to_CvMat, g.to_CvMat, nil) r2 = IplImage.merge(b0.to_CvMat, g0.to_CvMat, r.to_CvMat) rwin.show r2 gwin.show g2 bwin.show b2 GUI::wait_key(0)
GalaxyNote3 をPCからUSBカメラとして使う
今手元にあるPCにはカメラが付いていない。
なので、Androidスマホである GalaxyNote3 をUSBカメラとして使えるか試してみる。
『Androidスマホ内蔵カメラをパソコン用の「Webカメラ」として使おう:「DroidCam」(開発者:Dev47Apps)』
http://pc.nikkeibp.co.jp/article/special/20130625/1095722/?P=2
↑ここで紹介されている、 DroidCam を試してみたが、フツーにUSBカメラとして使えて、 USB接続の GalaxyNote3 のカメラで取り込んだ映像を ruby-opencv で処理できた。
【手順】
1. GlaxyNote3 で Googleプレイを検索、「DroidCam」をインストール。
2. DroidCam Client v5.0.1 を PC にインストール。
http://www.dev47apps.com/droidcam/windows/
3. SAMSUNGのサイトから、USBドライバーをインストール。(下記ページの「Download for Others」から「KIESとテザリング機能のUSB DRIVER」をクリックしてDL、インストール)
http://www.samsung.com/jp/support/usefulsoftware/KIES/
4. GalaxyNote3 の設定画面で「開発者オプション」を開き、「USBデバッグ」にチェック。
(必にならば「ビルド番号」7回タップで開発者オプションが表示される様にしておいて)
5. GalaxyNote3 をPCにUSB接続して、 DroidCam を起動。
6. PC側で DroidCam Client を起動、接続モードをUSBにして「Start」を押す。
下記コードを引数無しで起動して、例外も起きずにカメラ映像が表示されるのを確認。
require 'opencv' include OpenCV captureDevice = 0 if ARGV.size > 1 captureDevice = ARGV.shift captureDevice = captureDevice.to_i if /^\d$/ =~ captureDevice end win = GUI::Window.new("win") cap = CvCapture.open(captureDevice) puts cap.fps if cap.fps > 67 or cap.fps < 5 # 変なfpsの時は10fps(100msec間隔)にする frame_msec = 100 else frame_msec = 1000/cap.fps end loop do img = cap.query break unless img win.show img c = GUI::wait_key(frame_msec) break if c == 27 # [ESC]で終了 # end
ruby-opencvでマウスイベント処理
require 'opencv' include OpenCV w = GUI::Window.new("w") img = IplImage.new(340, 200, CV_8U, 3) img.fill!(CvColor::White) # 真白に塗り潰す # p = nil opt = {:color=>CvColor::Green, :thickness=>1} w.on_mouse do |m| # 左クリックで線を太くする opt[:thickness]+=1 if m.event == :left_button_down img.line!(p, m, opt) if p # 線を描画する # p = m w.show img end GUI::wait_key(0)
ruby-opencvで図形描画
require 'opencv' include OpenCV w = GUI::Window.new("w") img = IplImage.new(340, 200, CV_8U, 3) img.fill!(CvColor::White) # 真白に塗り潰す # img.line!(CvPoint.new(10,140),CvPoint.new(330,190), {:color=>CvColor::Red,:thickness=>4}) img.rectangle!(CvPoint.new(200,40),CvPoint.new(280,180), {:color=>CvColor::Green,:thickness=>9}) 8.times do |i| img.circle!(CvPoint.new(i*30,i*30), 15, {:color=>CvColor::Blue,:thickness=>6}) end font = CvFont.new(:plain, :hscale => 5.0, :vscale => 4.5, :shear => 1.0, :thickness => 3, :line_type => 5, :italic => true) img.put_text!('Ruby', CvPoint.new(2, 60), font, CvColor::Black) img.put_text!('OpenCV', CvPoint.new(2, 120), font, CvColor::Black) w.show img GUI::wait_key(0)
ruby-opencvでカラーチャネルを分離したり
splitでblue,green,redを分離できるのだけど、シングルプレーンからIplImage.merge(blue,green,red,nil)とかしても、BGR画像を復元できない。
何故??
require 'opencv' include OpenCV captureDevice,mode = 0,nil if ARGV.size > 0 captureDevice = ARGV.shift captureDevice = captureDevice.to_i if /^\d$/ =~ captureDevice end win = GUI::Window.new("inp") red = GUI::Window.new("red") gre = GUI::Window.new("green") blu = GUI::Window.new("blue") cap = CvCapture.open(captureDevice) begin fps = cap.fps if fps > 67 or fps < 5 # 変なfpsの時は10fps(100msec間隔)にする fps = 10 end rescue fps = 10 end frame_msec = 1000/fps loop do inp = cap.query break unless inp win.show inp b,g,r = inp.split red.show r gre.show g blu.show b bgr = inp.avg # 各カラープレーン毎に平均をとる # ravg,gavg,bavg = bgr[2],bgr[1],bgr[0] if ravg > gavg if ravg > bavg puts("赤っぽい") else puts("青っぽい") end else if gavg > bavg puts("緑っぽい") else puts("青っぽい") end end key = GUI::wait_key(frame_msec) mode = key.chr if key break if mode == 'q' end
ruby-opencvで色々なフィルタを試す
カメラで絵を取り込みながら、或いは動画を再生させながら、キーを押して、色々なフィルタを試す。
require 'opencv' include OpenCV captureDevice,mode = 0,nil if ARGV.size > 0 captureDevice = ARGV.shift captureDevice = captureDevice.to_i if /^\d$/ =~ captureDevice end win = GUI::Window.new("win") cap = CvCapture.open(captureDevice) begin fps = cap.fps if fps > 67 or fps < 5 # 変なfpsの時は10fps(100msec間隔)にする fps = 10 end rescue fps = 10 end frame_msec = 1000/fps loop do out = inp = cap.query break unless inp case mode when 'a'; out = inp.BGR2GRAY.add(100) #グレースケールにして白っぽくする when 'b'; out = inp.smooth(CV_BLUR) #単純平滑化 when 'c'; out = inp.BGR2GRAY.canny(120,200) #canny法でエッジ抽出 when 'd'; out = inp.BGR2GRAY.dilate #ディレーション when 'e'; out = inp.BGR2GRAY.erode #エロージョン when 'f'; out = inp.flip #左右反転 when 'g'; out = inp.smooth(CV_GAUSSIAN) #ガウシアン平滑化 when 'q'; break end win.show out key = GUI::wait_key(frame_msec) mode = key.chr if key end