四畳半テクノポリス

コロナのストレスで気が狂い、D進した院生

Kicadで設計したデータのスイッチサイエンスPCBへの発注

 昨日も記事に書いたが、後先を考えず、だらだらと続けていた基板設計が終わったのでスイッチサイエンスPCBに発注をかけた。現実逃避として打ち込んでいたマイクロマウスも、現状できる作業は大体終わってしまった。

 せっかく基板を発注したので、その手順を解説してみようと思う、解説は以下の4段階に分けて行っていく。

  1. 設計データからのガーバーデータの書き出し
  2. ガーバーデータの確認
  3. ガーバーデータのリネームと圧縮
  4. SwitchSciencePCBへの発注

今回は触れないが、設計した基板データはSwitchScencePCBのデザインルールに基づいた設計をしていることを前提とする。

1:設計データからのガーバーデータの書き出し

1.2:外形のガーバーデータの書き出し

 Kicadはで作成した設計データから基板の製造に必要なガーバーデータの書き出しを行う。ガーバーデータというのは、実際に基板の製造をおこなう、工作機械を動かすための加工データである。余談だが、基板の外形や配線がベクトル形式で格納されている。実際に加工を行う際はこのベクトルデータに対しCAMソフトで読み込み、ガーバーデータ通りに加工するためのNCDデータに変換されるのが一般的である。

 Kicadでガーバーデータをの書き出しを行うにはまず丈夫バー上の「Plot」ボタンを押し、ガーバーの書き出し用のウィンドウを開く、すると次の様なウィンドウが現れる。

f:id:toriten1024:20170211200346p:plain

ここでウィンドウの左が側にたくさん並んでいるチェックボックスが、ガーバーデータとして書き出すレイヤーの選択である。今回の基板は両面二層基板であるためチェックするのは

  • F.Cu: 表面の銅箔
  • B.Cu: 裏面の銅箔
  • B.SilkS: 裏面のシルク(部品番号などを示した印字)
  • F.SilkS: 表面のシルク
  • Edge.Cuts: 基板の外形データ

の5っつである。

 次にオプションの設定であるが、基本的には「Plot Footprint Value」と「Plot Footprint Refarence」だけチェックしておけば問題無い。基板の外形データを自動作成したい場合や、CAD上で非表示になっている文字を表示したいときにはその他のオプションを弄る必要がある。

 さらに、にGarber Optionsであるが「Use Protel filename Extinction」をチェックすると出力される基板の拡張子が製造で使うものと同じになる。

1.3:ドリルデータ

 基板のビアや、部品の足を差し込むスルーホールなど、の穴データはガーバーデータとは別途に出力する必要がある。ガーバーデータの出力ウィンドウを見ると、下の方に「Generate Drill File」というボタンがあるので、それをクリックすると、次の様なドリルファイル出力画面が表示される。

f:id:toriten1024:20170211202439p:plain

 「DrillUnit」というオプションは「MillMeters」にチェックを入れ「Drill Map FIle Format」は「Garver」にチェックを入れる。この状態で「Drill File」というボタンを押すとガーバーデータと同じフォルダに[ファイル名].drlというファイルが出力されるはずである。

2.ガーバーデータの確認

 出力したガーバーデータをガーバーデータビューアを用いて正しく出力出来ているか確認を行う、ガーバーデータの拡張子は「Use Protel filename Extinction」にチェックをしていた場合は、それぞれ次の用になっているはずである。

  • 表面の銅箔: [ファイル名].gtl
  • 裏面の銅箔:    [ファイル名].gbl
  • 裏面のシルク: [ファイル名].gbo
  • 表面のシルク: [ファイル名].gto
  • 基板の外形データ: [ファイル名].gml
  • ドリルの穴データ: [ファイル名].drl

 これらのファイルをガーバービューアに読み込んで正しく出力出来ているかの確認を行う。ガーバービューアのソフトはKiCAD付属「Gerv View」というものがあるのでそれを使って閲覧すると良い。

 ガーバーデータの確認を行うときに、注意して欲しいのは次の画像に示すようなマスク同士や、マスクとシルクの干渉である。画像を見るとD32とD24のマスクが干渉しあっているのが見て取れる、このままでも製造において致命的な問題があるわけではないが、不具合の原因となりやす買ったり、ハンダ付けがしにくくなるため、修正したほうが良い。

f:id:toriten1024:20170211203115p:plain

修正した画像が次の物である。ガーバーファイルを読みなおしたので色が変わってしまっているがD23がICの下のキャパシタ(D32)と干渉していない事が見て取れる。

f:id:toriten1024:20170211203332p:plain

 ガーバーとして出力出来ている以上、致命的な問題があるとも考えづらいが、このようにガーバーファイルのに変換するときに問題が発生することもあるため、一度ガーバービューアで確認して見る必要がある。

3:ガーバーデータのリネーム

 スイッチサイエンスPCBではFusionPCBの代理店であるため、発注するにはFusionPCBのルールに基づいたファイル名に書き換え、ZIPファイルで圧縮する必要がある。ここまでで解説してきた手順に則って設計しているだけなら次の用にファイル名を変更すれば良い。変更後の拡張子を除いたファイル名は統一する。

  • 表面の銅箔: [ファイル名].gtl → [ファイル名(統一)].GTL
  • 裏面の銅箔:    [ファイル名].gbl → [ファイル名(統一)].GBL
  • 裏面のシルク: [ファイル名].gbo → [ファイル名(統一)].GBO
  • 表面のシルク: [ファイル名].gto → [ファイル名(統一)].GTO
  • 基板の外形データ: [ファイル名].gml → [ファイル名(統一)].GKO
  • ドリルのあなデータ: [ファイル名].drl → [ファイル名(統一)].TXT

 外形データはGMLでいいとスイッチサイエンスのサイトには書かれているが、サイト上のプレビューで見た場合GMLだと正しく表示されないためGKOを用いた方が良いだろう。ここれらのファイルを一つのディレクトリに入れ圧縮し”[ファイル名(統一)].zip”っと言ったように、zipファイルで圧縮する。

4:SwitchSciencePCBへの発注

 zipファイルをアップロードしSwitchScencePCBに発注をかける。SwitchSciencePCBのサイトにアクセスすると次の様なフォームが現れるので、「ファイルを選択」をクリックし先ほど圧縮したzipファイルをアップロードする。

f:id:toriten1024:20170211205531p:plain

すると次のようにプレビューが表示されるはずである。

f:id:toriten1024:20170211205646p:plain

表示されたプレビューに問題がなければページの下の方に表示されているオプションを設定する。

f:id:toriten1024:20170211205822p:plain

 オプションでは基板の枚数や色や使用するハンダについて設定することができる。特にこだわりがなければそのままの設定で良いが、モータードライバーをつくっているのであれば、銅箔厚を増やす。ロボットの基板であれば軽量化を図るために基板の厚みを減らす。製品として販売したいのであれば、表面処理を鉛フリーのハンダに変更すると言った調整できる。

 最近ではElecrowが日本語に対応するなど色々な基板製造サービスが日本語で使える様になってきているが、学校等の教育機関への納入や必要書類の用意ははSwitchScienceの得意とするところであり、卒業研究などで基板を製造する機会があれば、ぜひSwitchSciencePCBを利用してほしい。

 

マイクロマウスの基板再修正

 テストが迫っておりそんな本来余裕は無いのであるが、現実逃避の癖で以前は全くやる気の失っていたマイクロマウスの設計になぜか打ち込んでいる。あまり良い事ではないが進捗は産めてしまっている。自分のこういうところは本当に嫌になってしまう、何かを成し遂げるのに十分な集中力は持っているがそれをまともに使うことが出来ないという事が浮き彫りになってしまうからである。

 そんなこんな、で本日も何故かマイクロマウスの基板の修正を行ったり、モータードライバ周りの部品を後輩氏に発注したりと、言ったことを行っていた。前回の記事では、マイクロマウスの基板の修正を行った話をしたが、あの後他のパーツも基板上のフットプリントに実装できるか、確かめてみようと考え、マイクロマウスの基板上に実際に載せ確認していたところ、アートワークの汚さが目立ち、居ても立っていられなくなり、基板の修正を始めてしまった。

前回基板を発注した時はかなりの突貫工事であり、余りアートワークにこだわって居られなかったが、今回修正を行ったことでかなりの、非効率的で無駄に絡み合った配線をしていた事が分かった。ユニバーサル基板や、エッチングの片面基板を含めると、過去に数十枚の基板を回路CADで設計してきているのだが、やはり、配線が複雑に絡まり合う基板の様なものは時間をかけて、設計せねばならないと痛感させられた。

f:id:toriten1024:20170211034313p:plain

 Kicadの機能として作成した基板の設計データを3D化するというものがある。これは、3Dデータで基板上に部品を並べることで、部品の干渉などの問題を予め予想できるという便利な機能である。僕はすぐ調子に乗り、ケアレスミスを起こしまくるタイプの人間なのでこの機能には何回か助けられている。

 

f:id:toriten1024:20170211034306p:plain

 

以上が現在のマイクロマウスの進捗である。どうにかサークルの新入生歓迎会までに直進できるようにしたいと考えている。

 

マイクロマウスの基板修正

 なんとなくツイッターを見ていたら、某大の学生が、ロボットを作らない「ロボットを作っていた人」が本当に嫌いだと言っていた。なんとなく自分に当てはまってしまう気がする。僕は現在はサークルで水中ロボットを作っているし、マイクロマウスは完成していないだけで去年は一年間チョビチョビ作っているので、全くの「ロボットを作っていた人」なわけではないがそれでもいたわけだが一向に完成が見えてこないのと、発注した基板にバグが見つかってしまい、最近はほぼ進捗を埋めていない

というわけでその基板のバグを修正したというのが今日の作業である。具体的には電源レギュレータのICのフットプリントが間違っていたという初歩的で恥ずかしいバグではある。

 こんなことを書いていてもしょうがないので僕のマイクロマウスの基板を公開する。メインのマイクロコントローラはPSOC5でメモリはたっぷりと64kbある。ジャイロセンサはMP9250を使用する。ロータリーエンコーダはこじまうす氏のものを参考にし、自作する予定である。

 現状の進捗として基板の第一バージョンを発注し、それにバグが見つかったので修正しているのと、ギアボックスとホイールをKicadで設計し、後輩氏に頼んで加工してもらった。という状況である。

f:id:toriten1024:20170202190015p:plain

 

f:id:toriten1024:20170207233320p:plain

この回路図はツイッターでは見せびらかしているのだけども、周りのマイクロマウス参加者から見て一向にマウスを完成させない僕はどのように写っているのだろうか。

近況

 最近どんどんクズになっている気がする。というのはろくに授業に出ていないからだと思う。ろくに授業で出ていないと言っても僕が悪いわけじゃない、もともと取れる授業はほとんど取っていたのだが、大学の後期前半が終わったあたりで単位を取るのが難しいと思った科目を2つ捨てたのと、後期前半で一つ科目が終わってしまい、その結果僕の時間割はかなりスカスカになってしまっている。基本的に一日数授業しか無かったり、全休の日も発生してしまっている。更に言うと休講と授業変更は大量発生しておりかなり不規則的である。後期中盤で受講取り消ししたり、終わってしまった科目は、朝一番の1限目に集中しているから起きる時間も不規則になって、夜寝るのも遅くなったり、かなりダメ人間な生活習慣になっている。

 一応講義にはちゃんと出席しているし、講義中はノート取りながら席に座っているが、高専情報科から環境生命工学化に編入したはいいものを結局化学のことは好きにはなれなかったので半分くらいの授業はコンピュータについて、あれこれ妄想して終わっている気がする。

 前にも書いたけど今大学に編入しようとしている高専生がいるんなら願書の第二志望に大して行きたくも無い学科の名前を書くのはやめよう、他の大学や専攻科に落ち結局その学科に行くことになった場合貴重な二十代の二年間と二年分の学費をつまらないことに突っ込んでしまうことになる。こうなるくらいだったら就職したほうが絶対に良いと思う。僕の周りの大学に行かずに就職した人たちはロボコンをやっていた高専卒ということもあってか、誰もが知っている大企業の設計チームだったり、開発チームだったりで活躍している人も多いから

Scratchの仕様について

 Scratchという教育や学習様に作られたプログラミング言語がある。かく言う私も中学生の頃、Scratchが日本に来たあたりにScratchでコンピュータプログラミングを学んだ、言うなればScratch第一世代である。

 以前よりタートルだのRobo Designerだの色々な教育用プログラミング言語があったが、Scratchが今現在のプログラミング教育ムーブメントにおいて多く使われている理由はオブジェクト指向で構造化プログラミングという泥臭さだと思う。それまでの教育用プログラミング言語は僕が知っている限りフローチャートをそのまま実行する様な方式のものが多かったがScratchはそれらに比べ、実践的な文法を取っていて、c言語あたりにも少し勉強すれば容易に移行できるんじゃないとかと思う(僕の高専時代の友達はScratch風のc言語エディタを作っていたし)。

 どうでもいい前置きが長くなってしまったが、最近インタプリタとかを作っているうちにScratchのマルチパラダイムや、実行順序という物が気になって、暇を見つけてはちびちび調べていたのでそれについてここにメモしておく。

あくまでも僕個人が手探りで調べたものなので間違いがあったら教えていただけると助かります。

Scratchの1処理の実行範囲

Scratchのプログラムはマルチパラダイムであるが、実行する際はOSがひとつのCPUで複数のプログラムを動作させる様に、あるスクリプトのある区間を実行して、また別のスプライトのスクリプトのある実行区間を実行してということを繰り返している。

 具体的に言えば緑色のフラッグのStartブロックが呼び出されてプログラムが動作すると、下につながっているブロックを実行していき、描画ブロックと言った特殊なブロックを実行したら、そこでそのプログラムの実行を停止してスタンバイ状態にし、次のプログラム実行権を譲る。次に呼び出された時には特殊なブロックの下からまた実行すると言った具合である。

私が調べた結果、プログラムをスタンバイ状態に遷移させる命令は次に示す通りだ

  • {見た目ブロック、動きブロック、音ブロック、ペンブロック}を含む制御ブロックの終端

    f:id:toriten1024:20170131233931p:plain

  • クローンを呼び出した時(この時はプログラムが中断されクローン内部のプログラムを実行してから戻ってくるようだ)

多分他にもあるような気がするが僕が確認出来なのはこの2種類、赤丸で囲ったように、制御ブロックのうちスタンバイ状態に移行してしまうものは丁寧に↺マークががかいある。

Scratchのフレームレート

 Scratchは他のプログラミング言語と違いフレームという概念を気にせずプログラミングできるが、コンピュータプログラムである以上、フレームレートが存在する。スクラッチのフレームレートは30FPSで固定でフレームごとにすべてのスプライトのすべてのスクリプトがスタンバイ状態に遷移するまで実行される。また、ターボモードを使えばフレームレート関係なく最速で実行されることになる。

 次のプログラムを実行してみれば実際にフレームレートを計測することができる。おそらく結果は31になるはずだ。

f:id:toriten1024:20170201000014p:plain

 

Scratchの実行順序

 Scratchはマルチパラダイムプログラミング言語だという、僕が使ってきた言語の中でマルチパラダイムと言えそうなのはVerilogくらいしか無いのだけど、ScratchはVerilogのマルチパラダイムと違って、プログラムの呼び出されるすべて並列していたり、入り乱れたたりしない事が分かった。僕が調べて分かったのはルールと次の様な感じである。

  • あとから作られたスプライトの方が先に実行される。
  • スプライト中の同じ条件で実行されるスクリプトがある場合最後、最初に作られたスプライトの方が先に実行される

次のプログラムを見てほしい、プログラムを見ただけでは実行結果がどうなるかわからない、このような場合は最初に操作されたものから実行され、最後に操作されたものが最後に実行される。例えばそれぞれのスクリプトの上にふられた番号の通りにプログラムを作成したとすると結果は-5となる。

f:id:toriten1024:20170201001804p:plain

クローンの最大数

 Scratchにはスプライト自身がクローンを作成するという機能があるが、この複製できる最大数はすべてのスプライト合わせて301となっている。次のプログラムを実行してもらえばクローンの最大数が301である事が確認できると思う。

f:id:toriten1024:20170201002330p:plain

 

以上で今まで調べて来た仕様に関する説明を終える。間違っている部分も多いと思われるが、もし誰かの参考になるのであれば嬉しい限りである。

TOEIC

 目覚まし時計の単調なビープ音で目が覚める。うるさいので叩く様にしてけした。今日はTOEICを受けに行かねばならないのだが、開場は11:45ごろだったはずなので移動時間を2時間程度と予想するとあと1時間半程度寝られるので二度寝した。私の下宿は駅から遠く自転車で一時間程度かかってしまう、そこからまた会場の名古屋まで電車で1時間程度かかるという計算だ。別に近所の豊橋会場で受けてもいいのだけれど、理由をつけて名古屋まで出かけたかったので、毎回名古屋会場を指定して申し込んでいる。

 そこから何度か二度寝、三度寝と繰り返していると9:30あたりになっていた。適当に着替えようと思ったが、洗濯をサボっていたため、あまり洗いたての服が残っていない、仕方なく下着とズボンは洗ったものを、シャツは昨日着たものを洗濯カゴから引っ張りだしてまた着る。昨日は家でじっとしていたので、あまり汚れていないだろう。それから、必要なものを適当にトートバッグに突っ込んでマウンテンバイクに乗り駅に向かう、以前は週末になるたびに駅前に遊びに言っていたのだが、最近は飽きてしまってあまり足を運ばなくなっている。

 駅につくと腕時計を家に忘れたことに気づいた。 しょうが無いので駅ビルの中で時計が安く売っていないか探していると、運良く100円ショップが見つかった。腕時計はなかったが親指サイズの小型の置き時計を見つける事ができたのでそれを購入した。

 駅に向かい券売機で切符を購入した。名鉄を利用したかったのだが間違えてJRの切符を購入してしまった。「まあ降りるときに精算すればいいだろう」と考え、改札をくぐり名鉄のホームに向かう。すでに11時近くなってしまっていることに気づきかなり焦ったがなんとか、11:15の名古屋行きに乗車した。

 適当に席に座り先ほど買った時計の時間合わせをしようとした。スマートフォンを開き時間を確認するとすぐに電源が切れてしまった。しょうが無いので電車の発車時刻に合うように時間を合わせ、ドアが閉まった瞬間にスタートさせた。普段電車に乗る機会が無いので電車に乗るだけでも十分に楽しく感じる。何より車窓から見える景色にだんだん大きな建物が増え都会に近づいているのが見えるのが楽しかった。

 今回の名古屋会場は金山駅の近くなのでそこで降りる。駅を出て受験票の裏に描いてある地図を眺めているとそちらへ向かっていく人の流れがあったのでその後を追った。開場は東海興業専門学校という学校の裏にある施設だった。よくわからないが教室のようなものがたくさんあった。多分専門学校の一部としても使われているのだろう。

 入り口で自分の受験する部屋を確認し、部屋の前の受付で身分証明書と受験票を見せ、部屋に入った。部屋にはほとんどの受験者がすでに着席していた。適当に参考書を開いて眺めてると、試験官がいつものやたら冗長な注意書きを読み始める。証明写真付きの身分証明書と受験票を机の上に置くように言われたので、そのとおりにした。ふと横を見ると隣の受験者は大学生らしく名古屋大学の学生証を机の上にだしていた。なんだか僕の劣等感を煽り、きっとこの人は僕より全然良いスコアを取るのだろうと思うと試験を受ける前からなんかアレな気分になった。

 試験はリスニングとリーディングで構成されているが、リスニングはいつもどおりの半分しかわからない感じ、リーディングはパート7の中盤までしか終わらせることができなかった。テスト終盤には隣のやつの名古屋大学の学生書が頭の中でチラチラして集中できなくなってしまった。あまり真面目に対策せず、自分で精一杯やったと思えていいないからこうなってしまうのだろう。自分を恨むしか無い。

 院試の願書提出が6月だからあと受けることのできるTOEICは3月と4月しか無い、そんな時に真面目に取り組まないとは「全く私は何を考えているのだろう」とか思ってしまった。

つづく

 

ガバガバなステレオマッチングとか

どうも、とり天です。研究室配属ですが、なんか温室とかやってる研究室でセンサネットワークを使ったようなIoTな事ができそうなので良かったなと思います。

 最近ですがアルバイトに行き詰っています、というのはOpenCVを使ったアルバイトをしているのですが、呼び出しても動かないステレオマッチングの関数メンバがあったので、ソースコードを読んでみたところ、なんと関数内が空っぽで"return 0"になっていました。結構重要な機能だったのでショックでしたね。それと同時に自力でステレオマッチングを作ってみたので紹介します。EmacsでインデントしたあとGeditで編集してめちゃくちゃなインデントになっていますが気にしない、あとステレオ対応のWEBカメラ(ZED)とかで読み込んで分割する様に書かれてますが、ステレオカメラ持っていない人は適当に左右の視差のある画像を読み込むようにしてね。

 

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <stdexcept>
#include <opencv2/core/utility.hpp>
#include <opencv2/core.hpp>
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"

//#include <cstdlib> 

//dvide image
void ImgDiv(cv::Mat src, cv::Mat right, cv::Mat left){
  int width = src.cols/2;
  int hight = src.rows;
  for(int i = 0; i < hight; i++){
    cv::Vec3b *p_src   = src.ptr<cv::Vec3b>(i);
    cv::Vec3b *p_right = right.ptr<cv::Vec3b>(i);
    cv::Vec3b *p_left  = left.ptr<cv::Vec3b>(i);
    for(int j = 0; j < width; j++){
      p_left[j] = p_src[j];
      p_right[j] = p_src[j + width];
    }
  }
}

void Depth2Hsv(cv::Mat src, cv::Mat res){
  if(src.cols != res.cols || src.rows != res.rows){
    //cout << "data size is not mach" << endl;
    return ;
  }
  int width = src.cols;
  int hight = src.rows;
  for(int i = 0; i < hight; i++){
    cv::Vec3b *p_src = src.ptr<cv::Vec3b>(i);
    cv::Vec3b *p_res = res.ptr<cv::Vec3b>(i);
    for(int j = 0; j < width; j++){
         p_res[j][0] = p_src[j][0] / 2;
         p_res[j][1] = 255;
         p_res[j][2] = 220;

    }
  }
}
void my_sad(cv::Mat right, cv::Mat left, cv::Mat dist ,int block_size, int diff ){
  if(right.channels() != 1 || left.channels() != 1 ||  dist.channels() != 1){
    std::cout << "Error : bad channnel" << std::endl;
    return ;
  }
  if(right.cols != left.cols || right.rows != left.rows){
    std::cout << "Error : not mach input image size" << std::endl;
    return ;
  }

  if(block_size % 2 != 1  ){
    std::cout << "Error : block size is not  2n + 1 " << std::endl;
    return ;
  }

  dist = cv::Scalar(0,0,0);
  std::cout << "width" << right.cols << " height" << right.rows << std::endl;
  int width = right.cols - block_size;
  int hight = right.rows - block_size;
  cv::Mat tmp = dist.clone();

  std::vector<std::vector<int> > arr;
  arr.resize(hight);
  for( int i=0; i < hight; i++ ){
    arr[i].resize(width,255);
  }
  for(int d = 0; d < diff ; d+=1){
    for(int i = (block_size/2+ 1) ; i < hight - (block_size/2+ 1) ; i += 1){
      cv::Vec3b *p_dist   = dist.ptr<cv::Vec3b>(i);
      cv::Vec3b *p_right = right.ptr<cv::Vec3b>(i);
      cv::Vec3b *p_left  = left.ptr<cv::Vec3b>(i);

      for(int j = (block_size /2) + 1; j < width - (block_size/2+ 1) -diff ; j+= 1 ) {
	int right_sum = 0;
	int left_sum = 0;      
	for(int l = 0; l < block_size ; l++){
	  cv::Vec3b *p_right = right.ptr<cv::Vec3b>(i - (block_size/2) + l);
	  cv::Vec3b *p_left  = left.ptr<cv::Vec3b>(i - (block_size/2) + l);
	  for(int m = 0; m <   block_size; m++){
	    right_sum += p_right[j/3][ - (block_size/2) + m + j % 3];
	    left_sum += p_left[j/3][ - (block_size/2) + m + d + j % 3];
	  } 
	}
	int delta =  ( (double)abs(right_sum - left_sum) / (double)(block_size * block_size *255)) * 255.0 ;

	if(delta < arr[i][j]) {
	  arr[i][j] = delta;
	  cv::Vec3b *p_dist = dist.ptr<cv::Vec3b>(i);
	  p_dist[j/3][ j % 3] =  (int)(( (double)d / (double)diff) * 255.0);
	}
      }
    }
  }
}

int main (void){
  cv::Mat src;
  cv::VideoCapture cap(0);
  int block = 7;
  int diff = 12;

  while(1){
    cap >> src;
    cv::resize(src, src, cv::Size(), 0.5, 0.5);
    cv::Mat right(src.rows, src.cols*0.5,src.type());
    cv::Mat left(src.rows, src.cols*0.5,src.type());
    ImgDiv(src,right,left);
    cv::cvtColor(right, right, CV_RGB2GRAY);
    cv::cvtColor(left, left, CV_RGB2GRAY);
    cv::Mat dist = right.clone();
     my_sad( right, left, dist , block, diff );
     cv::cvtColor(dist, dist, CV_GRAY2RGB);
     cv::Mat color(dist.rows, dist.cols, CV_8UC3);
     Depth2Hsv(dist, color);
     cv::cvtColor(color, color, CV_HSV2RGB);

     cv::imshow("window_r", right);
     cv::imshow("window_l", left);
     cv::imshow("window_d", color);
     
     cv::createTrackbar("block size","window_d",&block, 13,NULL,NULL);
     block = (block < 3  )? block = 3 : (block %2 != 1)? block - 1 : block;
     cv::createTrackbar("diffarence","window_d",&diff, 255,NULL,NULL); 
    int key = cv::waitKey(1);
    if(key == 113)//q
      {
	break;//
      }
    else if(key == 115)//s
      {
	cv::imwrite("img.png",dist );
      }
  }
}

まあアルゴリズムとしてはSADを用いたブロックマッチングを行っています。すごく適当な上に並列化もなにもしていないので、すごく重いです。

結果は次の画像に示す感じです。近いものほど赤く表示して、遠くのものほど青く表示しています。なんかキャリブレーションすら面倒くさくてしていませんがそれなりに遠くのものは遠くに、近くのものは近くと認識できているんじゃないかなぁ。部屋汚いね

左の画像

f:id:toriten1024:20170128205303p:plain

右の画像f:id:toriten1024:20170128205241p:plain

深度マップ

f:id:toriten1024:20170128205444p:plain

 

まあ詳しい話とかは今度の技術書展で豊橋技科大コンピュータクラブの出す部誌に載せようと思うので、そのあとブログにも簡単に載せようかな