whoopsidaisies's diary 2019-12-18T19:00:34+09:00 whoopsidaisies Hatena::Blog hatenablog://blog/6435988827676239766 Detectron2のModel Zooで物体検出、インスタンスセグメンテーション、姿勢推定 hatenablog://entry/26006613486122887 2019-12-18T19:00:34+09:00 2019-12-18T19:00:34+09:00 概要 Detectron2のModel Zooにある訓練済みを使って、物体検出やインスタンスセグメンテーション、姿勢推定等を行う。 多くのモデルに対して一括で処理できるコードを作った。便利。 Detectron2 FacebookのAI研究グループ(FAIR)が開発している物体検出アルゴリズムを実装のためのソフトウェア。 環境 ubuntu 18.04 GeForce GTX TITAN X インストール 詳細は省略。ほぼ公式の通りやった。Windowsでやろうとしたら公式対応してないから大変そうな雰囲気。 メモ代わりに大雑把な手順を載せるが公式を読んでやったほうがいい。 OS、cuda等:d… <h1>概要</h1> <p>Detectron2のModel Zooにある訓練済みを使って、物体検出や<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A4%A5%F3%A5%B9%A5%BF%A5%F3%A5%B9">インスタンス</a>セグメンテーション、姿勢推定等を行う。 多くのモデルに対して一括で処理できるコードを作った。便利。</p> <h1><a href="https://github.com/facebookresearch/detectron2">Detectron2</a></h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Facebook">Facebook</a>のAI研究グループ(FAIR)が開発している物体検出<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>を実装のためのソフトウェア。</p> <h1>環境</h1> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/ubuntu">ubuntu</a> 18.04</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/GeForce%20GTX">GeForce GTX</a> TITAN X</li> </ul> <h1>インストール</h1> <p>詳細は省略。ほぼ公式の通りやった。<a class="keyword" href="http://d.hatena.ne.jp/keyword/Windows">Windows</a>でやろうとしたら公式対応してないから大変そうな雰囲気。</p> <p>メモ代わりに大雑把な手順を載せるが公式を読んでやったほうがいい。</p> <ul> <li>OS、cuda等:dockerコンテナ利用 <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/nvidia">nvidia</a>/cuda:10.1-cudnn7-devel</li> </ul> </li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a>環境 <ul> <li>Anaconda 2019.10でpython3.7環境構築</li> </ul> </li> <li>pytorch <ul> <li><code>conda install pytorch torchvision cudatoolkit=10.1 -c pytorch</code></li> </ul> </li> <li><p>detectron2</p> <pre><code> git clone https://github.com/facebookresearch/detectron2.git cd detectron2 python setup.py build develop </code></pre></li> </ul> <h1><a href="https://github.com/facebookresearch/detectron2/blob/master/MODEL_ZOO.md">Detectron2 Model Zoo</a></h1> <p>学習済みのモデルが置いてある。 以下のようなものがあるが、詳細は<a href="https://github.com/facebookresearch/detectron2/blob/master/MODEL_ZOO.md">ウェブサイト</a>参照。</p> <ul> <li>タスク <ul> <li>COCO Object Detection</li> <li>COCO Instance Segmentation</li> <li>COCO Person Keypoint Detection</li> <li>COCO Panoptic Segmentation</li> <li>LVIS Instance Segmentation</li> <li>Cityscapes</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/Pascal">Pascal</a> VOC</li> </ul> </li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a> <ul> <li>Faster R-CNN、RetinaNet、Mask R-CNN、<a class="keyword" href="http://d.hatena.ne.jp/keyword/Cascade">Cascade</a> R-CNN等</li> <li>backbone: <a class="keyword" href="http://d.hatena.ne.jp/keyword/FPN">FPN</a>、ResNetベースのもの</li> </ul> </li> </ul> <h1>確認用コード</h1> <p>Model Zooにある学習済みモデルをロードするモジュールと、予測して可視化するためのモジュールがあったのでそれを使った。</p> <p>以下のコードを実行するとModel Zooにあるモデルの42個について予測を行える。</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">from</span> detectron2.data.detection_utils <span class="synPreProc">import</span> read_image <span class="synPreProc">from</span> detectron2.model_zoo.model_zoo <span class="synPreProc">import</span> ModelZooUrls <span class="synPreProc">from</span> detectron2.config <span class="synPreProc">import</span> get_cfg <span class="synPreProc">from</span> demo.predictor <span class="synPreProc">import</span> VisualizationDemo img_path = <span class="synConstant">'input.jpg'</span> img = read_image(img_path, <span class="synIdentifier">format</span>=<span class="synConstant">&quot;BGR&quot;</span>) <span class="synStatement">for</span> i, config_path <span class="synStatement">in</span> <span class="synIdentifier">enumerate</span>(ModelZooUrls.CONFIG_PATH_TO_URL_SUFFIX.keys()): <span class="synComment"># rpnとfast_rcnnは可視化対応していないので飛ばす</span> <span class="synStatement">if</span> <span class="synConstant">'rpn'</span> <span class="synStatement">in</span> config_path <span class="synStatement">or</span> <span class="synConstant">'fast_rcnn'</span> <span class="synStatement">in</span> config_path: <span class="synStatement">continue</span> <span class="synComment"># config設定</span> cfg = get_cfg() cfg.merge_from_file(f<span class="synConstant">'configs/{config_path}'</span>) cfg.MODEL.WEIGHTS = ModelZooUrls.get(config_path) score_thresh = <span class="synConstant">0.5</span> cfg.MODEL.RETINANET.SCORE_THRESH_TEST = score_thresh cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = score_thresh cfg.MODEL.PANOPTIC_FPN.COMBINE.INSTANCES_CONFIDENCE_THRESH = score_thresh cfg.freeze() <span class="synComment"># 検出&可視化</span> demo = VisualizationDemo(cfg) predictions, visualized_output = demo.run_on_image(img) <span class="synComment"># ファイル出力</span> dataset_name, algorithm = config_path.split(<span class="synConstant">&quot;/&quot;</span>) algorithm = algorithm.split(<span class="synConstant">'.'</span>)[<span class="synConstant">0</span>] visualized_output.save(f<span class="synConstant">'out/{i:02d}-{dataset_name}-{algorithm}.jpg'</span>) </pre> <h1>結果</h1> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181902.jpg" alt="f:id:whoopsidaisies:20191218181902j:plain" title="f:id:whoopsidaisies:20191218181902j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181904.jpg" alt="f:id:whoopsidaisies:20191218181904j:plain" title="f:id:whoopsidaisies:20191218181904j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181907.jpg" alt="f:id:whoopsidaisies:20191218181907j:plain" title="f:id:whoopsidaisies:20191218181907j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181911.jpg" alt="f:id:whoopsidaisies:20191218181911j:plain" title="f:id:whoopsidaisies:20191218181911j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181914.jpg" alt="f:id:whoopsidaisies:20191218181914j:plain" title="f:id:whoopsidaisies:20191218181914j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181916.jpg" alt="f:id:whoopsidaisies:20191218181916j:plain" title="f:id:whoopsidaisies:20191218181916j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181921.jpg" alt="f:id:whoopsidaisies:20191218181921j:plain" title="f:id:whoopsidaisies:20191218181921j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181926.jpg" alt="f:id:whoopsidaisies:20191218181926j:plain" title="f:id:whoopsidaisies:20191218181926j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181930.jpg" alt="f:id:whoopsidaisies:20191218181930j:plain" title="f:id:whoopsidaisies:20191218181930j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181932.jpg" alt="f:id:whoopsidaisies:20191218181932j:plain" title="f:id:whoopsidaisies:20191218181932j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181935.jpg" alt="f:id:whoopsidaisies:20191218181935j:plain" title="f:id:whoopsidaisies:20191218181935j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181937.jpg" alt="f:id:whoopsidaisies:20191218181937j:plain" title="f:id:whoopsidaisies:20191218181937j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181940.jpg" alt="f:id:whoopsidaisies:20191218181940j:plain" title="f:id:whoopsidaisies:20191218181940j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181943.jpg" alt="f:id:whoopsidaisies:20191218181943j:plain" title="f:id:whoopsidaisies:20191218181943j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181945.jpg" alt="f:id:whoopsidaisies:20191218181945j:plain" title="f:id:whoopsidaisies:20191218181945j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181947.jpg" alt="f:id:whoopsidaisies:20191218181947j:plain" title="f:id:whoopsidaisies:20191218181947j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181950.jpg" alt="f:id:whoopsidaisies:20191218181950j:plain" title="f:id:whoopsidaisies:20191218181950j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181953.jpg" alt="f:id:whoopsidaisies:20191218181953j:plain" title="f:id:whoopsidaisies:20191218181953j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181956.jpg" alt="f:id:whoopsidaisies:20191218181956j:plain" title="f:id:whoopsidaisies:20191218181956j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181959.jpg" alt="f:id:whoopsidaisies:20191218181959j:plain" title="f:id:whoopsidaisies:20191218181959j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182001.jpg" alt="f:id:whoopsidaisies:20191218182001j:plain" title="f:id:whoopsidaisies:20191218182001j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182004.jpg" alt="f:id:whoopsidaisies:20191218182004j:plain" title="f:id:whoopsidaisies:20191218182004j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182007.jpg" alt="f:id:whoopsidaisies:20191218182007j:plain" title="f:id:whoopsidaisies:20191218182007j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182010.jpg" alt="f:id:whoopsidaisies:20191218182010j:plain" title="f:id:whoopsidaisies:20191218182010j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182013.jpg" alt="f:id:whoopsidaisies:20191218182013j:plain" title="f:id:whoopsidaisies:20191218182013j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182016.jpg" alt="f:id:whoopsidaisies:20191218182016j:plain" title="f:id:whoopsidaisies:20191218182016j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182020.jpg" alt="f:id:whoopsidaisies:20191218182020j:plain" title="f:id:whoopsidaisies:20191218182020j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182023.jpg" alt="f:id:whoopsidaisies:20191218182023j:plain" title="f:id:whoopsidaisies:20191218182023j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182026.jpg" alt="f:id:whoopsidaisies:20191218182026j:plain" title="f:id:whoopsidaisies:20191218182026j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182029.jpg" alt="f:id:whoopsidaisies:20191218182029j:plain" title="f:id:whoopsidaisies:20191218182029j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182031.jpg" alt="f:id:whoopsidaisies:20191218182031j:plain" title="f:id:whoopsidaisies:20191218182031j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182035.jpg" alt="f:id:whoopsidaisies:20191218182035j:plain" title="f:id:whoopsidaisies:20191218182035j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182039.jpg" alt="f:id:whoopsidaisies:20191218182039j:plain" title="f:id:whoopsidaisies:20191218182039j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182041.jpg" alt="f:id:whoopsidaisies:20191218182041j:plain" title="f:id:whoopsidaisies:20191218182041j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182044.jpg" alt="f:id:whoopsidaisies:20191218182044j:plain" title="f:id:whoopsidaisies:20191218182044j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182047.jpg" alt="f:id:whoopsidaisies:20191218182047j:plain" title="f:id:whoopsidaisies:20191218182047j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182051.jpg" alt="f:id:whoopsidaisies:20191218182051j:plain" title="f:id:whoopsidaisies:20191218182051j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182055.jpg" alt="f:id:whoopsidaisies:20191218182055j:plain" title="f:id:whoopsidaisies:20191218182055j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182059.jpg" alt="f:id:whoopsidaisies:20191218182059j:plain" title="f:id:whoopsidaisies:20191218182059j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182101.jpg" alt="f:id:whoopsidaisies:20191218182101j:plain" title="f:id:whoopsidaisies:20191218182101j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <div class="images-row mceNonEditable"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182104.jpg" alt="f:id:whoopsidaisies:20191218182104j:plain" title="f:id:whoopsidaisies:20191218182104j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218182107.jpg" alt="f:id:whoopsidaisies:20191218182107j:plain" title="f:id:whoopsidaisies:20191218182107j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181911.jpg" alt="f:id:whoopsidaisies:20191218181911j:plain" title="f:id:whoopsidaisies:20191218181911j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20191218/20191218181907.jpg" alt="f:id:whoopsidaisies:20191218181907j:plain" title="f:id:whoopsidaisies:20191218181907j:plain" class="hatena-fotolife" itemprop="image"></span> </div> <p><div class="images-row mceNonEditable"></p> whoopsidaisies denseposeでU.S.A. hatenablog://entry/10257846132679628996 2018-12-03T19:37:59+09:00 2018-12-03T19:37:59+09:00 youtu.be 完全に出遅れたけど、DensePose使ってみたのでメモ。 Facebook等が発表した、2次元画像から人体の3Dサーフェスモデルを推定しちゃうすごい手法。 詳細とか使い方は下記のページあたりを参照。 shiropen.com github.com 環境 ubuntu 16.04 nvidia-docker導入済み(nvidia-dockerインストール、コンテナ等メモ - whoopsidaisies's diary) 導入 偉い人がdockerhubでイメージ公開してくれていたので活用。 動画ファイルをffmpegとかで画像にばらしておいた。 # ubuntu 16.04… <p><iframe width="480" height="270" src="https://www.youtube.com/embed/RONOvSMnlV0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://youtu.be/RONOvSMnlV0">youtu.be</a></cite></p> <p>完全に出遅れたけど、<a href="https://qiita.com/syoyo/items/e9193d18b0970950b9c6:embed">DensePose</a>使ってみたのでメモ。 <a class="keyword" href="http://d.hatena.ne.jp/keyword/Facebook">Facebook</a>等が発表した、2次元画像から人体の3D<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B5%A1%BC%A5%D5%A5%A7%A5%B9">サーフェス</a>モデルを推定しちゃうすごい手法。</p> <p>詳細とか使い方は下記のページあたりを参照。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fshiropen.com%2Fseamless%2Ffacebook-ai-densepose" title="Facebookら、2Dの群衆動画から人間の姿勢を推定し、身体のテクチャも貼ってくれるCNNを用いたシステム「DensePose」オープンソース発表" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://shiropen.com/seamless/facebook-ai-densepose">shiropen.com</a></cite> <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Ffacebookresearch%2FDensePose" title="facebookresearch/DensePose" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/facebookresearch/DensePose">github.com</a></cite></p> <h1>環境</h1> <ul> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/ubuntu">ubuntu</a> 16.04</li> <li><a class="keyword" href="http://d.hatena.ne.jp/keyword/nvidia">nvidia</a>-docker導入済み(<a href="http://whoopsidaisies.hatenablog.com/entry/2017/01/22/190618">nvidia-docker&#x30A4;&#x30F3;&#x30B9;&#x30C8;&#x30FC;&#x30EB;&#x3001;&#x30B3;&#x30F3;&#x30C6;&#x30CA;&#x7B49;&#x30E1;&#x30E2; - whoopsidaisies&#39;s diary</a>)</li> </ul> <h1>導入</h1> <p>偉い人が<a href="https://hub.docker.com/r/garyfeng/densepose/">dockerhubでイメージ公開</a>してくれていたので活用。 動画ファイルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/ffmpeg">ffmpeg</a>とかで画像にばらしておいた。</p> <pre class="code" data-lang="" data-unlink># ubuntu 16.04の端末で nvidia-docker run -it -d --name densepose garyfeng/densepose docker exec -it densepose bash # コンテナ内 # 実行時の引数でフォルダを指定するとフォルダ内の画像を一気に処理してくれる tools/infer_simple.py \ --cfg configs/DensePose_ResNet101_FPN_s1x-e2e.yaml \ --output-dir /root/data/infer_out/ \ --image-ext png \ --wts https://s3.amazonaws.com/densepose/DensePose_ResNet101_FPN_s1x-e2e.pkl \ /root/data/frame</pre> <p>以上、簡単にできてすごい。</p> whoopsidaisies OpenCV 3.4.1で背景差分 hatenablog://entry/17391345971620851816 2018-03-01T13:00:00+09:00 2018-03-01T13:31:22+09:00 OpenCV 3.4.1により背景差分のアルゴリズム7種類を比較。Google Summer of Code 2017で生まれたアルゴリズムの結果がきれいだった。C++、Pythonのサンプルコードあり。 <h1>背景差分</h1> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20180301/20180301131807.png" alt="f:id:whoopsidaisies:20180301131807p:plain" title="f:id:whoopsidaisies:20180301131807p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>画像の前景と背景を分離する手法。2013年に<a href="http://whoopsidaisies.hatenablog.com/entry/2013/12/18/092142">OpenCV 2.4.7での背景差分の記事</a>を書いたが、2018年になったいま<a class="keyword" href="http://d.hatena.ne.jp/keyword/OpenCV">OpenCV</a> 3.4.1で背景差分を行おうとしたら使える<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>が増えていたのでまとめておく。</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a></h1> <h2>MOG, MOG2, GMG</h2> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/OpenCV">OpenCV</a> 2.4.7でも使えた。以下のページに日本語でわかりやすい説明がある。</p> <p><a href="http://lang.sist.chukyo-u.ac.jp/classes/OpenCV/py_tutorials/py_video/py_bg_subtraction/py_bg_subtraction.html">&#x80CC;&#x666F;&#x5DEE;&#x5206; &mdash; OpenCV-Python Tutorials</a></p> <h2>KNN</h2> <p>K近傍方に基づく背景差分。前景の画<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C1%C7%BF%F4">素数</a>が少ない場合は効率が良いらしい。</p> <p><a href="https://www.sciencedirect.com/science/article/pii/S0167865505003521">Efficient adaptive density estimation per image pixel for the task of background subtraction - ScienceDirect</a></p> <h2>CNT</h2> <p>低スペックな計算機でもほかの<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>より高速に処理ができる。CNTという名前は「CouNT」の省略らしい。Raspberry Pi3での<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D9%A5%F3%A5%C1%A5%DE%A1%BC%A5%AF">ベンチマーク</a>ではMOG2が41秒に対し、CNTは18秒。</p> <p><a href="https://sagi-z.github.io/BackgroundSubtractorCNT/">https://sagi-z.github.io/BackgroundSubtractorCNT/</a></p> <h2>LSBP</h2> <p>Local <a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a> Binary Pattern。注目画素とその周辺画素の大小関係を符号化するLBP(Local Binary Pattern)は、高速に計算可能な画像特徴量として知られている。局所的なノイズや隣接画素が類似しているような場合にも<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%ED%A5%D0%A5%B9%A5%C8">ロバスト</a>にするようにSVD(<a class="keyword" href="http://d.hatena.ne.jp/keyword/%C6%C3%B0%DB%C3%CD%CA%AC%B2%F2">特異値分解</a>)を使った特徴量で背景差分を行っているそう。<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A4%C1%A4%E3%A4%F3">ちゃん</a>と勉強してないのでよくわらからない。</p> <p><a href="https://www.cv-foundation.org/openaccess/content_cvpr_2016_workshops/w24/papers/Guo_Background_Subtraction_Using_CVPR_2016_paper.pdf">https://www.cv-foundation.org/openaccess/content_cvpr_2016_workshops/w24/papers/Guo_Background_Subtraction_Using_CVPR_2016_paper.pdf</a></p> <h2>GSOC</h2> <p>LSBP特徴を使ってる。ノイズ除去とか穴埋めといった後処理をしているらしい。GSOC(<a class="keyword" href="http://d.hatena.ne.jp/keyword/Google">Google</a> <a class="keyword" href="http://d.hatena.ne.jp/keyword/Summer%20of%20Code">Summer of Code</a>)2017中で開発されたとかで元論文等はないらしいので<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>を読もう。</p> <p><a href="https://github.com/opencv/opencv_contrib/blob/6520dbaa224a661ca8105b1ab0b71451fd715f4c/modules/bgsegm/src/bgfg_gsoc.cpp">opencv_contrib/bgfg_gsoc.cpp at 6520dbaa224a661ca8105b1ab0b71451fd715f4c &middot; opencv/opencv_contrib &middot; GitHub</a></p> <h1>コード</h1> <p>実行には<a href="https://github.com/opencv/opencv_contrib">opencv_contrib</a>が必要。</p> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/C%2B%2B">C++</a></h2> <p><code>opencv_contrib</code>をダウンロードし、<code>opencv</code>の<code>cmake</code>時に例えば以下のように<code>OPENCV_EXTRA_MODULES_PATH</code>オプションを指定してビルドする。</p> <pre class="code" data-lang="" data-unlink>$ cmake -DOPENCV_EXTRA_MODULES_PATH=&lt;opencv_contrib&gt;/modules -DBUILD_opencv_legacy=OFF &lt;opencv_source_directory&gt;</pre> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a></h4> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/opencv.hpp&gt;</span> <span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/core/utility.hpp&gt;</span> <span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/bgsegm.hpp&gt;</span> <span class="synType">int</span> main() { <span class="synComment">// 動画ファイルの読み込み</span> cv::VideoCapture cap = cv::VideoCapture(<span class="synConstant">&quot;video.mp4&quot;</span>); <span class="synComment">// 背景差分器の生成</span> cv::Ptr&lt;cv::BackgroundSubtractor&gt; bgfs = cv::bgsegm::createBackgroundSubtractorGSOC(); <span class="synComment">//cv::Ptr&lt;cv::BackgroundSubtractor&gt; bgfs = cv::bgsegm::createBackgroundSubtractorCNT();</span> <span class="synComment">//cv::Ptr&lt;cv::BackgroundSubtractor&gt; bgfs = cv::bgsegm::createBackgroundSubtractorGMG();</span> <span class="synComment">//cv::Ptr&lt;cv::BackgroundSubtractor&gt; bgfs = cv::bgsegm::createBackgroundSubtractorLSBP();</span> <span class="synComment">//cv::Ptr&lt;cv::BackgroundSubtractor&gt; bgfs = cv::bgsegm::createBackgroundSubtractorMOG();</span> <span class="synComment">//cv::Ptr&lt;cv::BackgroundSubtractor&gt; bgfs = cv::createBackgroundSubtractorMOG2();</span> <span class="synComment">//cv::Ptr&lt;cv::BackgroundSubtractor&gt; bgfs = cv::createBackgroundSubtractorKNN();</span> <span class="synStatement">while</span> (cv::waitKey(<span class="synConstant">1</span>) == -<span class="synConstant">1</span>) { cv::Mat frame, foreGroundMask, segm; cap &gt;&gt; frame; <span class="synStatement">if</span> (frame.empty()) <span class="synStatement">break</span>; bgfs-&gt;apply(frame, foreGroundMask); frame.convertTo(segm, <span class="synConstant">0</span>, <span class="synConstant">0.5</span>); cv::add(frame, cv::Scalar(<span class="synConstant">100</span>, <span class="synConstant">100</span>, <span class="synConstant">0</span>), segm, foreGroundMask); cv::imshow(<span class="synConstant">&quot;output&quot;</span>, segm); } <span class="synStatement">return</span> <span class="synConstant">0</span>; } </pre> <h2><a class="keyword" href="http://d.hatena.ne.jp/keyword/Python">Python</a></h2> <p><code>pip</code>で管理している場合、以下のように<code>opencv-python</code>をアンインストール後に<code>opencv-contrib-python</code>をインストールすれば<code>opencv_contrib</code>が使える。</p> <pre class="code" data-lang="" data-unlink>pip uninstall opencv-python pip install opencv-contrib-python</pre> <h4><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a></h4> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> cv2 cap = cv2.VideoCapture(<span class="synConstant">'video.mp4'</span>) bgs = cv2.bgsegm.createBackgroundSubtractorLSBP() <span class="synStatement">while</span>(cap.isOpened()): ret, frame = cap.read() mask = bgs.<span class="synIdentifier">apply</span>(frame) bg = bgs.getBackgroundImage() cv2.imshow(<span class="synConstant">'mask'</span>, mask) cv2.imshow(<span class="synConstant">'bg'</span>, bg) <span class="synStatement">if</span> cv2.waitKey(<span class="synConstant">1</span>) != -<span class="synConstant">1</span>: <span class="synStatement">break</span> cap.release() cv2.destroyAllWindows() </pre> <h1>適用結果</h1> <p>比較のために各<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>を並べてみた。パラメータ調整もしてないから比較もくそもない気はするけど。GSOCが綺麗。LSBPはあんまり</p> <p><iframe width="459" height="344" src="https://www.youtube.com/embed/EILZ4YsI6rU?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=EILZ4YsI6rU">www.youtube.com</a></cite></p> <p>あと、背景差分やるだけだったらたぶん以下のページで紹介されている<a href="https://github.com/andrewssobral/bgslibrary">BGSLibrary</a>を使ったほうが良さそうではある。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fblog.negativemind.com%2F2017%2F07%2F12%2Fbgslibrary%2F" title="OpenCVベースの背景差分ライブラリ『BGSLibrary』" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://blog.negativemind.com/2017/07/12/bgslibrary/">blog.negativemind.com</a></cite></p> whoopsidaisies tensorflowでMASK R-CNNによるSemantic Segmentation hatenablog://entry/17391345971620252496 2018-02-27T18:44:48+09:00 2018-02-27T18:44:48+09:00 TensorFlow Object Detection APIを用いてMask R-CNNによる画像のセマンティックセグメンテーションを行った。 <h1>セマンティックセグメンテーション</h1> <p>下の写真みたいに、入力画像を物体ごとに領域分割する技術。</p> <blockquote><p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20180227/20180227180905.png" alt="f:id:whoopsidaisies:20180227180905p:plain" title="f:id:whoopsidaisies:20180227180905p:plain" class="hatena-fotolife" itemprop="image"></span> <a href="https://wiki.tum.de/display/lfdv/Image+Semantic+Segmentation">https://wiki.tum.de/display/lfdv/Image+Semantic+Segmentation</a></p></blockquote> <h1>Mask R-CNN</h1> <p>数あるセマンティックセグメンテーションを実現する手法の中で、2018年2月現在有力とされているものの一つ(たぶん)。</p> <p><iframe width="480" height="270" src="https://www.youtube.com/embed/OOT3UIXZztE?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=OOT3UIXZztE">www.youtube.com</a></cite></p> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A5%EB%A5%B4%A5%EA%A5%BA%A5%E0">アルゴリズム</a>の詳細についての説明は他に譲る。以下のページとかを参考にする。</p> <ul> <li><a href="https://arxiv.org/pdf/1703.06870.pdf">https://arxiv.org/pdf/1703.06870.pdf</a></li> <li><a href="http://kaiminghe.com/iccv17tutorial/maskrcnn_iccv2017_tutorial_kaiminghe.pdf">http://kaiminghe.com/iccv17tutorial/maskrcnn_iccv2017_tutorial_kaiminghe.pdf</a></li> <li><a href="http://deeplearning.csail.mit.edu/instance_ross.pdf">http://deeplearning.csail.mit.edu/instance_ross.pdf</a></li> </ul> <h1>TensorFlowのインストール</h1> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Google%C0%E8%C0%B8">Google先生</a>が公開している<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%A1%B3%A3%B3%D8%BD%AC">機械学習</a>用<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AA%A1%BC%A5%D7%A5%F3%A5%BD%A1%BC%A5%B9">オープンソース</a>ライブラリ。インストール方法は巷にあふれているので適当にググってインストールする。</p> <h1>Tensorflow Object Detection <a class="keyword" href="http://d.hatena.ne.jp/keyword/API">API</a>のインストール</h1> <p>以下の<a class="keyword" href="http://d.hatena.ne.jp/keyword/GitHub">GitHub</a>のレポジトリで様々なTensorfFlowのモデルが公開されている。公式サポートではないが物体検出とセマンティックセグメンテーションのモデルも数多く公開されているので、今回はそれを使う。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Ftensorflow%2Fmodels" title="tensorflow/models" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://github.com/tensorflow/models">github.com</a></cite></p> <p>インストールは公式の手順通りだが以下に適当にメモ。 <a href="https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md">models/installation.md at master &middot; tensorflow/models &middot; GitHub</a></p> <ul> <li>依存パッケージのインストール</li> </ul> <pre class="code" data-lang="" data-unlink>apt install protobuf-compiler pip install pillow lxml jupyter matplotlib</pre> <ul> <li>Protobufファイルを<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%D1%A5%A4%A5%EB">コンパイル</a></li> </ul> <pre class="code" data-lang="" data-unlink>cd [PATH to models]/research protoc object_detection/protos/*.proto --python_out=.</pre> <ul> <li>PYTHONPATHの追加</li> </ul> <pre class="code" data-lang="" data-unlink>cd [PATH to models]/research export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim</pre> <h1>モデルファイルのダウンロード</h1> <p><a href="https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md">Tensorflow detection model zoo</a>から物体検出やセマンティックセグメンテーションのトレーニング済みモデルをダウンロード出来る。とりあえず一番mAPの高い<a href="http://download.tensorflow.org/models/object_detection/mask_rcnn_inception_resnet_v2_atrous_coco_2018_01_28.tar.gz">mask_rcnn_inception_resnet_v2_atrous_coco</a>というモデルを使う。</p> <pre class="code" data-lang="" data-unlink>wget http://download.tensorflow.org/models/object_detection/mask_rcnn_inception_resnet_v2_atrous_coco_2018_01_28.tar.gz tar -zxvf mask_rcnn_inception_resnet_v2_atrous_coco_2018_01_28.tar.gz</pre> <h1>セマンティックセグメンテーションの<a class="keyword" href="http://d.hatena.ne.jp/keyword/python">python</a>コード</h1> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> tensorflow <span class="synStatement">as</span> tf <span class="synPreProc">import</span> numpy <span class="synStatement">as</span> np <span class="synPreProc">from</span> PIL <span class="synPreProc">import</span> Image <span class="synPreProc">from</span> object_detection.utils <span class="synPreProc">import</span> ops <span class="synStatement">as</span> utils_ops <span class="synPreProc">import</span> sys sys.path.append(<span class="synConstant">'[modelsのパス]/research/object_detection'</span>) <span class="synPreProc">from</span> utils <span class="synPreProc">import</span> label_map_util <span class="synPreProc">from</span> utils <span class="synPreProc">import</span> visualization_utils <span class="synStatement">as</span> vis_util <span class="synComment"># 学習済モデルの読み込み</span> PATH_TO_CKPT = <span class="synConstant">'mask_rcnn_inception_resnet_v2_atrous_coco_2018_01_28/frozen_inference_graph.pb'</span> detection_graph = tf.Graph() <span class="synStatement">with</span> detection_graph.as_default(): od_graph_def = tf.GraphDef() <span class="synStatement">with</span> tf.gfile.GFile(PATH_TO_CKPT, <span class="synConstant">'rb'</span>) <span class="synStatement">as</span> fid: serialized_graph = fid.read() od_graph_def.ParseFromString(serialized_graph) tf.import_graph_def(od_graph_def, name=<span class="synConstant">''</span>) <span class="synComment"># ラベルの読み込み</span> PATH_TO_LABELS = <span class="synConstant">'[modelsへのパス]/research/object_detection/data/mscoco_label_map.pbtxt'</span> NUM_CLASSES = <span class="synConstant">90</span> label_map = label_map_util.load_labelmap(PATH_TO_LABELS) categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=<span class="synIdentifier">True</span>) category_index = label_map_util.create_category_index(categories) <span class="synComment"># 画像の読み込みとnumpy配列への変換</span> <span class="synStatement">def</span> <span class="synIdentifier">load_image_into_numpy_array</span>(image): (im_width, im_height) = image.size <span class="synStatement">return</span> np.array(image.getdata()).reshape( (im_height, im_width, <span class="synConstant">3</span>)).astype(np.uint8) filename = <span class="synConstant">'[画像ファイルのパス]'</span> image = Image.<span class="synIdentifier">open</span>(filename) image_np = load_image_into_numpy_array(image) <span class="synComment"># セマンティックセグメンテーションの処理</span> <span class="synStatement">with</span> detection_graph.as_default(): <span class="synStatement">with</span> tf.Session() <span class="synStatement">as</span> sess: <span class="synComment"># 入出力用テンソルのハンドルを取得</span> image_tensor = tf.get_default_graph().get_tensor_by_name(<span class="synConstant">'image_tensor:0'</span>) tensor_dict = {} tensor_dict[<span class="synConstant">'num_detections'</span>] = tf.get_default_graph().get_tensor_by_name(<span class="synConstant">'num_detections:0'</span>) tensor_dict[<span class="synConstant">'detection_boxes'</span>] = tf.get_default_graph().get_tensor_by_name(<span class="synConstant">'detection_boxes:0'</span>) tensor_dict[<span class="synConstant">'detection_scores'</span>] = tf.get_default_graph().get_tensor_by_name(<span class="synConstant">'detection_scores:0'</span>) tensor_dict[<span class="synConstant">'detection_classes'</span>] = tf.get_default_graph().get_tensor_by_name(<span class="synConstant">'detection_classes:0'</span>) tensor_dict[<span class="synConstant">'detection_masks'</span>] = tf.get_default_graph().get_tensor_by_name(<span class="synConstant">'detection_masks:0'</span>) <span class="synComment"># バッチ内の最初の画像の結果を取り出す</span> detection_boxes = tf.squeeze(tensor_dict[<span class="synConstant">'detection_boxes'</span>], [<span class="synConstant">0</span>]) detection_masks = tf.squeeze(tensor_dict[<span class="synConstant">'detection_masks'</span>], [<span class="synConstant">0</span>]) <span class="synComment"># 各検出ボックスのマスクを画像全体上のマスクへ変換</span> real_num_detection = tf.cast(tensor_dict[<span class="synConstant">'num_detections'</span>][<span class="synConstant">0</span>], tf.int32) detection_boxes = tf.<span class="synIdentifier">slice</span>(detection_boxes, [<span class="synConstant">0</span>, <span class="synConstant">0</span>], [real_num_detection, -<span class="synConstant">1</span>]) detection_masks = tf.<span class="synIdentifier">slice</span>(detection_masks, [<span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>], [real_num_detection, -<span class="synConstant">1</span>, -<span class="synConstant">1</span>]) detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks( detection_masks, detection_boxes, image_np.shape[<span class="synConstant">0</span>], image_np.shape[<span class="synConstant">1</span>]) detection_masks_reframed = tf.cast( tf.greater(detection_masks_reframed, <span class="synConstant">0.5</span>), tf.uint8) <span class="synComment"># バッチ分の次元を追加</span> tensor_dict[<span class="synConstant">'detection_masks'</span>] = tf.expand_dims( detection_masks_reframed, <span class="synConstant">0</span>) <span class="synComment"># 実行</span> output_dict = sess.run(tensor_dict, feed_dict={image_tensor: np.expand_dims(image_np, <span class="synConstant">0</span>)}) <span class="synComment"># バッチ分の次元の削除と型変換</span> output_dict[<span class="synConstant">'num_detections'</span>] = <span class="synIdentifier">int</span>(output_dict[<span class="synConstant">'num_detections'</span>][<span class="synConstant">0</span>]) output_dict[<span class="synConstant">'detection_classes'</span>] = output_dict[ <span class="synConstant">'detection_classes'</span>][<span class="synConstant">0</span>].astype(np.uint8) output_dict[<span class="synConstant">'detection_boxes'</span>] = output_dict[<span class="synConstant">'detection_boxes'</span>][<span class="synConstant">0</span>] output_dict[<span class="synConstant">'detection_scores'</span>] = output_dict[<span class="synConstant">'detection_scores'</span>][<span class="synConstant">0</span>] output_dict[<span class="synConstant">'detection_masks'</span>] = output_dict[<span class="synConstant">'detection_masks'</span>][<span class="synConstant">0</span>] <span class="synComment"># 画像にマスクとバウンディングボックスを書き込んで出力</span> vis_util.visualize_boxes_and_labels_on_image_array( image_np, output_dict[<span class="synConstant">'detection_boxes'</span>], output_dict[<span class="synConstant">'detection_classes'</span>], output_dict[<span class="synConstant">'detection_scores'</span>], category_index, instance_masks=output_dict.get(<span class="synConstant">'detection_masks'</span>), use_normalized_coordinates=<span class="synIdentifier">True</span>, line_thickness=<span class="synConstant">8</span>) Image.fromarray(image_np).save(<span class="synConstant">'out.png'</span>) </pre> <h1>結果</h1> <p>拾ってきたフリー写真に適用した結果が以下。手だけ写ってても人間って判断してくれるのね。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20180227/20180227183425.png" alt="f:id:whoopsidaisies:20180227183425p:plain" title="f:id:whoopsidaisies:20180227183425p:plain" class="hatena-fotolife" itemprop="image"></span></p> whoopsidaisies nvidia-dockerインストール、コンテナ等メモ hatenablog://entry/10328749687208981069 2017-01-22T19:06:18+09:00 2017-01-22T19:06:18+09:00 基本的に公式サイトの説明とかの通りにやるだけなんだけど自分用にメモ。 ホストOS:ubuntu 16.04LTS dockerのインストール 参考: Get Docker for Ubuntu - Docker # https通信で公開鍵ダウンロードするため apt-get update apt-get install curl ca-certificates # dockerレポジトリの公開鍵の登録 curl -fsSL https://yum.dockerproject.org/gpg | apt-key add - # add-apt-repositoryコマンドのインストール apt-… <p>基本的に公式サイトの説明とかの通りにやるだけなんだけど自分用にメモ。</p> <p>ホストOS:<a class="keyword" href="http://d.hatena.ne.jp/keyword/ubuntu">ubuntu</a> 16.04LTS</p> <h1>dockerのインストール</h1> <p>参考: <a href="https://docs.docker.com/engine/installation/linux/ubuntu/"><img src="https://cdn-ak.favicon.st-hatena.com/?url=https%3A%2F%2Fdocs.docker.com%2Fengine%2Finstallation%2Flinux%2Fubuntu%2F" alt="" class="http-favicon" /></a><a href="https://docs.docker.com/engine/installation/linux/ubuntu/">Get Docker for Ubuntu - Docker</a></p> <pre class="code" data-lang="" data-unlink># https通信で公開鍵ダウンロードするため apt-get update apt-get install curl ca-certificates # dockerレポジトリの公開鍵の登録 curl -fsSL https://yum.dockerproject.org/gpg | apt-key add - # add-apt-repositoryコマンドのインストール apt-get install software-properties-common # dockerレポジトリ追加 add-apt-repository &#34;deb https://apt.dockerproject.org/repo/ ubuntu-$(lsb_release -cs) main&#34; # aptでhttps通信するため apt-get install apt-transport-https # dockerのインストール apt-get update apt-get install docker-engine</pre> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/NVIDIA">NVIDIA</a>ドライバのインストール</h1> <p>これが一番ハマって大変な場合が多い気がするが、ここでは省略。どうにかうまいことインストールする。</p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/NVIDIA">NVIDIA</a> Dockerのインストール</h1> <pre class="code" data-lang="" data-unlink># debパッケージのダウンロード(2017/1/22現在で最新のもの) curl -LO https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.0/nvidia-docker_1.0.0-1_amd64.deb # インストール dpkg -i nvidia-docker_1.0.0-1_amd64.deb rm nvidia-docker_1.0.0-1_amd64.deb # 動作確認(GPU情報が表示されると良い) nvidia-docker run --rm nvidia/cuda nvidia-smi</pre> <p>バージョンについては下記ページでチェックして適宜ダウンロードするものを確認する。</p> <p><a href="https://github.com/NVIDIA/nvidia-docker/releases"><img src="https://cdn-ak.favicon.st-hatena.com/?url=https%3A%2F%2Fgithub.com%2FNVIDIA%2Fnvidia-docker%2Freleases" alt="" class="http-favicon" /></a><a href="https://github.com/NVIDIA/nvidia-docker/releases">Releases &middot; NVIDIA/nvidia-docker &middot; GitHub</a></p> <h1><a class="keyword" href="http://d.hatena.ne.jp/keyword/NVIDIA">NVIDIA</a> Dockerコンテナメモ</h1> <p>便利なものがあれば随時追記予定。</p> <ul> <li><a href="https://hub.docker.com/u/nvidia/">https://hub.docker.com/u/nvidia/</a><br/> <a class="keyword" href="http://d.hatena.ne.jp/keyword/nvidia">nvidia</a>公式コンテナ。CUDAやCuDNNのバージョン、OSの種類を選べる。</li> <li><a href="https://hub.docker.com/u/kaixhin/">https://hub.docker.com/u/kaixhin/</a><br/> イギリスの研究者作成のコンテナ。色々あって便利。</li> </ul> whoopsidaisies C#で3次元グラフを表示する ILNumerics hatenablog://entry/8454420450075953018 2014-12-02T18:32:47+09:00 2014-12-02T18:32:47+09:00 ILNumericsは.NETで使用可能な数値計算等のライブラリである.グラフ表示機能も備わっているので,それを使ってC#のWindowsフォーム上に3次元グラフを表示する. ILNumericsのインストール 現在最新バージョン(4.x系)のILNumericsは14日間のトライアル版以外は有償だが,Community Editionという無償版が提供されていた3.x系のバージョンがNuGetでインストール可能なのでそれを使う.まず,Visual StudioでWindowsフォームアプリケーションを作成する.そして,プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オン… <p><a href="http://ilnumerics.net/">ILNumerics</a>は.NETで使用可能な数値計算等のライブラリである.グラフ表示機能も備わっているので,それを使ってC#のWindowsフォーム上に3次元グラフを表示する.</p> <div class="section"> <h3>ILNumericsのインストール</h3> <p>現在最新バージョン(4.x系)のILNumericsは<a href="http://ilnumerics.net/shop.html">14&#x65E5;&#x9593;&#x306E;&#x30C8;&#x30E9;&#x30A4;&#x30A2;&#x30EB;&#x7248;&#x4EE5;&#x5916;&#x306F;&#x6709;&#x511F;</a>だが,<a href="http://ilnumerics.net/closed-source-version-available.html">Community Edition&#x3068;&#x3044;&#x3046;&#x7121;&#x511F;&#x7248;&#x304C;&#x63D0;&#x4F9B;&#x3055;&#x308C;&#x3066;&#x3044;&#x305F;3.x&#x7CFB;&#x306E;&#x30D0;&#x30FC;&#x30B8;&#x30E7;&#x30F3;</a>が<a href="https://www.nuget.org/packages/ILNumerics/">NuGet&#x3067;&#x30A4;&#x30F3;&#x30B9;&#x30C8;&#x30FC;&#x30EB;&#x53EF;&#x80FD;</a>なのでそれを使う.</p><p>まず,Visual StudioでWindowsフォームアプリケーションを作成する.</p><p>そして,プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「ILNumerics」を検索・インストールする.</p> </div> <div class="section"> <h3>グラフ表示用コントロールの配置</h3> <p>フォームデザイナを開きツールボックスの適当なところで右クリックして「アイテムの選択(I)...」を選択する.</p><p>「.NET Framework コンポーネント」タブの「参照(B)...」ボタンを押して,「(ソリューションのパス)\packages\ILNumerics.3.3.3.0\lib\ILNumerics.dll」を選択したらOK.</p><p>するとツールボックスIL○○というコントロールが追加される.その中の,ILPanelコントロールをフォーム上に配置する.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141202/20141202163400.png" alt="f:id:whoopsidaisies:20141202163400p:plain" title="f:id:whoopsidaisies:20141202163400p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>使ってみる</h3> <div class="section"> <h4>曲面</h4> <p>例として,以下の2変数関数を表示させてみる.<br /> <img src="http://chart.apis.google.com/chart?cht=tx&chl=z%3D%5Cfrac%7B%5Csin%28%5Csqrt%7Bx%5E2%2By%5E2%7D%29%7D%7B%5Csqrt%7Bx%5E2%2By%5E2%7D%7D" alt="z=\frac{\sin(\sqrt{x^2+y^2})}{\sqrt{x^2+y^2}}"/></p><p>まず,コードの適当な場所に以下のusingを書いておく.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synStatement">using</span> ILNumerics.Drawing; <span class="synStatement">using</span> ILNumerics.Drawing.Plotting; </pre><p>そして,フォームロードイベントとかの適当なイベントに以下のコードを書く.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// グラフを格納するオブジェクトの生成</span> var scene = <span class="synStatement">new</span> ILScene { <span class="synComment">// 3次元モードでプロット領域を生成</span> <span class="synStatement">new</span> ILPlotCube(twoDMode: <span class="synConstant">false</span>) { <span class="synComment">// 曲面の生成</span> <span class="synStatement">new</span> ILSurface( (x,y) =&gt; (<span class="synType">float</span>)( Math.Sin(Math.Sqrt(x*x + y*y))/Math.Sqrt(x*x + y*y))) } }; <span class="synComment">// 描画用コントロールに生成したグラフをセット</span> ilPanel1.Scene = scene; </pre><p>実行すると以下のように3次元グラフが表示される.マウスドラッグとかホイールとかで視点や拡大率を変えられる.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141202/20141202172655.png" alt="f:id:whoopsidaisies:20141202172655p:plain" title="f:id:whoopsidaisies:20141202172655p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h4>等高線</h4> <p>サンプル用の地形データも用意されていて,以下のように使うことが出来る.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>var scene = <span class="synStatement">new</span> ILScene { <span class="synStatement">new</span> ILPlotCube(twoDMode: <span class="synConstant">false</span>){ <span class="synStatement">new</span> ILSurface(ILNumerics.ILMath.tosingle(ILNumerics.ILSpecialData.terrain)) } }; ilPanel1.Scene = scene; </pre><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141202/20141202180125.png" alt="f:id:whoopsidaisies:20141202180125p:plain" title="f:id:whoopsidaisies:20141202180125p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>ここまでは曲面表示のためILSurfaceクラスを使ってきたが,ILContourPlotクラスを使えば以下のように等高線表示も出来る.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>var scene = <span class="synStatement">new</span> ILScene { <span class="synStatement">new</span> ILPlotCube{ <span class="synStatement">new</span> ILContourPlot(ILNumerics.ILMath.tosingle(ILNumerics.ILSpecialData.terrain)) } }; ilPanel1.Scene = scene; </pre><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141202/20141202180132.png" alt="f:id:whoopsidaisies:20141202180132p:plain" title="f:id:whoopsidaisies:20141202180132p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h4>散布図</h4> <p>ILPointsクラスで散布図を表示させることも出来る.以下はランダムに点を打って対数軸にして表示した例.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>ILNumerics.ILArray&lt;<span class="synType">float</span>&gt; p = ILNumerics.ILMath.tosingle(ILNumerics.ILMath.rand(<span class="synConstant">3</span>, <span class="synConstant">10000</span>)); var scene = <span class="synStatement">new</span> ILScene{ <span class="synStatement">new</span> ILPlotCube(twoDMode:<span class="synConstant">false</span>){ <span class="synStatement">new</span> ILPoints { Positions = p, Color = <span class="synConstant">null</span>, Colors = p, Size = <span class="synConstant">1</span>, } } }; var scaleModes = scene.First&lt;ILPlotCube&gt;().ScaleModes; scaleModes.XAxisScale = AxisScale.Logarithmic; scaleModes.YAxisScale = AxisScale.Logarithmic; scaleModes.ZAxisScale = AxisScale.Logarithmic; ilPanel1.Scene = scene; </pre><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141202/20141202182150.png" alt="f:id:whoopsidaisies:20141202182150p:plain" title="f:id:whoopsidaisies:20141202182150p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> </div> whoopsidaisies Python+OpenCVで特徴量記述・アルゴリズムまとめ hatenablog://entry/8454420450075890810 2014-12-01T23:50:13+09:00 2014-12-01T23:50:13+09:00 Python+OpenCVで画像の特徴点の特徴量を記述する.OpenCV2.4.9およびOpenCV3.0 alphaについて使用できるアルゴリズムをまとめる.Python+OpenCVで特徴点抽出・使えるアルゴリズムまとめ OpenCV2.4.9と3.0 alpha - whoopsidaisies's diary の続き. 環境 WindowsでOpenCV公式サイトのダウンロードページから2.4.9および3.0 alphaのビルド済みバイナリをダウンロードしてきて解凍したものを使う. 特徴量記述器の使い方 特徴点抽出のときのFeatureDetectorと同じように,特徴量記述についても… <p>Python+OpenCVで画像の特徴点の特徴量を記述する.OpenCV2.4.9およびOpenCV3.0 alphaについて使用できるアルゴリズムをまとめる.</p><p><a href="http://whoopsidaisies.hatenablog.com/entry/2014/12/01/031213"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2014%2F12%2F01%2F031213" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2014/12/01/031213">Python+OpenCV&#x3067;&#x7279;&#x5FB4;&#x70B9;&#x62BD;&#x51FA;&#x30FB;&#x4F7F;&#x3048;&#x308B;&#x30A2;&#x30EB;&#x30B4;&#x30EA;&#x30BA;&#x30E0;&#x307E;&#x3068;&#x3081; OpenCV2.4.9&#x3068;3.0 alpha - whoopsidaisies&#39;s diary</a><br /> の続き.</p> <div class="section"> <h3>環境</h3> <p>WindowsでOpenCV公式サイトの<a href="http://opencv.org/downloads.html">&#x30C0;&#x30A6;&#x30F3;&#x30ED;&#x30FC;&#x30C9;&#x30DA;&#x30FC;&#x30B8;</a>から<a href="https://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.9/opencv-2.4.9.exe/download">2.4.9</a>および<a href="http://sourceforge.net/projects/opencvlibrary/files/opencv-win/3.0.0-alpha/">3.0 alpha</a>のビルド済みバイナリをダウンロードしてきて解凍したものを使う.</p> </div> <div class="section"> <h3>特徴量記述器の使い方</h3> <p>特徴点抽出のときのFeatureDetectorと同じように,特徴量記述についてもDescriptorExtractorという共通インターフェースが用意されている.</p><p>使い方は以下の通り.</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 引数でどの特徴量記述子を使うか指定 </span> extractor = cv2.DescriptorExtractor_create(extractor_name) <span class="synComment"># 引数として画像と特徴点を渡す</span> <span class="synComment"># 戻り値は特徴点と特徴量</span> keypoints, descriptors = extractor.compute(img, keypoints) </pre><p>DescriptorExtractor_createメソッドで指定出来る特徴量記述子を以下にまとめた.</p> <table> <tr> <td>OpenCVバージョン</td> <th> 実数ベクトル</th> <th> バイナリコード</th> </tr> <tr> <td>2.4.9</td> <td>SIFT, SURF</td> <td>BRIEF, BRISK, <del>ORB</del>, FREAK</td> </tr> <tr> <td>3.0 alpha</td> <td>KAZE</td> <td>AKAZE, BRISK, ORB</td> </tr> </table><p>(2.4.9でORBがなぜかランタイムエラーが出るので追々調査予定)</p> </div> <div class="section"> <h3>特徴量の中身</h3> <p>descriptorsの中身は2次元のarrayになっており,特徴点ごとに特徴量のベクトルが格納されている.</p><p>KAZEで記述した特徴量を表示してみるとこんな感じ(0番目の点).</p> <pre class="code lang-python" data-lang="python" data-unlink>&gt;&gt;descriptors[<span class="synConstant">0</span>] array([ -<span class="synConstant">7.38840317e-04</span>, -<span class="synConstant">6.34267868e-04</span>, <span class="synConstant">2.61819176e-03</span>, <span class="synConstant">3.50267510e-03</span>, -<span class="synConstant">1.59906253e-04</span>, -<span class="synConstant">4.56994586e-03</span>, <span class="synConstant">4.39605350e-03</span>, <span class="synConstant">9.44076758e-03</span>, -<span class="synConstant">1.75689301e-03</span>, <span class="synConstant">8.05667194e-04</span>, <span class="synConstant">3.55383591e-03</span>, <span class="synConstant">4.12554527e-03</span>, -<span class="synConstant">1.54193444e-03</span>, <span class="synConstant">1.58668880e-03</span>, <span class="synConstant">2.78847502e-03</span>, <span class="synConstant">3.14337271e-03</span>, -<span class="synConstant">1.62520558e-02</span>, <span class="synConstant">1.65848620e-02</span>, <span class="synConstant">3.65739577e-02</span>, <span class="synConstant">2.07063138e-01</span>, <span class="synConstant">2.64649391e-02</span>, -<span class="synConstant">6.13974873e-03</span>, <span class="synConstant">9.64385048e-02</span>, <span class="synConstant">2.91850477e-01</span>, <span class="synConstant">5.54781593e-02</span>, <span class="synConstant">6.74537197e-03</span>, <span class="synConstant">6.74520805e-02</span>, <span class="synConstant">8.45865980e-02</span>, -<span class="synConstant">2.12559430e-03</span>, <span class="synConstant">1.18403265e-03</span>, <span class="synConstant">5.09992335e-03</span>, <span class="synConstant">4.04977519e-03</span>, -<span class="synConstant">1.28035052e-02</span>, <span class="synConstant">6.93068025e-04</span>, <span class="synConstant">3.93203236e-02</span>, <span class="synConstant">4.54802722e-01</span>, -<span class="synConstant">2.96720478e-04</span>, <span class="synConstant">6.83288351e-02</span>, <span class="synConstant">8.15773308e-02</span>, <span class="synConstant">6.17026806e-01</span>, -<span class="synConstant">1.08468741e-01</span>, <span class="synConstant">5.95125668e-02</span>, <span class="synConstant">1.92962006e-01</span>, <span class="synConstant">2.17324436e-01</span>, -<span class="synConstant">1.21422755e-02</span>, <span class="synConstant">2.50244630e-03</span>, <span class="synConstant">1.34693161e-02</span>, <span class="synConstant">6.25377288e-03</span>, <span class="synConstant">2.55310140e-03</span>, -<span class="synConstant">4.21544649e-02</span>, <span class="synConstant">2.98030730e-02</span>, <span class="synConstant">1.50349155e-01</span>, <span class="synConstant">4.27789390e-02</span>, -<span class="synConstant">9.73087847e-02</span>, <span class="synConstant">1.63991615e-01</span>, <span class="synConstant">1.90487400e-01</span>, <span class="synConstant">3.39032081e-03</span>, -<span class="synConstant">2.32313443e-02</span>, <span class="synConstant">1.98113456e-01</span>, <span class="synConstant">6.58137947e-02</span>, -<span class="synConstant">1.16498368e-02</span>, <span class="synConstant">2.66303378e-03</span>, <span class="synConstant">1.25482017e-02</span>, <span class="synConstant">4.14769724e-03</span>], dtype=float32) </pre><p>グラフ表示だとこんな感じ.</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> matplotlib.pyplot <span class="synStatement">as</span> plt plt.plot(descriptors[<span class="synConstant">0</span>]) </pre><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141201/20141201234637.png" alt="f:id:whoopsidaisies:20141201234637p:plain" title="f:id:whoopsidaisies:20141201234637p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>KAZEは64次元の実数ベクトルで特徴量記述をするので以上のようになるが,記述子によってデータ量が違うため配列の長さや型が変わってくる.</p> </div> whoopsidaisies Python+OpenCVで特徴点抽出・使えるアルゴリズムまとめ OpenCV2.4.9と3.0 alpha hatenablog://entry/8454420450075787134 2014-12-01T03:12:13+09:00 2014-12-01T03:12:13+09:00 軽量プログラミング言語が苦手なので敬遠していたが,世間ではPythonからOpenCVを呼ぶのが流行っているようなので,練習がてらOpenCVで使える特徴点抽出アルゴリズムをまとめてみる.OpenCV2.4.9とOpenCV3.0 alphaについてまとめる.3.0 betaはなぜか動かなかったのでいつか暇があれば調査. 環境 WindowsでOpenCV公式サイトのダウンロードページから2.4.9および3.0 alphaのビルド済みバイナリをダウンロードしてきて解凍したものを使う.PythonからのOpenCVの呼び出し方はこことかを参照. 特徴点抽出の使い方 OpenCVで実装されている特… <p>軽量プログラミング言語が苦手なので敬遠していたが,世間ではPythonからOpenCVを呼ぶのが流行っているようなので,練習がてらOpenCVで使える特徴点抽出アルゴリズムをまとめてみる.</p><p>OpenCV2.4.9とOpenCV3.0 alphaについてまとめる.3.0 betaはなぜか動かなかったのでいつか暇があれば調査.</p> <div class="section"> <h3>環境</h3> <p>WindowsでOpenCV公式サイトの<a href="http://opencv.org/downloads.html">&#x30C0;&#x30A6;&#x30F3;&#x30ED;&#x30FC;&#x30C9;&#x30DA;&#x30FC;&#x30B8;</a>から<a href="https://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.9/opencv-2.4.9.exe/download">2.4.9</a>および<a href="http://sourceforge.net/projects/opencvlibrary/files/opencv-win/3.0.0-alpha/">3.0 alpha</a>のビルド済みバイナリをダウンロードしてきて解凍したものを使う.</p><p>PythonからのOpenCVの呼び出し方は<a href="http://docs.opencv.org/trunk/doc/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.html">&#x3053;&#x3053;&#x3068;&#x304B;</a>を参照.</p> </div> <div class="section"> <h3>特徴点抽出の使い方</h3> <p>OpenCVで実装されている特徴点抽出のアルゴリズムはいくつかあるが,FeatureDetectorという共通インターフェースを使うことでどのアルゴリズムでも同様の記述で使える.使い方は以下.</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synComment"># 画像読み込み</span> img = cv2.imread(<span class="synConstant">'gazou.bmp'</span>) <span class="synComment"># FeatureDetectorのインスタンスを生成</span> detector = cv2.FeatureDetector_create(detector_type) <span class="synComment"># 特徴点を抽出</span> keypoints = detctor.detect(img) </pre><p>FeatureDetector_createメソッドの引数にアルゴリズム名を文字列で渡すことで,どのアルゴリズムで特徴点抽出するかを選択することが出来る.例えば,ORBアルゴリズムで特徴点を抽出して表示するのは以下のようになる.</p> <pre class="code lang-python" data-lang="python" data-unlink><span class="synPreProc">import</span> cv2 img = cv2.imread(<span class="synConstant">'gazou.bmp'</span>) <span class="synComment"># アルゴリズム名を引数で渡す</span> detector = cv2.FeatureDetector_create(<span class="synConstant">'ORB'</span>) keypoints = detctor.detect(img) <span class="synComment"># 画像への特徴点の書き込み</span> out = cv2.drawKeypoints(img, keypoints, <span class="synIdentifier">None</span>) <span class="synComment"># 表示</span> cv2.imshow(name, out) cv2.waitKey(<span class="synConstant">0</span>) </pre><p>結果は以下のようになる.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141201/20141201024751.png" alt="f:id:whoopsidaisies:20141201024751p:plain" title="f:id:whoopsidaisies:20141201024751p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>ちなみに特徴点の書き込み部分を以下のようにすると,特徴点のサイズと方向を表す円が描画される.</p> <pre class="code lang-python" data-lang="python" data-unlink>out = cv2.drawKeypoints(img, keypoints, <span class="synIdentifier">None</span>, <span class="synIdentifier">None</span>, cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) </pre><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141201/20141201024104.png" alt="f:id:whoopsidaisies:20141201024104p:plain" title="f:id:whoopsidaisies:20141201024104p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>FeatureDetectorインターフェースで使えるアルゴリズム</h3> <p>FeatureDetectorインターフェースで指定できる特徴点抽出アルゴリズムはOpenCVのバージョンで変わるようなので,OpenCV2.4.9で使えるものとOpenCV3.0 alphaで使えるものを以下にまとめる.<br /> <br /> </p> <table> <tr> <td>バージョン</td> <th>アルゴリズム名</th> </tr> <tr> <th>2.4.9</th> <td>BRISK, Dense, FAST, FASTX, GFTT, HARRIS, MSER, ORB, SIFT, STAR, SURF, SURF_OCL, SimpleBlob</td> </tr> <tr> <th>3.0 alpha</th> <td>AKAZE, BRISK, FAST, GFTT, HARRIS, KAZE, MSER, ORB, SimpleBlob</td> </tr> </table><p><br /> C++版については以下の記事にまとめてある.<br /> <a href="http://whoopsidaisies.hatenablog.com/entry/2014/08/20/200215"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2014%2F08%2F20%2F200215" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2014/08/20/200215">OpenCV3.0.0-alpha&#x306E;&#x7279;&#x5FB4;&#x62BD;&#x51FA;&#x30FB;&#x30DE;&#x30C3;&#x30C1;&#x30F3;&#x30B0;&#x307E;&#x3068;&#x3081; - whoopsidaisies&#39;s diary</a><br /> <a href="http://whoopsidaisies.hatenablog.com/entry/2013/12/07/135810"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2013%2F12%2F07%2F135810" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2013/12/07/135810">OpenCV&#x3067;&#x753B;&#x50CF;&#x306E;&#x7279;&#x5FB4;&#x62BD;&#x51FA;&#x30FB;&#x30DE;&#x30C3;&#x30C1;&#x30F3;&#x30B0;&#x3092;&#x884C;&#x3046; - whoopsidaisies&#39;s diary</a></p> </div> whoopsidaisies C#で画像をWavelet変換 Accord.NET hatenablog://entry/8454420450075706497 2014-11-30T10:32:21+09:00 2014-11-30T10:32:21+09:00 C#で画像のWavelet変換を行う.コンピュータビジョン等の.NET向けのオープンソースのライブラリであるAccord.NET Frameworkを使う. Accord.NETのインストール NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「Accord.Imaging」を検索・インストール. WaveletTransformクラス Accord.NETのWaveletTransformクラスによってWavelet変換を行える.入力画像はグレースケールで,解像度が2のべき乗でないといけない. ソースコード WaveletT… <p>C#で画像のWavelet変換を行う.コンピュータビジョン等の.NET向けのオープンソースのライブラリである<a href="http://accord-framework.net/">Accord.NET Framework</a>を使う.</p> <div class="section"> <h3>Accord.NETのインストール</h3> <p>NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「Accord.Imaging」を検索・インストール.</p> </div> <div class="section"> <h3>WaveletTransformクラス</h3> <p>Accord.NETの<a href="http://accord-framework.net/docs/html/T_Accord_Imaging_Filters_WaveletTransform.htm">WaveletTransform</a>クラスによってWavelet変換を行える.入力画像はグレースケールで,解像度が2のべき乗でないといけない.</p> </div> <div class="section"> <h3>ソースコード</h3> <p>WaveletTransformクラスの初期化時にWavelet母関数を指定する.その引数でWavelet変換のレベルを指定できる.ここではHaar関数でレベル2とした.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// 入力画像</span> var img = <span class="synStatement">new</span> Bitmap(<span class="synSpecial">@</span><span class="synConstant">&quot;Penguins.jpg&quot;</span>); <span class="synComment">// 画像の解像度が2のべき乗になるように調整</span> var bitWidth = Convert.ToString(img.Width - <span class="synConstant">1</span>, <span class="synConstant">2</span>).Length; var bitHeight = Convert.ToString(img.Height - <span class="synConstant">1</span>, <span class="synConstant">2</span>).Length; var width = (<span class="synType">int</span>)Math.Pow(<span class="synConstant">2</span>, bitWidth); var height = (<span class="synType">int</span>)Math.Pow(<span class="synConstant">2</span>, bitHeight); <span class="synComment">// 隙間の部分はゼロ埋め</span> var imgPadded = <span class="synStatement">new</span> Bitmap(width, height, img.PixelFormat); var graphics = Graphics.FromImage(imgPadded); graphics.DrawImage(img, <span class="synConstant">0</span>, <span class="synConstant">0</span>); graphics.Dispose(); <span class="synComment">// グレースケール化</span> var gray = <span class="synStatement">new</span> AForge.Imaging.Filters.Grayscale(<span class="synConstant">0.2125</span>, <span class="synConstant">0.7154</span>, <span class="synConstant">0.0721</span>).Apply(imgPadded); <span class="synComment">// Wavelet変換クラスの作成</span> <span class="synComment">// Harrクラスの初期化時にレベルを指定出来る</span> var wavelet = <span class="synStatement">new</span> Accord.Imaging.Filters.WaveletTransform(<span class="synStatement">new</span> Accord.Math.Wavelets.Haar(<span class="synConstant">2</span>)); <span class="synComment">// Wavelet変換</span> var imgWavelet = wavelet.Apply(gray); pictureBox1.Image = imgWavelet; </pre> </div> <div class="section"> <h3>結果</h3> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141130/20141130095415.png" alt="f:id:whoopsidaisies:20141130095415p:plain" title="f:id:whoopsidaisies:20141130095415p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>逆変換</h3> <p>WaveletTransformクラスの<a href="http://accord-framework.net/docs/html/P_Accord_Imaging_Filters_WaveletTransform_Backward.htm">Backword</a>プロパティをtrueにしてApplyメソッドを実行すると逆変換が出来る.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>wavelet.Backward = <span class="synConstant">true</span>; var gyaku = wavelet.Apply(imgWavelet); </pre> </div> whoopsidaisies C#で画像を高速フーリエ変換 AForge.NET hatenablog://entry/8454420450075684932 2014-11-30T09:19:05+09:00 2014-11-30T09:19:05+09:00 C#で画像の高速フーリエ変換(FFT)を行う.コンピュータビジョン等のライブラリであるAForge.NET Frameworkを使う. AForge.NETのインストール Nuget経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「AForge」で検索.「AForge.Imaging」を選択してインストール. ComplexImageクラス AForge.NETのComplexImageクラスを使うと画像のFFTおよび逆FFTが出来る.入力する画像はグレースケールで解像度が2のべき乗になっている必要がある. ソースコード 画像のグレー… <p>C#で画像の高速フーリエ変換(FFT)を行う.コンピュータビジョン等のライブラリである<a href="https://code.google.com/p/aforge/">AForge.NET Framework</a>を使う.</p> <div class="section"> <h3>AForge.NETのインストール</h3> <p>Nuget経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「AForge」で検索.「AForge.Imaging」を選択してインストール.</p> </div> <div class="section"> <h3>ComplexImageクラス</h3> <p>AForge.NETの<a href="http://www.aforgenet.com/framework/docs/html/8ec218c8-628b-e6b9-c398-3d65f14280d5.htm">ComplexImage</a>クラスを使うと画像のFFTおよび逆FFTが出来る.入力する画像はグレースケールで解像度が2のべき乗になっている必要がある.</p> </div> <div class="section"> <h3>ソースコード</h3> <p>画像のグレースケール化は<a href="http://www.aforgenet.com/framework/docs/html/d7196dc6-8176-4344-a505-e7ade35c1741.htm">Grayscale</a>クラスを使った.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// 入力画像</span> var img = <span class="synStatement">new</span> Bitmap(<span class="synSpecial">@</span><span class="synConstant">&quot;Lighthouse.jpg&quot;</span>); pictureBox1.Image = img; <span class="synComment">// 画像の解像度が2のべき乗になるように調整</span> var bitWidth = Convert.ToString(img.Width - <span class="synConstant">1</span>, <span class="synConstant">2</span>).Length; var bitHeight = Convert.ToString(img.Height - <span class="synConstant">1</span>, <span class="synConstant">2</span>).Length; var width = (<span class="synType">int</span>)Math.Pow(<span class="synConstant">2</span>, bitWidth); var height = (<span class="synType">int</span>)Math.Pow(<span class="synConstant">2</span>, bitHeight); <span class="synComment">// 隙間の部分はゼロ埋め</span> var imgPadded = <span class="synStatement">new</span> Bitmap(width, height, img.PixelFormat); var graphics = Graphics.FromImage(imgPadded); graphics.DrawImage(img, <span class="synConstant">0</span>, <span class="synConstant">0</span>); graphics.Dispose(); <span class="synComment">// グレースケール化</span> var gray = <span class="synStatement">new</span> AForge.Imaging.Filters.Grayscale(<span class="synConstant">0.2125</span>, <span class="synConstant">0.7154</span>, <span class="synConstant">0.0721</span>).Apply(imgPadded); pictureBox2.Image = gray; <span class="synComment">// FFT</span> var complexImage = AForge.Imaging.ComplexImage.FromBitmap(gray); complexImage.ForwardFourierTransform(); pictureBox3.Image = complexImage.ToBitmap(); </pre> </div> <div class="section"> <h3>結果画像</h3> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141130/20141130083904.png" alt="f:id:whoopsidaisies:20141130083904p:plain" title="f:id:whoopsidaisies:20141130083904p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>FFT後の値</h3> <p>ComplexImageクラスの<a href="http://www.aforgenet.com/framework/docs/html/5717ee01-e66e-d13d-8578-bdcc862e033f.htm">Data</a>プロパティは2次元配列でFFT後の値が格納されている.また,<a href="http://www.aforgenet.com/framework/docs/html/bf07655f-4048-c890-190a-16859beb1925.htm">BackwardFourierTransform</a>メソッドで逆FFTを行える.</p> </div> whoopsidaisies Visual Studioでデバッグ時にOpenCVのMat等の画像を表示できるプラグインが便利 hatenablog://entry/8454420450075550903 2014-11-28T17:56:37+09:00 2014-11-28T17:56:37+09:00 OpenCV公式サイトのNEWSを見てたら「Image Watch plugin for Visual Studio」というのを見つけた.使ってみたら便利そうだったのでメモ.もっと早く知りたかった.わざわざimshowとかのコードを追加してウィンドウを表示させなくてもMatの中の画像を確認できる.また,拡大表示とか画素値の表示も出来るため通常のOpenCVの画像表示用のウィンドウより便利な気がする. Image Watch plugin for Visual Studioのインストール 以下のサイトからダウンロードしてきて指示にしたがってインストールするだけ. Image Watch exte… <p><a href="http://opencv.org/image-watch-plugin-for-visual-studio.html">OpenCV&#x516C;&#x5F0F;&#x30B5;&#x30A4;&#x30C8;&#x306E;NEWS</a>を見てたら「<a href="https://visualstudiogallery.msdn.microsoft.com/e682d542-7ef3-402c-b857-bbfba714f78d">Image Watch plugin for Visual Studio</a>」というのを見つけた.使ってみたら便利そうだったのでメモ.もっと早く知りたかった.</p><p>わざわざimshowとかのコードを追加してウィンドウを表示させなくてもMatの中の画像を確認できる.また,拡大表示とか画素値の表示も出来るため通常のOpenCVの画像表示用のウィンドウより便利な気がする.</p> <div class="section"> <h3>Image Watch plugin for Visual Studioのインストール</h3> <p>以下のサイトからダウンロードしてきて指示にしたがってインストールするだけ.<br /> <a href="https://visualstudiogallery.msdn.microsoft.com/e682d542-7ef3-402c-b857-bbfba714f78d"><img src="http://cdn-ak.favicon.st-hatena.com/?url=https%3A%2F%2Fvisualstudiogallery.msdn.microsoft.com%2Fe682d542-7ef3-402c-b857-bbfba714f78d" alt="" class="http-favicon" /></a><a href="https://visualstudiogallery.msdn.microsoft.com/e682d542-7ef3-402c-b857-bbfba714f78d">Image Watch extension</a></p><p>以下のサイトに詳しい手順等載ってます.<br /> <a href="http://www.atinfinity.info/blog/archives/1601"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwww.atinfinity.info%2Fblog%2Farchives%2F1601" alt="" class="http-favicon" /></a><a href="http://www.atinfinity.info/blog/archives/1601">Image Watch&#x306E;&#x4F7F;&#x3044;&#x65B9; | dandelion&#39;s log</a><br /> </p> </div> <div class="section"> <h3>使ってみる</h3> <p>以下のコードで試してみた.画像を表示させるためのコードは特に必要ない.画像が入っている変数があれば自動で表示してくれる.</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/opencv.hpp&gt;</span> <span class="synStatement">using</span> <span class="synType">namespace</span> cv; <span class="synType">void</span> main() { <span class="synComment">// 画像読み込み</span> Mat img = imread(<span class="synConstant">&quot;Penguins.jpg&quot;</span>); <span class="synComment">// Sobelフィルタ</span> Mat imgSobel; Sobel(img, imgSobel, img.depth(), <span class="synConstant">1</span>, <span class="synConstant">1</span>); <span class="synComment">// ラプラシアンフィルタ</span> Mat imgLaplacian; Laplacian(img, imgLaplacian, img.depth()); <span class="synComment">// Cannyアルゴリズム</span> Mat imgCanny; Canny(img, imgCanny, <span class="synConstant">50</span>, <span class="synConstant">200</span>); } </pre><p>一番下の行にブレークポイントを置いて,デバッグ実行して止める.</p><p>「表示」メニューの中から「Image Watch」を探してクリックしてウィンドウを表示させる.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141128/20141128173607.png" alt="f:id:whoopsidaisies:20141128173607p:plain" title="f:id:whoopsidaisies:20141128173607p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>そうすると以下の様なウィンドウが出てきて,Mat型の変数とその中身の画像が表示される.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141128/20141128165602.png" alt="f:id:whoopsidaisies:20141128165602p:plain" title="f:id:whoopsidaisies:20141128165602p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>左側に画像一覧があるので,クリックすれば以下のようにその画像が表示される.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141128/20141128165507.png" alt="f:id:whoopsidaisies:20141128165507p:plain" title="f:id:whoopsidaisies:20141128165507p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>マウススクロールで拡大可能.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141128/20141128173940.png" alt="f:id:whoopsidaisies:20141128173940p:plain" title="f:id:whoopsidaisies:20141128173940p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>最大まで拡大すると各画素の画素値が数字で表示される.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141128/20141128174024.png" alt="f:id:whoopsidaisies:20141128174024p:plain" title="f:id:whoopsidaisies:20141128174024p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>画素を右クリックしたら,その画素のアドレスのコピーとかも出来るもよう.</p><p>以上のようにOpenCVのMatの中の画像を簡単に確認できるので,Visual StudioでOpenCVを使う場合はかなり便利だと思う.</p><p>試してないけど<a href="https://visualstudiogallery.msdn.microsoft.com/e682d542-7ef3-402c-b857-bbfba714f78d">&#x914D;&#x5E03;&#x30B5;&#x30A4;&#x30C8;</a>の説明によると,cv::Mat_<>, CvMat, _IplImageなんかにも対応しているらしい.</p> </div> whoopsidaisies opencvで文字認識その1 Tesseractラッパ hatenablog://entry/12921228815733154180 2014-11-12T00:31:00+09:00 2014-11-12T00:31:00+09:00 OpenCV3.0系から文字認識モジュールが搭載されるようなので使ってみる.現状の3.0 alphaや3.0 betaでは,文字認識モジュールはメインレポジトリに組み込まれておらず開発用レポジトリのopencv_contribの方に入っているようで,opencv_contribと一緒にOpenCVをビルドする必要がある. OpenCVの文字認識モジュール OpenCVのドキュメントによると,以下の2種類の文字認識方法があるらしい. オープンソースのOCRライブラリtesseract-ocrを呼び出す方法 隠れマルコフモデルによる認識方法 今回は,1の方法について試してみる. 文字認識モジュール… <p><a href="http://opencv.org/opencv-3-0-alpha.html">OpenCV3.0&#x7CFB;&#x304B;&#x3089;&#x6587;&#x5B57;&#x8A8D;&#x8B58;&#x30E2;&#x30B8;&#x30E5;&#x30FC;&#x30EB;&#x304C;&#x642D;&#x8F09;&#x3055;&#x308C;&#x308B;</a>ようなので使ってみる.現状の3.0 alphaや3.0 betaでは,文字認識モジュールはメインレポジトリに組み込まれておらず開発用レポジトリの<a href="https://github.com/itseez/opencv_contrib">opencv_contrib</a>の方に入っているようで,opencv_contribと一緒にOpenCVをビルドする必要がある.</p> <div class="section"> <h3>OpenCVの文字認識モジュール</h3> <p><a href="http://docs.opencv.org/trunk/modules/text/doc/ocr.html">OpenCV&#x306E;&#x30C9;&#x30AD;&#x30E5;&#x30E1;&#x30F3;&#x30C8;</a>によると,以下の2種類の文字認識方法があるらしい.</p> <ol> <li>オープンソースのOCRライブラリ<a href="https://code.google.com/p/tesseract-ocr/">tesseract-ocr</a>を呼び出す方法</li> <li><a href="http://cmp.felk.cvut.cz/~neumalu1/icdar2011_article.pdf">&#x96A0;&#x308C;&#x30DE;&#x30EB;&#x30B3;&#x30D5;&#x30E2;&#x30C7;&#x30EB;&#x306B;&#x3088;&#x308B;&#x8A8D;&#x8B58;&#x65B9;&#x6CD5;</a></li> </ol><p>今回は,1の方法について試してみる.</p> </div> <div class="section"> <h3>文字認識モジュールの準備</h3> <div class="section"> <h4>tesseract-ocrのダウンロード</h4> <p><a href="https://code.google.com/p/tesseract-ocr/downloads/list">https://code.google.com/p/tesseract-ocr/downloads/list</a>からVC++からtesseract-ocrを呼び出す用のライブラリをダウンロード・解凍する.「tesseract-3.xx.xx-win32-lib-include-dirs.zip」って名前のやつ.今回は「<a href="https://code.google.com/p/tesseract-ocr/downloads/detail?name=tesseract-3.02.02-win32-lib-include-dirs.zip&can=2&q=">tesseract-3.02.02-win32-lib-include-dirs.zip</a>」を使った.</p><p><a href="https://code.google.com/p/tesseract-ocr/downloads/list">https://code.google.com/p/tesseract-ocr/downloads/list</a>からtesseract-ocr用の学習済みのデータファイルをダウンロードしておく.今回は英語で試すため「<a href="https://code.google.com/p/tesseract-ocr/downloads/detail?name=tesseract-ocr-3.02.eng.tar.gz&can=2&q=">tesseract-ocr-3.02.eng.tar.gz</a>」をダウンロード・解凍する.</p> </div> <div class="section"> <h4>opencv_contribのダウンロード</h4> <p><a href="https://github.com/itseez/opencv_contrib">https://github.com/itseez/opencv_contrib</a>からopencv_contribをダウンロード・解凍する.</p> </div> <div class="section"> <h4>OpenCVのビルド</h4> <p>CMakeを使ってビルドする.<a href="http://www.buildinsider.net/small/opencv/02#cmake">&#x3053;&#x3053;&#x3089;&#x3078;&#x3093;</a>を参考に.</p><p>「OPENCV_EXTRA_MODULES_PATH」パラメータの値を「(opencv_contribのパス)/modules」にセットしてConfigureする.</p><p>すると「Tesseract_INCLUDE_DIR」と「Tesseract_LIBRARY」というパラメータが出てくるので</p> <ul> <li>Tesseract_INCLUDE_DIR ← (tesseract-ocrのパス)/include</li> <li>Tesseract_LIBRARY ← (tesseract-ocrのパス)/lib</li> </ul><p>とセットする.</p><p>以上の設定でGenerateしてOpenCVをビルドすると文字認識モジュールが組み込まれる.で,インストールする.</p> </div> </div> <div class="section"> <h3>動作確認</h3> <p>実際に画像を入力してやってみたソースコードと結果が以下.OpenCVのMat形式の画像を使って文字認識出来るため,<a href="https://code.google.com/p/tesseract-ocr/wiki/APIExample">tesseract-ocr&#x306E;API&#x76F4;&#x63A5;&#x53E9;&#x304F;</a>よりは使いやすいと思う.</p><p>追記)文字のかたまりの位置の出力が間違っていたためソースコードと結果画像を修正した.</p> <div class="section"> <h5>ソースコード</h5> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/opencv.hpp&gt;</span> <span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/text.hpp&gt;</span> <span class="synType">void</span> main() { <span class="synComment">// 画像読み込み</span> <span class="synType">auto</span> image = cv::imread(<span class="synConstant">&quot;moji.jpg&quot;</span>); <span class="synComment">// グレースケール化</span> cv::Mat gray; cv::cvtColor(image, gray, COLOR_RGB2GRAY); <span class="synComment">// 文字認識クラスのインスタンス生成</span> <span class="synType">auto</span> ocr = cv::text::OCRTesseract::create(<span class="synConstant">&quot;(言語データのパス)/tessdata&quot;</span>, <span class="synConstant">&quot;eng&quot;</span>); std::string text; std::vector&lt;cv::Rect&gt; boxes; std::vector&lt;std::string&gt; words; vector&lt;<span class="synType">float</span>&gt; confidences; <span class="synComment">// 文字認識の実行</span> ocr-&gt;run(gray, text, &amp;boxes, &amp;words, &amp;confidences); <span class="synComment">// 結果出力</span> printf(<span class="synConstant">&quot;</span><span class="synSpecial">%s\n</span><span class="synConstant">&quot;</span>, text.c_str()); <span class="synComment">// 文字のかたまりごとに出力</span> printf(<span class="synConstant">&quot; 文字 | 位置 | 大きさ | 信頼度</span><span class="synSpecial">\n</span><span class="synConstant">&quot;</span>); printf(<span class="synConstant">&quot;-----------+------------+------------+----------</span><span class="synSpecial">\n</span><span class="synConstant">&quot;</span>); <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; boxes.size(); i++) { printf(<span class="synConstant">&quot;</span><span class="synSpecial">%-10s</span><span class="synConstant"> | (</span><span class="synSpecial">%3d</span><span class="synConstant">, </span><span class="synSpecial">%3d</span><span class="synConstant">) | (</span><span class="synSpecial">%3d</span><span class="synConstant">, </span><span class="synSpecial">%3d</span><span class="synConstant">) | </span><span class="synSpecial">%f\n</span><span class="synConstant">&quot;</span>, words[i].c_str(), boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height, confidences[i]); } } </pre> </div> <div class="section"> <h5>実行結果</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20141112/20141112103657.png" alt="f:id:whoopsidaisies:20141112103657p:plain" title="f:id:whoopsidaisies:20141112103657p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> </div> whoopsidaisies C#で細線化 AForge.NET hatenablog://entry/12921228815732929148 2014-09-15T09:45:49+09:00 2014-09-15T09:45:49+09:00 C#で画像の細線化処理を行って線画像を作成する.コンピュータビジョン等のライブラリであるAForge.NET Frameworkには,モルフォロジー処理が実装されているのでそれを利用する.細線化のアルゴリズムは以下のサイトあたりを参照. パターン認識の前処理に必要な二値画像の細線化:CodeZine 細線化アルゴリズム 画像処理ソリューション technotype AForge.NETのインストール Nuget経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「AForge」で検索.「AForge.Imaging」を選択してインストール… <p>C#で画像の細線化処理を行って線画像を作成する.コンピュータビジョン等のライブラリである<a href="https://code.google.com/p/aforge/">AForge.NET Framework</a>には,<a href="http://www.aforgenet.com/framework/features/morphology_filters.html">&#x30E2;&#x30EB;&#x30D5;&#x30A9;&#x30ED;&#x30B8;&#x30FC;&#x51E6;&#x7406;&#x304C;&#x5B9F;&#x88C5;&#x3055;&#x308C;&#x3066;&#x3044;&#x308B;</a>のでそれを利用する.</p><p>細線化のアルゴリズムは以下のサイトあたりを参照.<br /> <a href="http://codezine.jp/article/detail/98"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fcodezine.jp%2Farticle%2Fdetail%2F98" alt="" class="http-favicon" /></a><a href="http://codezine.jp/article/detail/98">&#x30D1;&#x30BF;&#x30FC;&#x30F3;&#x8A8D;&#x8B58;&#x306E;&#x524D;&#x51E6;&#x7406;&#x306B;&#x5FC5;&#x8981;&#x306A;&#x4E8C;&#x5024;&#x753B;&#x50CF;&#x306E;&#x7D30;&#x7DDA;&#x5316;&#xFF1A;CodeZine</a><br /> <a href="http://imagingsolution.blog107.fc2.com/blog-entry-138.html"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fimagingsolution.blog107.fc2.com%2Fblog-entry-138.html" alt="" class="http-favicon" /></a><a href="http://imagingsolution.blog107.fc2.com/blog-entry-138.html">&#x7D30;&#x7DDA;&#x5316;&#x30A2;&#x30EB;&#x30B4;&#x30EA;&#x30BA;&#x30E0; &#x753B;&#x50CF;&#x51E6;&#x7406;&#x30BD;&#x30EA;&#x30E5;&#x30FC;&#x30B7;&#x30E7;&#x30F3;</a><br /> <a href="http://www.technotype.net/tutorial/tutorial.php?fileId=%7BImage%20processing%7D&sectionId=%7Bthinning-filter%7D"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwww.technotype.net%2Ftutorial%2Ftutorial.php%3FfileId%3D%257BImage%2520processing%257D%26sectionId%3D%257Bthinning-filter%257D" alt="" class="http-favicon" /></a><a href="http://www.technotype.net/tutorial/tutorial.php?fileId=%7BImage%20processing%7D&sectionId=%7Bthinning-filter%7D">technotype</a><br /> </p> <div class="section"> <h3>AForge.NETのインストール</h3> <p>Nuget経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「AForge」で検索.「AForge.Imaging」を選択してインストール.</p> </div> <div class="section"> <h3>ソースコード</h3> <p>ヒット・ミス演算を行う<a href="http://www.aforgenet.com/framework/docs/html/027a2813-1cf8-c91f-3d9c-365f577afd63.htm">HitAndMiss&#x30AF;&#x30E9;&#x30B9;</a>を使う.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// using AForge.Imaging.Filters; をソースコードに書いておく</span> <span class="synComment">// 元画像の読み込み</span> var bmp = <span class="synStatement">new</span> Bitmap(<span class="synSpecial">@</span><span class="synConstant">&quot;moji.png&quot;</span>); pictureBox1.Image = bmp; <span class="synComment">// 二値化処理</span> var gray = <span class="synStatement">new</span> Grayscale(<span class="synConstant">0.2125</span>,<span class="synConstant">0.7154</span>,<span class="synConstant">0.0721</span>).Apply(bmp); var binary = <span class="synStatement">new</span> Threshold().Apply(gray); pictureBox2.Image = binary; <span class="synComment">// 細線化用の8つのフィルタを作成</span> var filterSequence = <span class="synStatement">new</span> FiltersSequence(); filterSequence.Add(<span class="synStatement">new</span> HitAndMiss( <span class="synStatement">new</span> <span class="synType">short</span>[,] { { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, { -<span class="synConstant">1</span>, <span class="synConstant">1</span>, -<span class="synConstant">1</span> }, { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span> } }, HitAndMiss.Modes.Thinning)); filterSequence.Add(<span class="synStatement">new</span> HitAndMiss( <span class="synStatement">new</span> <span class="synType">short</span>[,] { { -<span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, { -<span class="synConstant">1</span>, <span class="synConstant">1</span>, -<span class="synConstant">1</span> } }, HitAndMiss.Modes.Thinning)); filterSequence.Add(<span class="synStatement">new</span> HitAndMiss( <span class="synStatement">new</span> <span class="synType">short</span>[,] { { <span class="synConstant">1</span>, -<span class="synConstant">1</span>, <span class="synConstant">0</span> }, { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, { <span class="synConstant">1</span>, -<span class="synConstant">1</span>, <span class="synConstant">0</span> } }, HitAndMiss.Modes.Thinning)); filterSequence.Add(<span class="synStatement">new</span> HitAndMiss( <span class="synStatement">new</span> <span class="synType">short</span>[,] { { -<span class="synConstant">1</span>, <span class="synConstant">1</span>, -<span class="synConstant">1</span> }, { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, { -<span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> } }, HitAndMiss.Modes.Thinning)); filterSequence.Add(<span class="synStatement">new</span> HitAndMiss( <span class="synStatement">new</span> <span class="synType">short</span>[,] { { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span> }, { -<span class="synConstant">1</span>, <span class="synConstant">1</span>, -<span class="synConstant">1</span> }, { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> } }, HitAndMiss.Modes.Thinning)); filterSequence.Add(<span class="synStatement">new</span> HitAndMiss( <span class="synStatement">new</span> <span class="synType">short</span>[,] { { -<span class="synConstant">1</span>, <span class="synConstant">1</span>, -<span class="synConstant">1</span> }, { <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span> }, { <span class="synConstant">0</span>, <span class="synConstant">0</span>, -<span class="synConstant">1</span> } }, HitAndMiss.Modes.Thinning)); filterSequence.Add(<span class="synStatement">new</span> HitAndMiss( <span class="synStatement">new</span> <span class="synType">short</span>[,] { { <span class="synConstant">0</span>, -<span class="synConstant">1</span>, <span class="synConstant">1</span> }, { <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span> }, { <span class="synConstant">0</span>, -<span class="synConstant">1</span>, <span class="synConstant">1</span> } }, HitAndMiss.Modes.Thinning)); filterSequence.Add(<span class="synStatement">new</span> HitAndMiss( <span class="synStatement">new</span> <span class="synType">short</span>[,] { { <span class="synConstant">0</span>, <span class="synConstant">0</span>, -<span class="synConstant">1</span> }, { <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span> }, { -<span class="synConstant">1</span>, <span class="synConstant">1</span>, -<span class="synConstant">1</span> } }, HitAndMiss.Modes.Thinning)); <span class="synComment">// フィルタ処理の繰り返し回数を指定</span> var filter = <span class="synStatement">new</span> FilterIterator(filterSequence, <span class="synConstant">20</span>); <span class="synComment">// 細線化処理の実行</span> var thinned = filter.Apply(binary); pictureBox3.Image = thinned; </pre><p>実行結果.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140915/20140915092901.png" alt="f:id:whoopsidaisies:20140915092901p:plain" title="f:id:whoopsidaisies:20140915092901p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> whoopsidaisies C#でGISデータ(shpファイル)を開く DotSpatialによる方法 hatenablog://entry/12921228815730750295 2014-09-15T01:10:17+09:00 2014-09-15T01:10:17+09:00 DotSpatialは.NET向けのオープンソースの地理情報システムライブラリである.これを使ってGISで用いられるshpファイル(とセットのshxファイルとdbfファイル)を読み込む. DotSpatialのインストール Nuget経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「DotSpatial」で検索.たくさん出てくるが,ここでは「DotSpatial.Controls」選択してインストール. Mapコントロールの追加 GISデータ表示用のコントロールが用意されているのでそれを使ってみる.まず,一度プロジェクトをビルドする.… <p><a href="http://dotspatial.codeplex.com/">DotSpatial</a>は.NET向けのオープンソースの地理情報システムライブラリである.これを使ってGISで用いられるshpファイル(とセットのshxファイルとdbfファイル)を読み込む.</p> <div class="section"> <h3>DotSpatialのインストール</h3> <p>Nuget経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「DotSpatial」で検索.たくさん出てくるが,ここでは「DotSpatial.Controls」選択してインストール.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140914/20140914212117.png" alt="f:id:whoopsidaisies:20140914212117p:plain" title="f:id:whoopsidaisies:20140914212117p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>Mapコントロールの追加</h3> <p>GISデータ表示用のコントロールが用意されているのでそれを使ってみる.</p><p>まず,一度プロジェクトをビルドする.そうするとDotSpatialのDLLが実行ファイルのディレクトリにコピーされる.</p><p>ツールボックスの適当なところでクリックして「アイテムの選択(I)...」を選択.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140914/20140914212749.png" alt="f:id:whoopsidaisies:20140914212749p:plain" title="f:id:whoopsidaisies:20140914212749p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>「.NET Framework コンポーネント」タブの「参照(B)...」ボタンを押して,「(実行ファイルのパス)\DotSpatial.Controls.dll」を選択したらOK.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140914/20140914212821.png" alt="f:id:whoopsidaisies:20140914212821p:plain" title="f:id:whoopsidaisies:20140914212821p:plain" class="hatena-fotolife" itemprop="image"></span></p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140914/20140914213930.png" alt="f:id:whoopsidaisies:20140914213930p:plain" title="f:id:whoopsidaisies:20140914213930p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>そうすると「Map」というコントロールが追加されているのでフォームに追加する.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140914/20140914213818.png" alt="f:id:whoopsidaisies:20140914213818p:plain" title="f:id:whoopsidaisies:20140914213818p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>シェープファイルの読み込み</h3> <p>シェープファイルは「<a href="http://www.esrij.com/products/data/japan-shp/"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwww.esrij.com%2Fproducts%2Fdata%2Fjapan-shp%2F" alt="" class="http-favicon" /></a><a href="http://www.esrij.com/products/data/japan-shp/">&#x5168;&#x56FD;&#x5E02;&#x533A;&#x753A;&#x6751;&#x754C;&#x30C7;&#x30FC;&#x30BF; | &#x30C7;&#x30FC;&#x30BF;&#x88FD;&#x54C1;&nbsp;|&nbsp;&#x88FD;&#x54C1;&nbsp;|&nbsp;ESRI&#x30B8;&#x30E3;&#x30D1;&#x30F3;&#x682A;&#x5F0F;&#x4F1A;&#x793E;</a>」でESRI Japanが配布している全国市区町村界データを使う.ダウンロードして解答したら以下のコードを追加する.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>map1.AddLayer(<span class="synSpecial">@</span><span class="synConstant">&quot;D:\Users\whoops\Downloads\japan_ver72\japan_ver72.shp&quot;</span>); </pre><p>実行すると以下のように地図が表示される.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140914/20140914214517.png" alt="f:id:whoopsidaisies:20140914214517p:plain" title="f:id:whoopsidaisies:20140914214517p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>属性情報の表示 Infoモード</h3> <p>上の状態だと地図が表示されるだけで何もできないためMapコントロールのモードを変える.以下のようにコードを追加してInfoモードにする.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>map1.AddLayer(<span class="synSpecial">@</span><span class="synConstant">&quot;D:\Users\whoops\Downloads\japan_ver72\japan_ver72.shp&quot;</span>); map1.FunctionMode = DotSpatial.Controls.FunctionMode.Info; </pre><p>これで実行すると以下のようにクリックした位置の市町村の情報を見れる.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140914/20140914214930.png" alt="f:id:whoopsidaisies:20140914214930p:plain" title="f:id:whoopsidaisies:20140914214930p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>領域の選択 Selectモード</h3> <p>Selectモードににするとドラッグで領域指定できる.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>map1.FunctionMode = DotSpatial.Controls.FunctionMode.Select; </pre><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140915/20140915002531.png" alt="f:id:whoopsidaisies:20140915002531p:plain" title="f:id:whoopsidaisies:20140915002531p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>選択しただけだと何も表示されないので,TextBoxに選択された領域の情報を表示してみる.MAPコントロールのMouseUpイベントを追加して以下のコードを書き込む.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synType">private</span> <span class="synType">void</span> map1_MouseUp(<span class="synType">object</span> sender, MouseEventArgs e) { textBox1.Text = <span class="synConstant">&quot;&quot;</span>; <span class="synComment">// MAPコントロールが保持しているレイヤーデータを取得</span> var featureLayer = map1.Layers[<span class="synConstant">0</span>] <span class="synStatement">as</span> DotSpatial.Symbology.FeatureLayer; <span class="synComment">// すべてのデータについてループ</span> <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; featureLayer.DrawnStates.Length; ++i) { <span class="synComment">// 選択されているかどうか判別</span> <span class="synStatement">if</span> (featureLayer.DrawnStates[i].Selected == <span class="synConstant">true</span>) { <span class="synComment">// i番目の属性情報取得</span> var feature = featureLayer.FeatureSet.GetFeature(i); <span class="synComment">// DataRowからフィールド名でアクセス</span> textBox1.Text += System.String.Format( <span class="synConstant">&quot;{0} : {1} {2} {3}人&quot;</span>, feature.DataRow[<span class="synConstant">&quot;JCODE&quot;</span>], feature.DataRow[<span class="synConstant">&quot;KEN&quot;</span>], feature.DataRow[<span class="synConstant">&quot;SIKUCHOSON&quot;</span>], feature.DataRow[<span class="synConstant">&quot;P_NUM&quot;</span>] ) + System.Environment.NewLine; } } } </pre><p>選択されているかどうかはレイヤーデータの<a href="http://www.nudoq.org/#!/Packages/DotSpatial.Symbology/DotSpatial.Symbology/LabelLayer/P/DrawnStates">DrawnStates</a>プロパティに格納されている.</p><p>属性情報は<a href="https://dotspatial.codeplex.com/wikipage?title=DotSpatial.Data.Vectors.Beginner.FeatureSet">FeatureSet</a>プロパティに格納されていて<a href="http://www.nudoq.org/#!/Packages/DotSpatial.Data/DotSpatial.Data/PolygonShapefile/M/GetFeature">GetFeature</a>メソッドで指定した番号のデータを取得できる.</p><p>各属性情報へは,DataRawにフィールド名を指定することで取得できる.このサンプルで使っているフィールド名は「<a href="http://www.esrij.com/products/data/japan-shp/">&#x5168;&#x56FD;&#x5E02;&#x533A;&#x753A;&#x6751;&#x754C;&#x30C7;&#x30FC;&#x30BF; | &#x30C7;&#x30FC;&#x30BF;&#x88FD;&#x54C1;&nbsp;|&nbsp;&#x88FD;&#x54C1;&nbsp;|&nbsp;ESRI&#x30B8;&#x30E3;&#x30D1;&#x30F3;&#x682A;&#x5F0F;&#x4F1A;&#x793E;</a>」を参照.</p><p>実行してドラッグで領域選択すると以下のようにTextBoxに情報が表示される.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140915/20140915004858.png" alt="f:id:whoopsidaisies:20140915004858p:plain" title="f:id:whoopsidaisies:20140915004858p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>MAPコントロールなしで読み込み</h3> <p>MAPコントロールを配置しなくても<a href="http://www.nudoq.org/#!/Packages/DotSpatial.Data/DotSpatial.Data/DataManager">DataManager</a>クラスの<a href="http://www.nudoq.org/#!/Packages/DotSpatial.Data/DotSpatial.Data/DataManager/M/OpenFile">OpenFile</a>メソッドを使えばシェープファイルは読み込める.</p><p>以下にシェープファイルを読み込んで,0番目のデータの座標を出力するコードを載せる.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// シェープファイルの読み込み</span> var layer = DotSpatial.Data.DataManager.DefaultDataManager.OpenFile(<span class="synSpecial">@</span><span class="synConstant">&quot;D:\Users\whoops\Downloads\japan_ver72\japan_ver72.shp&quot;</span>) <span class="synStatement">as</span> DotSpatial.Data.FeatureSet; <span class="synComment">// 0番目のデータの座標を表示</span> <span class="synStatement">foreach</span> (var cordinate <span class="synStatement">in</span> layer.GetFeature(<span class="synConstant">0</span>).Coordinates) { Console.WriteLine(cordinate.ToString()); } </pre><p>実行結果<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140915/20140915010455.png" alt="f:id:whoopsidaisies:20140915010455p:plain" title="f:id:whoopsidaisies:20140915010455p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>コントロールを使わない方法だけを使う場合NuGetで「DotSpatial.Data」をインストールすればできる.</p> </div> whoopsidaisies SVGアニメーションで初音ミクの一筆書き hatenablog://entry/12921228815732826994 2014-09-13T22:22:26+09:00 2014-09-13T22:22:26+09:00 SVGによるアニメーションの勉強メモと,作った初音ミクの一筆書きアニメーション.アニメーションをSVGのanimateMotion要素と,CSSのanimationプロパティを使った.本当はCSS使わないでやりたかったのだけどそれだと面倒くさそうだったのでCSSも使った.元画像は以下のサイトから持ってきた. piapro(ピアプロ)|イラスト「一筆書きで 初音ミクを 描きました」 以下が作ったアニメーション.SVGとCSSのアニメーションの同期の取り方がわからなかったので,読み込みの度にタイミングが変わってしまう. ※SVGファイルを置くのに借りていたレンタルサーバーの期限が切れてしまったため… <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>によるアニメーションの勉強メモと,作った<a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%E9%B2%BB%A5%DF%A5%AF">初音ミク</a>の一筆書きアニメーション.</p><p>アニメーションを<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>のanimateMotion要素と,<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>のanimationプロパティを使った.本当は<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>使わないでやりたかったのだけどそれだと面倒くさそうだったので<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>も使った.</p><p>元画像は以下のサイトから持ってきた.<br /> <a href="http://piapro.jp/t/zL1d"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fpiapro.jp%2Ft%2FzL1d" alt="" class="http-favicon" /></a><a href="http://piapro.jp/t/zL1d">piapro(&#x30D4;&#x30A2;&#x30D7;&#x30ED;)|&#x30A4;&#x30E9;&#x30B9;&#x30C8;&#x300C;&#x4E00;&#x7B46;&#x66F8;&#x304D;&#x3067; &#x521D;&#x97F3;&#x30DF;&#x30AF;&#x3092; &#x63CF;&#x304D;&#x307E;&#x3057;&#x305F;&#x300D;</a></p><p><del><br /> 以下が作ったアニメーション.<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>と<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>のアニメーションの同期の取り方がわからなかったので,読み込みの度にタイミングが変わってしまう.</del><br /> ※<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>ファイルを置くのに借りていた<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%D0%A1%BC">レンタルサーバー</a>の期限が切れてしまったため、暇なとき別のところにアップロードしなおします。</p> <div class="section"> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a> animateMotion要素</h3> <p>赤い円を移動させるのには,<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>の<a href="https://developer.mozilla.org/ja/docs/Web/SVG/Element/animateMotion">animateMotion&#x8981;&#x7D20;</a>を使った.</p><p>animateMotion要素を用いると,図形をpathで指定した任意の曲線に沿って移動させることが出来る.また,<a href="https://developer.mozilla.org/ja/docs/Web/SVG/Element/mpath">mpath&#x8981;&#x7D20;</a>によって以下のようにpathの参照が可能.</p> <blockquote cite="https://developer.mozilla.org/ja/docs/Web/SVG/Element/animateMotion"> <pre class="code lang-xml" data-lang="xml" data-unlink><span class="synIdentifier">&lt;path </span><span class="synType">d</span>=<span class="synConstant">&quot;M10,110 A120,120 -45 0,1 110 10 A120,120 -45 0,1 10,110&quot;</span> <span class="synIdentifier"> </span><span class="synType">stroke</span>=<span class="synConstant">&quot;lightgrey&quot;</span><span class="synIdentifier"> </span><span class="synType">stroke-width</span>=<span class="synConstant">&quot;2&quot;</span><span class="synIdentifier"> </span> <span class="synIdentifier"> </span><span class="synType">fill</span>=<span class="synConstant">&quot;none&quot;</span><span class="synIdentifier"> </span><span class="synType">id</span>=<span class="synConstant">&quot;theMotionPath&quot;</span><span class="synIdentifier">/&gt;</span> <span class="synIdentifier">&lt;circle </span><span class="synType">cx</span>=<span class="synConstant">&quot;10&quot;</span><span class="synIdentifier"> </span><span class="synType">cy</span>=<span class="synConstant">&quot;110&quot;</span><span class="synIdentifier"> </span><span class="synType">r</span>=<span class="synConstant">&quot;3&quot;</span><span class="synIdentifier"> </span><span class="synType">fill</span>=<span class="synConstant">&quot;lightgrey&quot;</span><span class="synIdentifier"> /&gt;</span> <span class="synIdentifier">&lt;circle </span><span class="synType">cx</span>=<span class="synConstant">&quot;110&quot;</span><span class="synIdentifier"> </span><span class="synType">cy</span>=<span class="synConstant">&quot;10&quot;</span><span class="synIdentifier"> </span><span class="synType">r</span>=<span class="synConstant">&quot;3&quot;</span><span class="synIdentifier"> </span><span class="synType">fill</span>=<span class="synConstant">&quot;lightgrey&quot;</span><span class="synIdentifier"> /&gt;</span> <span class="synComment">&lt;!-- Here is a red circle which will be moved along the motion path. --&gt;</span> <span class="synIdentifier">&lt;circle </span><span class="synType">cx</span>=<span class="synConstant">&quot;&quot;</span><span class="synIdentifier"> </span><span class="synType">cy</span>=<span class="synConstant">&quot;&quot;</span><span class="synIdentifier"> </span><span class="synType">r</span>=<span class="synConstant">&quot;5&quot;</span><span class="synIdentifier"> </span><span class="synType">fill</span>=<span class="synConstant">&quot;red&quot;</span><span class="synIdentifier">&gt;</span> <span class="synComment">&lt;!-- Define the motion path animation --&gt;</span> <span class="synIdentifier">&lt;animateMotion </span><span class="synType">dur</span>=<span class="synConstant">&quot;6s&quot;</span><span class="synIdentifier"> </span><span class="synType">repeatCount</span>=<span class="synConstant">&quot;indefinite&quot;</span><span class="synIdentifier">&gt;</span> <span class="synIdentifier">&lt;mpath </span><span class="synType">xlink</span><span class="synComment">:</span><span class="synType">href</span>=<span class="synConstant">&quot;#theMotionPath&quot;</span><span class="synIdentifier">/&gt;</span> <span class="synIdentifier">&lt;/animateMotion&gt;</span> <span class="synIdentifier">&lt;/circle&gt;</span> </pre> <cite><a href="https://developer.mozilla.org/ja/docs/Web/SVG/Element/animateMotion">animateMotion - SVG | MDN</a></cite> </blockquote> </div> <div class="section"> <h3><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a> animate要素</h3> <p>線を描いていく様子は,<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>の<a href="http://css-tricks.com/svg-line-animation-works/">animate&#x8981;&#x7D20;&#x3092;&#x4F7F;&#x3063;&#x3066;&#x7834;&#x7DDA;&#x306E;&#x9593;&#x9694;&#x3092;&#x5909;&#x3048;&#x308B;&#x65B9;&#x6CD5;</a>を使った.<br /> 破線の間隔が変わることで線が伸びて行っているように見えるようだ.</p> <blockquote cite="http://css-tricks.com/svg-line-animation-works/"> <p><img src="http://cdn.css-tricks.com/wp-content/uploads/2014/02/animate-stroke-full.gif"></img></p> <cite><a href="http://css-tricks.com/svg-line-animation-works/">How SVG Line Animation Works | CSS-Tricks</a></cite> </blockquote> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/CSS">CSS</a>に以下のように描いてやるといいようだが,stroke-dasharrayやstroke-dashoffsetの値を線の長さくらいにしなくてはならないらしく少し面倒.</p> <pre class="code lang-css" data-lang="css" data-unlink>path <span class="synIdentifier">{</span> stroke-dasharray: <span class="synConstant">1000</span>; stroke-dashoffset: <span class="synConstant">1000</span>; animation: dash <span class="synConstant">5s</span> linear forwards; <span class="synIdentifier">}</span> @keyframes dash <span class="synIdentifier">{</span> to { stroke-dashoffset: <span class="synConstant">0</span>; <span class="synIdentifier">}</span> <span class="synError">}</span> </pre> </div> <div class="section"> <h3>d3.jsで作成</h3> <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/%BD%E9%B2%BB%A5%DF%A5%AF">初音ミク</a>の座標データは画像からこつこつと抽出した.以下からダウンロード可能.<br /> <a href="http://whoopsidaisies.site-station.net/blog/miku.csv">http://whoopsidaisies.site-station.net/blog/miku.csv</a></p><p><a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>直打ちでもよかったが,せっかくなのでd3.jsで<a class="keyword" href="http://d.hatena.ne.jp/keyword/CSV">CSV</a>ファイルを読み込んで<a class="keyword" href="http://d.hatena.ne.jp/keyword/SVG">SVG</a>を吐き出した.</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink>d3.csv(<span class="synConstant">&quot;miku2.csv&quot;</span>, <span class="synIdentifier">function</span> (data) <span class="synIdentifier">{</span> <span class="synIdentifier">var</span> line = d3.svg.line() .x(<span class="synIdentifier">function</span> (d) <span class="synIdentifier">{</span> <span class="synStatement">return</span> Math.round(d.x * 10) / 10; <span class="synIdentifier">}</span>) .y(<span class="synIdentifier">function</span> (d) <span class="synIdentifier">{</span> <span class="synStatement">return</span> Math.round(d.y * 10) / 10; <span class="synIdentifier">}</span>) .interpolate(<span class="synConstant">&quot;linear&quot;</span>); <span class="synIdentifier">var</span> svg = d3.select(<span class="synConstant">&quot;body&quot;</span>).append(<span class="synConstant">&quot;svg&quot;</span>).attr(<span class="synConstant">&quot;width&quot;</span>, 700).attr(<span class="synConstant">&quot;height&quot;</span>, 900); <span class="synIdentifier">var</span> path = svg.append(<span class="synConstant">&quot;path&quot;</span>) .attr(<span class="synIdentifier">{</span> <span class="synConstant">&quot;d&quot;</span>: line(data), <span class="synConstant">&quot;stroke&quot;</span>: <span class="synConstant">&quot;black&quot;</span>, <span class="synConstant">&quot;stroke-width&quot;</span>: 2, <span class="synConstant">&quot;fill&quot;</span>: <span class="synConstant">&quot;none&quot;</span>, <span class="synConstant">&quot;id&quot;</span>: <span class="synConstant">&quot;mikupath&quot;</span> <span class="synIdentifier">}</span>); svg.append(<span class="synConstant">&quot;circle&quot;</span>) .attr(<span class="synIdentifier">{</span> <span class="synConstant">&quot;cx&quot;</span>: <span class="synConstant">&quot;&quot;</span>, <span class="synConstant">&quot;cy&quot;</span>: <span class="synConstant">&quot;&quot;</span>, <span class="synConstant">&quot;r&quot;</span>: <span class="synConstant">&quot;5&quot;</span>, <span class="synConstant">&quot;fill&quot;</span>: <span class="synConstant">&quot;red&quot;</span> <span class="synIdentifier">}</span>) .append(<span class="synConstant">&quot;animateMotion&quot;</span>) .attr(<span class="synIdentifier">{</span> <span class="synConstant">&quot;dur&quot;</span>: <span class="synConstant">&quot;20s&quot;</span>, <span class="synConstant">&quot;repeatCount&quot;</span>: <span class="synConstant">&quot;indefinite&quot;</span> <span class="synIdentifier">}</span>) .append(<span class="synConstant">&quot;mpath&quot;</span>) .attr(<span class="synConstant">&quot;xlink:href&quot;</span>, <span class="synConstant">&quot;#mikupath&quot;</span>); <span class="synIdentifier">}</span>); </pre><p><del><br /> <a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%BD%A1%BC%A5%B9%A5%B3%A1%BC%A5%C9">ソースコード</a>全文は以下.<br /> <a href="http://whoopsidaisies.site-station.net/blog/mikuanimation2.html">http://whoopsidaisies.site-station.net/blog/mikuanimation2.html</a><br /> </del><br /> <del><br /> 実行後のhtmlは以下.<br /> <a href="http://whoopsidaisies.site-station.net/blog/mikuanimation.html">http://whoopsidaisies.site-station.net/blog/mikuanimation.html</a><br /> </del><br /> ※<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%EC%A5%F3%A5%BF%A5%EB%A5%B5%A1%BC%A5%D0%A1%BC">レンタルサーバー</a>の期限が切れてしまったため、暇なとき別のところにアップロードしなおします。</p> </div> whoopsidaisies PowerPointのオートシェイプで好きな関数の曲線を作る C# NetOfficeによる方法 hatenablog://entry/12921228815732529471 2014-09-11T12:43:18+09:00 2014-09-11T12:43:18+09:00 sin(x)/xのオートシェイプオートシェイプできれいな波形を作りたいときがたまにあるのだけど,C#を使って上の画像みたいにsin(x)/xのオートシェイプをわりときれいに作れたので手順をまとめる.試した環境はPowerPoint2010とVisual Studio 2013.バージョンが違うと少し変わる可能性はあると思う.(わざわざC#でやらずともVBAマクロでも同じことは出来るけど,VBAは苦手なのでC#でやる.VBAでのやり方も後述します)出来上がったPowerPointファイルを以下からダウンロードできるようにしておいた. sinc.pptx - Google ドライブ NetOffi… <p><figure><br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140911/20140911101713.png" alt="f:id:whoopsidaisies:20140911101713p:plain" title="f:id:whoopsidaisies:20140911101713p:plain" class="hatena-fotolife" itemprop="image"></span><br /> <figcaption align="center">sin(x)/xのオートシェイプ</figcaption></figure></p><p>オートシェイプできれいな波形を作りたいときがたまにあるのだけど,C#を使って上の画像みたいにsin(x)/xのオートシェイプをわりときれいに作れたので手順をまとめる.</p><p>試した環境はPowerPoint2010とVisual Studio 2013.バージョンが違うと少し変わる可能性はあると思う.(わざわざC#でやらずともVBAマクロでも同じことは出来るけど,VBAは苦手なのでC#でやる.VBAでのやり方も後述します)</p><p>出来上がったPowerPointファイルを以下からダウンロードできるようにしておいた.<br /> <a href="https://docs.google.com/file/d/0B8I67X8vyAXOSFJLaTlIOGhsMGM/edit"><img src="http://cdn-ak.favicon.st-hatena.com/?url=https%3A%2F%2Fdocs.google.com%2Ffile%2Fd%2F0B8I67X8vyAXOSFJLaTlIOGhsMGM%2Fedit" alt="" class="http-favicon" /></a><a href="https://docs.google.com/file/d/0B8I67X8vyAXOSFJLaTlIOGhsMGM/edit">sinc.pptx - Google &#x30C9;&#x30E9;&#x30A4;&#x30D6;</a><br /> </p> <div class="section"> <h3>NetOffice.PowerPointのインストール</h3> <p>以前「<a href="http://whoopsidaisies.hatenablog.com/entry/2014/06/19/101032">C#&#x3067;Excel&#x30D5;&#x30A1;&#x30A4;&#x30EB;&#x3092;&#x4F5C;&#x6210;&#x30FB;&#x30B0;&#x30E9;&#x30D5;&#x3092;&#x633F;&#x5165;&#x3059;&#x308B; NetOffice&#x306B;&#x3088;&#x308B;&#x65B9;&#x6CD5; - whoopsidaisies&#39;s diary</a>」で紹介した,<a href="http://netoffice.codeplex.com/">NetOffice</a>という.NET用のライブラリを使うとPowerPoint等にアクセスして色々出来るのでそれを利用する.</p><p>NetOfficeはNuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「NetOffice.PowerPoint」を検索してインストール.</p> </div> <div class="section"> <h3>ソースコード</h3> <p>以下にソースコードを載せる.スライドを作って<a href="http://msdn.microsoft.com/ja-jp/library/office/ff744765(v=office.15).aspx">AddCurve</a>メソッドで曲線を追加しているだけである.</p><p>AddCurveメソッドの引数として,float[(点の数),2]に座標を格納して渡す.この点の座標を元にベジェ曲線を描くようである.<a href="http://msdn.microsoft.com/ja-jp/library/office/ff744765(v=office.15).aspx">&#x70B9;&#x306E;&#x6570;&#x306F;3n+1&#x500B;</a>にしないと止まるので注意.</p><p>点の座標はスライドの左上が(0,0)でピクセルで指定する.スライドのオブジェクトの<a href="http://msdn.microsoft.com/ja-jp/library/office/ff745135(v=office.15).aspx">PageSetup</a>プロパティにスライドの幅と高さが格納されているのでそれを元に大きさを調整した.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synType">static</span> <span class="synType">void</span> Main(<span class="synType">string</span>[] args) { <span class="synComment">// パワーポイントを開く</span> <span class="synStatement">using</span> (var app = <span class="synStatement">new</span> NetOffice.PowerPointApi.Application()) { <span class="synComment">// プレゼンテーションの作成</span> var presentation = app.Presentations.Add(); <span class="synComment">// スライドの追加</span> var slide = presentation.Slides.Add(<span class="synConstant">1</span>, NetOffice.PowerPointApi.Enums.PpSlideLayout.ppLayoutBlank); <span class="synComment">// sin(x)/xの座標を得る</span> var sinc = GetSinc(presentation.PageSetup.SlideWidth, presentation.PageSetup.SlideHeight); <span class="synComment">// 座標からベジェ曲線を描画する</span> <span class="synComment">// 引数はfloatの二次元配列.座標の数は6n+1個じゃないといけないため注意.</span> slide.Shapes.AddCurve(sinc); <span class="synComment">// プレゼンテーションの保存</span> presentation.SaveAs(<span class="synSpecial">@</span><span class="synConstant">&quot;D:\a.pptx&quot;</span>); <span class="synComment">// プレゼンテーションファイルを閉じる</span> presentation.Close(); <span class="synComment">// パワーポイントの終了 作成したファイル以外も閉じられるので注意</span> <span class="synComment">//app.Quit();</span> } } <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">summary</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// sin(x)/x関数の座標をスライドの大きさに合わせて拡大,</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;/</span><span class="synStatement">summary</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">param</span><span class="synIdentifier"> </span><span class="synType">name</span>=<span class="synConstant">&quot;slideWidth&quot;</span><span class="synIdentifier">&gt;</span><span class="synComment">スライドの幅</span><span class="synIdentifier">&lt;/</span><span class="synStatement">param</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">param</span><span class="synIdentifier"> </span><span class="synType">name</span>=<span class="synConstant">&quot;slideHeight&quot;</span><span class="synIdentifier">&gt;</span><span class="synComment">スライドの高さ</span><span class="synIdentifier">&lt;/</span><span class="synStatement">param</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">returns</span><span class="synIdentifier">&gt;</span><span class="synComment">sin(x)/x関数を描くための点の座標</span><span class="synIdentifier">&lt;/</span><span class="synStatement">returns</span><span class="synIdentifier">&gt;</span> <span class="synType">static</span> <span class="synType">float</span>[,] GetSinc(<span class="synType">float</span> slideWidth, <span class="synType">float</span> slideHeight) { <span class="synComment">// xが-4π~4πまでのsin(x)/xを求める.601点.</span> var xs = Enumerable.Range(-<span class="synConstant">300</span>, <span class="synConstant">601</span>).Select(x =&gt; x * <span class="synConstant">4</span> * Math.PI / <span class="synConstant">300</span>); var ys = xs.Select(x =&gt; x != <span class="synConstant">0</span> ? Math.Sin(x) / x : <span class="synConstant">1</span>); <span class="synComment">// PowerPointのスライドのサイズに合わせて移動・拡大をする</span> <span class="synComment">// 中心座標</span> var cx = slideWidth / <span class="synConstant">2</span>; var cy = slideHeight / <span class="synConstant">2</span>; <span class="synComment">// オブジェクトのだいたいの大きさ</span> var width = slideWidth * <span class="synConstant">0.8</span>; var height = slideHeight * <span class="synConstant">0.8</span>; var pptXs = xs.Select(x =&gt; x / (<span class="synConstant">4</span> * Math.PI) * width / <span class="synConstant">2</span> + cx).ToArray(); var pptYs = ys.Select(y =&gt; -y * height / <span class="synConstant">2</span> + cy).ToArray(); <span class="synComment">// AddCurveメソッドに渡すためにfloatの2次元配列に代入する</span> var sinc = <span class="synStatement">new</span> <span class="synType">float</span>[pptXs.Length, <span class="synConstant">2</span>]; <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; pptXs.Length; ++ i) { sinc[i, <span class="synConstant">0</span>] = (<span class="synType">float</span>)pptXs[i]; sinc[i, <span class="synConstant">1</span>] = (<span class="synType">float</span>)pptYs[i]; } <span class="synStatement">return</span> sinc; } </pre><p>実行すると,記事の最初の画像のpptxファイルが作成される.GetSincメソッドの部分を適当な座標を格納をするように変えれば自分の好きな曲線を引ける.</p><p>ちなみに出来た曲線はオートシェイプなので,以下の画像のように線の太さとか種類とか色とかも簡単に変えられる.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140911/20140911115617.png" alt="f:id:whoopsidaisies:20140911115617p:plain" title="f:id:whoopsidaisies:20140911115617p:plain" class="hatena-fotolife" itemprop="image"></span><br /> 拡大してもきれい.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140911/20140911115623.png" alt="f:id:whoopsidaisies:20140911115623p:plain" title="f:id:whoopsidaisies:20140911115623p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>VBAマクロでのやり方</h3> <p>記事の最初にも述べたが,C#を使わずともVBAマクロで同じことが出来る.以下に参考になるコードを載せる(<a href="http://msdn.microsoft.com/ja-jp/library/office/ff744765(v=office.15).aspx">&#x3053;&#x3053;</a>のサンプル見やすくしただけだけど).</p><p>これの点の座標を引きたい曲線の座標にしてやればOK.</p> <pre class="code lang-vb" data-lang="vb" data-unlink><span class="synStatement">Sub</span> DrawCurve<span class="synStatement">()</span> <span class="synComment"> ' 1枚目のスライドのオブジェクトを得る</span> <span class="synStatement">Dim</span> slide <span class="synStatement">As</span> PowerPoint<span class="synStatement">.</span>slide <span class="synStatement">Set</span> slide <span class="synStatement">=</span> ActivePresentation<span class="synStatement">.</span>Slides<span class="synStatement">(</span><span class="synConstant">1</span><span class="synStatement">)</span> <span class="synComment"> ' ベジェ曲線を引くための点の座標を配列に格納</span> <span class="synComment"> ' ここの座標の値を適当に変えてやれば好きな曲線が引ける</span> <span class="synStatement">Dim</span> points<span class="synStatement">(</span><span class="synConstant">1</span> <span class="synStatement">To</span> <span class="synConstant">7</span><span class="synStatement">,</span> <span class="synConstant">1</span> <span class="synStatement">To</span> <span class="synConstant">2</span><span class="synStatement">)</span> <span class="synStatement">As</span> <span class="synType">Single</span> points<span class="synStatement">(</span><span class="synConstant">1</span><span class="synStatement">,</span> <span class="synConstant">1</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">0</span> points<span class="synStatement">(</span><span class="synConstant">1</span><span class="synStatement">,</span> <span class="synConstant">2</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">0</span> points<span class="synStatement">(</span><span class="synConstant">2</span><span class="synStatement">,</span> <span class="synConstant">1</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">72</span> points<span class="synStatement">(</span><span class="synConstant">2</span><span class="synStatement">,</span> <span class="synConstant">2</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">72</span> points<span class="synStatement">(</span><span class="synConstant">3</span><span class="synStatement">,</span> <span class="synConstant">1</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">100</span> points<span class="synStatement">(</span><span class="synConstant">3</span><span class="synStatement">,</span> <span class="synConstant">2</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">40</span> points<span class="synStatement">(</span><span class="synConstant">4</span><span class="synStatement">,</span> <span class="synConstant">1</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">20</span> points<span class="synStatement">(</span><span class="synConstant">4</span><span class="synStatement">,</span> <span class="synConstant">2</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">50</span> points<span class="synStatement">(</span><span class="synConstant">5</span><span class="synStatement">,</span> <span class="synConstant">1</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">90</span> points<span class="synStatement">(</span><span class="synConstant">5</span><span class="synStatement">,</span> <span class="synConstant">2</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">120</span> points<span class="synStatement">(</span><span class="synConstant">6</span><span class="synStatement">,</span> <span class="synConstant">1</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">60</span> points<span class="synStatement">(</span><span class="synConstant">6</span><span class="synStatement">,</span> <span class="synConstant">2</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">30</span> points<span class="synStatement">(</span><span class="synConstant">7</span><span class="synStatement">,</span> <span class="synConstant">1</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">150</span> points<span class="synStatement">(</span><span class="synConstant">7</span><span class="synStatement">,</span> <span class="synConstant">2</span><span class="synStatement">)</span> <span class="synStatement">=</span> <span class="synConstant">90</span> <span class="synComment"> ' 曲線の追加</span> slide<span class="synStatement">.</span>Shapes<span class="synStatement">.</span>AddCurve SafeArrayOfPoints:<span class="synStatement">=</span>points <span class="synStatement">End</span> <span class="synStatement">Sub</span> </pre> </div> whoopsidaisies OpenCVでDeepFlow hatenablog://entry/12921228815730868159 2014-08-21T22:16:42+09:00 2014-08-21T22:16:42+09:00 opencv_contribを見てたら,DeepFlowというオプティカルフローのアルゴリズムが実装されていたので勉強ついでに使ってみる. DeepFlow DeepFlowはコンピュータビジョンの分野では有名な国際学会ICCV2013でWeinzaepfelらによって発表されたアルゴリズムである. HAL - INRIA :: [hal-00873592, version 1] DeepFlow: Large displacement optical flow with deep matchingDeepFlowではDeep Matchingという画像のマッチング手法(これも同論文内で提案さ… <p><a href="http://code.opencv.org/projects/opencv/wiki/ChangeLog">opencv_contrib</a>を見てたら,<a href="http://lear.inrialpes.fr/src/deepmatching/">DeepFlow</a>というオプティカルフローのアルゴリズムが実装されていたので勉強ついでに使ってみる.</p> <div class="section"> <h3>DeepFlow</h3> <p>DeepFlowはコンピュータビジョンの分野では有名な国際学会<a href="http://www.iccv2013.org/">ICCV2013</a>でWeinzaepfelらによって発表されたアルゴリズムである.<br /> <a href="http://hal.inria.fr/hal-00873592"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fhal.inria.fr%2Fhal-00873592" alt="" class="http-favicon" /></a><a href="http://hal.inria.fr/hal-00873592">HAL - INRIA :: [hal-00873592, version 1] DeepFlow: Large displacement optical flow with deep matching</a></p><p>DeepFlowではDeep Matchingという画像のマッチング手法(これも同論文内で提案されている)を用いてオプティカルフローを求めている.</p><p>以下の画像にアルゴリズムの全体像がまとめられている.</p> <blockquote cite="http://lear.inrialpes.fr/src/deepmatching/"> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140821/20140821140023.jpg" alt="f:id:whoopsidaisies:20140821140023j:plain" title="f:id:whoopsidaisies:20140821140023j:plain" class="hatena-fotolife" itemprop="image"></span></p> <cite><a href="http://lear.inrialpes.fr/src/deepmatching/"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Flear.inrialpes.fr%2Fsrc%2Fdeepmatching%2F" alt="" class="http-favicon" /></a><a href="http://lear.inrialpes.fr/src/deepmatching/">LEAR - DeepMatchingFlow</a></cite> </blockquote> <p>パワーポイントの資料は<a href="http://lear.inrialpes.fr/people/pweinzae/files/DeepFlow_iccv2013_slides.ppt">&#x3053;&#x3061;&#x3089;</a><br /> </p> <div class="section"> <h4>Deep Matching</h4> <p><a href="http://lear.inrialpes.fr/people/revaud/">Deep Matching</a>では,畳み込み,プーリング,サブサンプリングを繰り返しすことで,画像間のQuasi-Denseなマッチング(日本語でなんていうかわからない.準密?)を求める.</p><p>Deep Learningで注目を集めているConvolutional Neural Networks(CNN)に似たアプローチとなっている.</p><p>Deep Matchingを使うと以下のように非剛体のマッチングもうまく出来るようである.</p> <blockquote cite="http://lear.inrialpes.fr/people/revaud/"> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140821/20140821152916.png" alt="f:id:whoopsidaisies:20140821152916p:plain" title="f:id:whoopsidaisies:20140821152916p:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140821/20140821152927.png" alt="f:id:whoopsidaisies:20140821152927p:plain" title="f:id:whoopsidaisies:20140821152927p:plain" class="hatena-fotolife" itemprop="image"></span></p> <cite><a href="http://lear.inrialpes.fr/people/revaud/"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Flear.inrialpes.fr%2Fpeople%2Frevaud%2F" alt="" class="http-favicon" /></a><a href="http://lear.inrialpes.fr/people/revaud/">Jerome Revaud</a></cite> </blockquote> </div> </div> <div class="section"> <h3>オプティカルフロー</h3> <p>DeepFlowでは,時間的輝度勾配と空間的輝度勾配の拘束条件に加えて,Deep Matchingで求めた対応とオプティカルフローとの差異も拘束条件として目的関数に入れることで,密でかつ大きな動きにも強いオプティカルフローを得るようである.</p><p>目的関数の最小化は<a href="http://ja.wikipedia.org/wiki/SOR%E6%B3%95">SOR&#x6CD5;</a>という反復法で行っているようである.</p><p>DeepFlowで以下の画像みたいな感じにマッチングとオプティカルフローが得られるらしい.</p> <blockquote cite="http://lear.inrialpes.fr/src/deepmatching/"> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140821/20140821180059.png" alt="f:id:whoopsidaisies:20140821180059p:plain" title="f:id:whoopsidaisies:20140821180059p:plain" class="hatena-fotolife" itemprop="image"></span></p> <cite><a href="http://lear.inrialpes.fr/src/deepmatching/"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Flear.inrialpes.fr%2Fsrc%2Fdeepmatching%2F" alt="" class="http-favicon" /></a><a href="http://lear.inrialpes.fr/src/deepmatching/">LEAR - DeepMatchingFlow</a></cite> </blockquote> </div> <div class="section"> <h3>OpenCVで動かしてみる</h3> <p>DeepFlowは2014/8/21現在<a href="https://github.com/Itseez/opencv_contrib">opencv_contrib</a>に入っているが,opencv_contribは開発用リポジトリらしいので自己責任で.</p><p><a href="https://github.com/Itseez/opencv_contrib">&#x3053;&#x3053;</a>からソースを落としてきて,OpenCVのCMakeのオプションで「OPENCV_EXTRA_MODULES_PATH」を「(opencv_contribのパス)/modules」としてgenerate,ビルドしてやるとOpenCVにopencv_contrib内のモジュールが組み込まれる.</p><p>実際にDeepFlowを動かしてみたソースコードは以下.<br /> DeepFlowのパラメータは<a href="http://docs.opencv.org/3.0-alpha/modules/optflow/doc/dense_optflow.html?highlight=deepflow#optflow::OpticalFlowDeepFlow: public DenseOpticalFlow">&#x3053;&#x3053;</a>を参照.</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/opencv.hpp&gt;</span> <span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/optflow.hpp&gt;</span> <span class="synType">void</span> main() { <span class="synStatement">using</span> <span class="synType">namespace</span> cv; <span class="synComment">// DeepFlow計算用のインスタンスを生成</span> <span class="synType">auto</span> deepflow = optflow::createOptFlow_DeepFlow(); <span class="synComment">// 動画読み込み</span> <span class="synType">auto</span> capture = VideoCapture(<span class="synConstant">&quot;video.mp4&quot;</span>); <span class="synComment">// 前のフレーム保存</span> <span class="synComment">// まだグレースケールしか対応してないようなので変換</span> Mat prev, tmp; capture &gt;&gt; tmp; cvtColor(tmp, prev, COLOR_RGB2GRAY); <span class="synStatement">while</span> (cv::waitKey(<span class="synConstant">1</span>) == -<span class="synConstant">1</span>) { Mat curr; capture &gt;&gt; tmp; <span class="synStatement">if</span> (tmp.empty()) <span class="synStatement">break</span>; cvtColor(tmp, curr, COLOR_RGB2GRAY); <span class="synComment">// オプティカルフローの計算</span> Mat flow; deepflow-&gt;calc(prev, curr, flow); <span class="synComment">// 表示するようにX成分とY成分に分解</span> Mat flowXY[<span class="synConstant">2</span>]; split(flow, flowXY); <span class="synComment">// 極座標に変換</span> Mat magnitude, angle; cartToPolar(flowXY[<span class="synConstant">0</span>], flowXY[<span class="synConstant">1</span>], magnitude, angle, <span class="synConstant">true</span>); <span class="synComment">// 色相(H)はオプティカルフローの角度</span> <span class="synComment">// 彩度(S)は0~1に正規化したオプティカルフローの大きさ</span> <span class="synComment">// 明度(V)は1</span> Mat hsvPlanes[<span class="synConstant">3</span>]; hsvPlanes[<span class="synConstant">0</span>] = angle; hsvPlanes[<span class="synConstant">1</span>] = magnitude; hsvPlanes[<span class="synConstant">2</span>] = Mat::ones(angle.size(), CV_32F); <span class="synComment">// HSVを合成して一枚の画像にする</span> Mat hsv; merge(hsvPlanes, <span class="synConstant">3</span>, hsv); <span class="synComment">// 表示</span> imshow(<span class="synConstant">&quot;DeepFlow&quot;</span>, hsv); <span class="synComment">// 前のフレームを保存</span> prev = curr; } } </pre><p>結果はこんな感じ.かなり時間かかった.<br /> ちょいちょい真っ赤になるのは仕様なのかバグなのか.</p><p><iframe width="420" height="315" frameborder="0" allowfullscreen="" src="https://youtube.googleapis.com/v/pCoA0dc9gGE&feature&amp;source=uds"></iframe><br><a href="http://www.youtube.com/watch?v=pCoA0dc9gGE&feature">OpenCVでDeepFlow - YouTube</a></p> </div> whoopsidaisies OpenCV3.0.0-alphaの特徴抽出・マッチングまとめ hatenablog://entry/12921228815730771882 2014-08-20T20:02:15+09:00 2014-08-20T20:02:15+09:00 OpenCV3.0.0-alphaのパッケージが公開されたと話題になっていたので使ってみる.Change Logを見るとAKAZE特徴量が組み込まれている. AKAZE特徴量の紹介と他特徴量との比較 - 遥かへのスピードランナー によるとAKAZE特徴量は,以前のOpenCVでもakaze-opencvというパッケージを入れれば使えたが,OpenCV3.0.0-alphaでは元々組み込まれているのでそのまま使えるようだ.逆にSIFTやSURFなんかは元々OpenCVで使えたが OpenCV 3.0.0-alphaでSIFT/SURFを使う | .COM-POUND によると,opencv_co… <p>OpenCV3.0.0-alphaのパッケージが<a href="http://sourceforge.net/projects/opencvlibrary/files/opencv-win/3.0.0-alpha/">&#x516C;&#x958B;&#x3055;&#x308C;&#x305F;</a>と話題になっていたので使ってみる.</p><p><a href="http://code.opencv.org/projects/opencv/wiki/ChangeLog#30-alpha">Change Log</a>を見るとAKAZE特徴量が組み込まれている.<br /> <a href="http://poly.hatenablog.com/entry/2014/01/06/063012"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fpoly.hatenablog.com%2Fentry%2F2014%2F01%2F06%2F063012" alt="" class="http-favicon" /></a><a href="http://poly.hatenablog.com/entry/2014/01/06/063012">AKAZE&#x7279;&#x5FB4;&#x91CF;&#x306E;&#x7D39;&#x4ECB;&#x3068;&#x4ED6;&#x7279;&#x5FB4;&#x91CF;&#x3068;&#x306E;&#x6BD4;&#x8F03; - &#x9065;&#x304B;&#x3078;&#x306E;&#x30B9;&#x30D4;&#x30FC;&#x30C9;&#x30E9;&#x30F3;&#x30CA;&#x30FC;</a><br /> によるとAKAZE特徴量は,以前のOpenCVでも<a href="https://github.com/thorikawa/akaze-opencv">akaze-opencv</a>というパッケージを入れれば使えたが,OpenCV3.0.0-alphaでは元々組み込まれているのでそのまま使えるようだ.</p><p>逆にSIFTやSURFなんかは元々OpenCVで使えたが<br /> <a href="http://www.yasutomo57jp.com/2014/08/19/opencv-3-0-0-alpha%E3%81%A7siftsurf%E3%82%92%E4%BD%BF%E3%81%86/"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwww.yasutomo57jp.com%2F2014%2F08%2F19%2Fopencv-3-0-0-alpha%25E3%2581%25A7siftsurf%25E3%2582%2592%25E4%25BD%25BF%25E3%2581%2586%2F" alt="" class="http-favicon" /></a><a href="http://www.yasutomo57jp.com/2014/08/19/opencv-3-0-0-alpha%E3%81%A7siftsurf%E3%82%92%E4%BD%BF%E3%81%86/">OpenCV 3.0.0-alpha&#x3067;SIFT/SURF&#x3092;&#x4F7F;&#x3046; | .COM-POUND</a><br /> によると,<a href="https://github.com/Itseez/opencv_contrib">opencv_contrib</a>に移動されてしまいOpenCVと一緒にビルドしないと使えないようである.</p> <div class="section"> <h3>OpenCV3.0.0-alphaでの変更点まとめ</h3> <p>以前当ブログで<br /> <a href="http://whoopsidaisies.hatenablog.com/entry/2013/12/07/135810"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2013%2F12%2F07%2F135810" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2013/12/07/135810">OpenCV&#x3067;&#x753B;&#x50CF;&#x306E;&#x7279;&#x5FB4;&#x62BD;&#x51FA;&#x30FB;&#x30DE;&#x30C3;&#x30C1;&#x30F3;&#x30B0;&#x3092;&#x884C;&#x3046; - whoopsidaisies&#39;s diary</a><br /> にOpenCV2.4.7の画像の特徴抽出あたりをまとめた記事を書いていたので,今回はOpenCV3.0.0-alphaでの変更点をまとめてみる.</p> <div class="section"> <h4>特徴点抽出(FeatureDetectorインターフェース)</h4> <table> <tr> <td></td> <th>FeatureDetector</th> </tr> <tr> <th>OpenCV2.4.7</th> <td>FAST,<span style="color: #c0c0c0">FASTX</span>,<span style="color: #0000ff">STAR</span>,<span style="color: #0000ff">SIFT</span>,<span style="color: #0000ff">SURF</span>,ORB,BRISK,MSER,GFTT,HARRIS,<span style="color: #c0c0c0">Dense</span>,SimpleBlob</td> </tr> <tr> <th>OpenCV3.0.0-alpha</th> <td>FAST,ORB,BRISK,MSER,GFTT,HARRIS,SimpleBlob,<span style="color: #ff0000">KAZE</span>,<span style="color: #ff0000">AKAZE</span></td> </tr> <tr> <th>opencv_contrib</th> <td>STAR,SIFT,SURF</td> </tr> </table><p><span style="color: #ff0000">赤字</span>はOpenCV3.0.0-alphaで追加されたもの.<br /> <span style="color: #0000ff">青字</span>はopencv_contribを入れれば使えるもの.<br /> <span style="color: #c0c0c0">灰色</span>はOpenCV3.0.0-alphaでなくなってしまってopencv_contribにも入ってないもの.</p><p>FASTXとDenseはなくなってしまったようである.</p> </div> <div class="section"> <h4>特徴記述(DescriptorExtractorインターフェース)</h4> <table> <tr> <td></td> <th>DescriptorExtractor</th> </tr> <tr> <th>OpenCV2.4.7</th> <td><span style="color: #0000ff">SIFT</span>,<span style="color: #0000ff">SURF</span>,<span style="color: #0000ff">BRIEF</span>,BRISK,ORB,<span style="color: #0000ff">FRIEK</span></td> </tr> <tr> <th>OpenCV3.0.0-alpha</th> <td>BRISK,ORB,<span style="color: #ff0000">KAZE</span>,<span style="color: #ff0000">AKAZE</span></td> </tr> <tr> <th>opencv_contrib</th> <td>SIFT,SURF,BRIEF,FREAK</td> </tr> </table><p><span style="color: #ff0000">赤字</span>はOpenCV3.0.0-alphaで追加されたもの.<br /> <span style="color: #0000ff">青字</span>はopencv_contribを入れれば使えるもの.</p> </div> <div class="section"> <h4>特徴点マッチング(DescriptorMatcherインターフェース)</h4> <table> <tr> <td></td> <th>DescriptorExtractor</th> </tr> <tr> <td>OpenCV2.4.7およびOpenCV3.0.0-alpha</td> <td>BruteForce,BruteForce-L1,BruteForce-SL2,BruteForce-Hamming,BruteForce-Hamming(2),FlannBased</td> </tr> </table><p>DescriptorMatcherに関しては変わりがないようである.</p> </div> </div> <div class="section"> <h3>AKAZEを使ってみる</h3> <p>AKAZEを使ってみたかったので,OpenCV3.0.0-alphaで特徴抽出を行ってみる.ついでに他のアルゴリズムとも画像を比較してみる.特徴抽出のソースコードは以下.</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink>cv::String detectorNames[] = {<span class="synConstant">&quot;AKAZE&quot;</span>, <span class="synConstant">&quot;KAZE&quot;</span>, <span class="synConstant">&quot;FAST&quot;</span>, <span class="synConstant">&quot;ORB&quot;</span>, <span class="synConstant">&quot;BRISK&quot;</span>, <span class="synConstant">&quot;MSER&quot;</span>, <span class="synConstant">&quot;GFTT&quot;</span>, <span class="synConstant">&quot;HARRIS&quot;</span>, <span class="synConstant">&quot;SimpleBlob&quot;</span>,}; <span class="synType">auto</span> img = cv::imread(<span class="synConstant">&quot;Penguins.jpg&quot;</span>); <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; <span class="synConstant">9</span>; i++) { <span class="synType">auto</span> detector = cv::FeatureDetector::create(detectorNames[i]); std::vector&lt;cv::KeyPoint&gt; keyPoints; detector-&gt;detect(img, keyPoints); cv::Mat output; cv::drawKeypoints(img, keyPoints, output, cv::Scalar::all(-<span class="synConstant">1</span>),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::imwrite(detectorNames[i] + <span class="synConstant">&quot;.bmp&quot;</span>, output); } </pre><p><hr></p> <div class="section"> <h5>AKAZE</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140820/20140820194415.jpg" alt="f:id:whoopsidaisies:20140820194415j:plain" title="f:id:whoopsidaisies:20140820194415j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <hr></p> </div> <div class="section"> <h5>KAZE</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140820/20140820194424.jpg" alt="f:id:whoopsidaisies:20140820194424j:plain" title="f:id:whoopsidaisies:20140820194424j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <hr></p> </div> <div class="section"> <h5>FAST</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140820/20140820194432.jpg" alt="f:id:whoopsidaisies:20140820194432j:plain" title="f:id:whoopsidaisies:20140820194432j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <hr></p> </div> <div class="section"> <h5>ORB</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140820/20140820194437.jpg" alt="f:id:whoopsidaisies:20140820194437j:plain" title="f:id:whoopsidaisies:20140820194437j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <hr></p> </div> <div class="section"> <h5>BRISK</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140820/20140820194444.jpg" alt="f:id:whoopsidaisies:20140820194444j:plain" title="f:id:whoopsidaisies:20140820194444j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <hr></p> </div> <div class="section"> <h5>MSER</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140820/20140820194454.jpg" alt="f:id:whoopsidaisies:20140820194454j:plain" title="f:id:whoopsidaisies:20140820194454j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <hr></p> </div> <div class="section"> <h5>GFTT</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140820/20140820194459.jpg" alt="f:id:whoopsidaisies:20140820194459j:plain" title="f:id:whoopsidaisies:20140820194459j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <hr></p> </div> <div class="section"> <h5>HARRIS</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140820/20140820194510.jpg" alt="f:id:whoopsidaisies:20140820194510j:plain" title="f:id:whoopsidaisies:20140820194510j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <hr></p> </div> <div class="section"> <h5>SimpleBlog</h5> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140820/20140820194515.jpg" alt="f:id:whoopsidaisies:20140820194515j:plain" title="f:id:whoopsidaisies:20140820194515j:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> </div> whoopsidaisies C#でDeep Learning(Accord.NETによる方法) hatenablog://entry/12921228815730581582 2014-08-19T01:54:20+09:00 2014-08-19T01:54:20+09:00 流行りのDeep LearningをC#で試してみる.機械学習やコンピュータビジョン,信号処理等の.NET向けのオープンソースのライブラリであるAccord.NET FrameworkにDeep Learningが実装されているのでそれを使う.Deep Belief Networks(DBN), Deep Neural Networks(DNNs)とおまけにRestricted Boltzmann Machine(RBM)を単体で動かしてみる.Deep Learning自体については以下のページ等を参考に. MIRU2014 tutorial deeplearning Deep Learnin… <p>流行りのDeep LearningをC#で試してみる.機械学習やコンピュータビジョン,信号処理等の.NET向けのオープンソースのライブラリである<a href="http://accord-framework.net/">Accord.NET Framework</a>にDeep Learningが実装されているのでそれを使う.</p><p>Deep Belief Networks(DBN), Deep Neural Networks(DNNs)とおまけにRestricted Boltzmann Machine(RBM)を単体で動かしてみる.</p><p>Deep Learning自体については以下のページ等を参考に.<br /> <a href="http://www.slideshare.net/Takayosi/miru2014-tutorial-deeplearning-37219713"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwww.slideshare.net%2FTakayosi%2Fmiru2014-tutorial-deeplearning-37219713" alt="" class="http-favicon" /></a><a href="http://www.slideshare.net/Takayosi/miru2014-tutorial-deeplearning-37219713">MIRU2014 tutorial deeplearning</a><br /> <a href="http://www.slideshare.net/beam2d/deep-learning20140130"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwww.slideshare.net%2Fbeam2d%2Fdeep-learning20140130" alt="" class="http-favicon" /></a><a href="http://www.slideshare.net/beam2d/deep-learning20140130">Deep Learning&#x6280;&#x8853;&#x306E;&#x4ECA;</a><br /> <a href="http://www.vision.is.tohoku.ac.jp/files/9313/6601/7876/CVIM_tutorial_deep_learning.pdf"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwww.vision.is.tohoku.ac.jp%2Ffiles%2F9313%2F6601%2F7876%2FCVIM_tutorial_deep_learning.pdf" alt="" class="http-favicon" /></a><a href="http://www.vision.is.tohoku.ac.jp/files/9313/6601/7876/CVIM_tutorial_deep_learning.pdf">&#x30C7;&#x30A3;&#x30FC;&#x30D7;&#x30E9;&#x30FC;&#x30CB;&#x30F3;&#x30B0; &#x30C1;&#x30E5;&#x30FC;&#x30C8;&#x30EA;&#x30A2;&#x30EB;&#xFF08;&#x3082;&#x3057;&#x304F;&#x306F;&#x7814;&#x7A76;&#x52D5;&#x5411;&#x5831;&#x544A;&#xFF09;</a><br /> </p> <div class="section"> <h3>Accord.NETのインストール</h3> <p>NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「Accord.Neuro」を検索・インストール.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140819/20140819013518.png" alt="f:id:whoopsidaisies:20140819013518p:plain" title="f:id:whoopsidaisies:20140819013518p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>ソースコード</h3> <ul> <li><a href="#dbn1">Deep Belief Networks(DBN) - 教師あり学習(Back propagation)</a></li> <li><a href="#dbn2">Deep Belief Networks(DBN) - 教師なし学習(Contrastive Divergence)</a></li> <li><a href="#dnn">Deep Neural Networks(DNNs)</a></li> <li><a href="#rbm">Restricted Boltzmann Machine(RBM)</a></li> </ul><p>を動かすサンプルコードを載せていくが,いずれのサンプルでも以下のusingを書いておくこと.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synStatement">using</span> Accord.Neuro; <span class="synStatement">using</span> Accord.Neuro.Networks; <span class="synStatement">using</span> Accord.Neuro.Learning; <span class="synStatement">using</span> AForge.Neuro.Learning; <span class="synStatement">using</span> Accord.Neuro.ActivationFunctions; <span class="synStatement">using</span> Accord.Math; </pre><p><a name = "dbn1"></a></p> </div> <div class="section"> <h3>Deep Belief Networks(DBN) - 教師あり学習(Back propagation)</h3> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// トレーニングデータ</span> <span class="synType">double</span>[][] inputs = { <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, }; <span class="synType">double</span>[][] outputs = { <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">1</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">1</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">1</span> }, }; <span class="synComment">// DBNの生成</span> var network = <span class="synStatement">new</span> DeepBeliefNetwork( <span class="synStatement"> inputsCount:</span> inputs.Length, <span class="synComment">// 入力層の次元</span> <span class="synStatement"> hiddenNeurons:</span> <span class="synStatement">new</span> <span class="synType">int</span>[] { <span class="synConstant">4</span>, <span class="synConstant">2</span> }); <span class="synComment">// 隠れ層と出力層の次元</span> <span class="synComment">// ネットワークの重みをガウス分布で初期化する</span> <span class="synStatement">new</span> GaussianWeights(network).Randomize(); network.UpdateVisibleWeights(); <span class="synComment">// DBNの学習アルゴリズムの生成 5000回繰り返し入力</span> var teacher = <span class="synStatement">new</span> BackPropagationLearning(network); <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; <span class="synConstant">5000</span>; i++) teacher.RunEpoch(inputs, outputs); <span class="synComment">// 重みの更新</span> network.UpdateVisibleWeights(); <span class="synComment">// 学習されたネットワークでテストデータが各クラスに属する確率を計算</span> <span class="synType">double</span>[] input = { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }; var output = network.Compute(input); <span class="synComment">// 一番確率の高いクラスのインデックスを得る</span> <span class="synType">int</span> imax; output.Max(<span class="synStatement">out</span> imax); <span class="synComment">// 結果出力</span> Console.WriteLine(<span class="synConstant">&quot;class : {0}&quot;</span>, imax); <span class="synStatement">foreach</span> (var o <span class="synStatement">in</span> output) { Console.Write(<span class="synConstant">&quot;{0} &quot;</span>, o); } </pre><p>実行結果</p> <pre class="code" data-lang="" data-unlink>class : 0 0.883118949465337 0.115560850111682</pre><p><a name="#dbn2"></a></p> </div> <div class="section"> <h3>Deep Belief Networks(DBN) - 教師なし学習(Contrastive Divergence)</h3> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// トレーニングデータ</span> <span class="synType">double</span>[][] inputs = { <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, }; <span class="synComment">// DBNの生成</span> var network = <span class="synStatement">new</span> DeepBeliefNetwork( <span class="synStatement"> inputsCount:</span> <span class="synConstant">6</span>, <span class="synStatement"> hiddenNeurons:</span> <span class="synStatement">new</span> <span class="synType">int</span>[] { <span class="synConstant">4</span>, <span class="synConstant">2</span> }); <span class="synComment">// ネットワークの重みをガウス分布で初期化する</span> <span class="synStatement">new</span> GaussianWeights(network).Randomize(); network.UpdateVisibleWeights(); <span class="synComment">// DBNの学習アルゴリズムの生成 5000回繰り返し入力</span> var teacher = <span class="synStatement">new</span> DeepBeliefNetworkLearning(network) { Algorithm = (h, v, i) =&gt; <span class="synStatement">new</span> ContrastiveDivergenceLearning(h, v) }; var layerData = teacher.GetLayerInput(inputs); <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; <span class="synConstant">5000</span>; i++) teacher.RunEpoch(layerData); <span class="synComment">// 重みの更新</span> network.UpdateVisibleWeights(); <span class="synComment">// 学習されたネットワークでテストデータが各クラスに属する確率を計算</span> <span class="synType">double</span>[] input = { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }; var output = network.Compute(input); <span class="synComment">// 一番確率の高いクラスのインデックスを得る</span> <span class="synType">int</span> imax; output.Max(<span class="synStatement">out</span> imax); <span class="synComment">// 結果出力</span> Console.WriteLine(<span class="synConstant">&quot;class : {0}&quot;</span>, imax); <span class="synStatement">foreach</span> (var o <span class="synStatement">in</span> output) { Console.Write(<span class="synConstant">&quot;{0} &quot;</span>, o); } </pre><p>実行結果</p> <pre class="code" data-lang="" data-unlink>class : 1 0.529437183967883 0.554114047128916</pre><p><a name="#dnn"></a></p> </div> <div class="section"> <h3>Deep Neural Networks(DNNs)</h3> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// トレーニングデータ</span> <span class="synType">double</span>[][] inputs = { <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, }; <span class="synType">double</span>[][] outputs = { <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">1</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">1</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">1</span> }, }; <span class="synComment">// ネットワークの生成</span> var network = <span class="synStatement">new</span> DeepBeliefNetwork( <span class="synStatement"> inputsCount:</span> inputs.Length, <span class="synComment">// 入力層の次元</span> <span class="synStatement"> hiddenNeurons:</span> <span class="synStatement">new</span> <span class="synType">int</span>[] { <span class="synConstant">4</span>, <span class="synConstant">2</span> }); <span class="synComment">// 隠れ層と出力層の次元</span> <span class="synComment">// DNNの学習アルゴリズムの生成</span> var teacher = <span class="synStatement">new</span> DeepNeuralNetworkLearning(network) { Algorithm = (ann, i) =&gt; <span class="synStatement">new</span> ParallelResilientBackpropagationLearning(ann), LayerIndex = network.Machines.Count - <span class="synConstant">1</span>, }; <span class="synComment">// 5000回繰り返し学習</span> var layerData = teacher.GetLayerInput(inputs); <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; <span class="synConstant">5000</span>; i++) teacher.RunEpoch(layerData, outputs); <span class="synComment">// 重みの更新</span> network.UpdateVisibleWeights(); <span class="synComment">// 学習されたネットワークでテストデータが各クラスに属する確率を計算</span> <span class="synType">double</span>[] input = { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }; var output = network.Compute(input); <span class="synComment">// 一番確率の高いクラスのインデックスを得る</span> <span class="synType">int</span> imax; output.Max(<span class="synStatement">out</span> imax); <span class="synComment">// 結果出力</span> Console.WriteLine(<span class="synConstant">&quot;class : {0}&quot;</span>, imax); <span class="synStatement">foreach</span> (var o <span class="synStatement">in</span> output) { Console.Write(<span class="synConstant">&quot;{0} &quot;</span>, o); } </pre><p>実行結果</p> <pre class="code" data-lang="" data-unlink>class : 0 0.999680477117216 0.00120961077917418</pre><p><a name="#rbm"></a></p> </div> <div class="section"> <h3>Restricted Boltzmann Machine(RBM)</h3> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// トレーニングデータ</span> <span class="synType">double</span>[][] inputs = { <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">0</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span> }, }; <span class="synType">double</span>[][] outputs = { <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">1</span>, <span class="synConstant">0</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">1</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">1</span> }, <span class="synStatement">new</span> <span class="synType">double</span>[] { <span class="synConstant">0</span>, <span class="synConstant">1</span> }, }; <span class="synComment">// RBMの生成</span> var rbm = <span class="synStatement">new</span> RestrictedBoltzmannMachine( <span class="synStatement"> inputsCount:</span> <span class="synConstant">6</span>, <span class="synStatement"> hiddenNeurons:</span> <span class="synConstant">2</span>); <span class="synComment">// トレーニングデータで学習</span> var teacher = <span class="synStatement">new</span> ContrastiveDivergenceLearning(rbm); <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; <span class="synConstant">5000</span>; i++) teacher.RunEpoch(inputs); <span class="synComment">// テストデータ</span> <span class="synType">double</span>[] input = { <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">1</span>, <span class="synConstant">0</span>, <span class="synConstant">0</span> }; <span class="synComment">// 学習されたネットワークで各クラスに属する確率を計算</span> var output = rbm.Compute(input); <span class="synComment">// 一番確率の高いクラスのインデックスを得る</span> <span class="synType">int</span> imax; output.Max(<span class="synStatement">out</span> imax); <span class="synComment">// 結果出力</span> Console.WriteLine(<span class="synConstant">&quot;class : {0}&quot;</span>, imax); <span class="synStatement">foreach</span> (var o <span class="synStatement">in</span> output) { Console.Write(<span class="synConstant">&quot;{0} &quot;</span>, o); } </pre><p>実行結果</p> <pre class="code" data-lang="" data-unlink>class : 1 0.133832413712274 0.906343089146992</pre> </div> whoopsidaisies C#でSVM libsvm.netによる方法 hatenablog://entry/12921228815730367189 2014-08-16T18:30:02+09:00 2014-08-16T18:30:02+09:00 SVMのライブラリであるLIBSVMを.NETプロジェクトで使えるようにするlibsvm.netを動かしてみる. libsvm.netのインストール NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「libsvm.net」を検索・インストール. 動作確認 libsvm.netでは,トレーニングデータやテストデータをLIBSVMと同じ形式でファイルから入力できる.データのフォーマットは以下の通りである. &ltlabel> &ltindex1>:&ltvalue1> &ltindex2>:&ltvalue2> ... &lti… <p>SVMのライブラリである<a href="http://www.csie.ntu.edu.tw/~cjlin/libsvm/">LIBSVM</a>を.NETプロジェクトで使えるようにする<a href="https://code.google.com/p/libsvm-net/">libsvm.net</a>を動かしてみる.</p> <div class="section"> <h3>libsvm.netのインストール</h3> <p>NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「libsvm.net」を検索・インストール.</p> </div> <div class="section"> <h3>動作確認</h3> <p>libsvm.netでは,トレーニングデータやテストデータをLIBSVMと同じ形式でファイルから入力できる.データのフォーマットは以下の通りである.</p> <blockquote cite="http://bio-info.biz/tips/libsvm_data_format.html"> <p>&ltlabel&gt &ltindex1&gt:&ltvalue1&gt &ltindex2&gt:&ltvalue2&gt ... &ltindexN&gt:&ltvalueN&gt<br /> &ltlabel&gt &ltindex1&gt:&ltvalue1&gt &ltindex2&gt:&ltvalue2&gt ... &ltindexN&gt:&ltvalueN&gt<br /> &ltlabel&gt &ltindex1&gt:&ltvalue1&gt &ltindex2&gt:&ltvalue2&gt ... &ltindexN&gt:&ltvalueN&gt<br /> .<br /> .<br /> .<br /> &ltlabel&gt &ltindex1&gt:&ltvalue1&gt &ltindex2&gt:&ltvalue2&gt ... &ltindexN&gt:&ltvalueN&gt</p> <cite><a href="http://bio-info.biz/tips/libsvm_data_format.html">LIBSVM&#x306E;&#x5165;&#x529B;&#x30C7;&#x30FC;&#x30BF;&#x5F62;&#x5F0F;&#x306B;&#x3064;&#x3044;&#x3066;</a></cite> </blockquote> <p><a href="http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/">&#x3053;&#x3053;</a>にLIBSVM用のデータセットが落ちていたので,<a href="http://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/binary.html#fourclass">fourclass</a>というデータセットを使ってみる.</p><p>以下に,分類器を動かすソースコード乗せる.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">// トレーニングデータの読み込み</span> var training = libsvm.ProblemHelper.ReadProblem(<span class="synConstant">&quot;fourclass&quot;</span>); <span class="synComment">// RBFカーネルを生成</span> var gamma = <span class="synConstant">1</span>; var kernel = libsvm.KernelHelper.RadialBasisFunctionKernel(gamma); <span class="synComment">// C-SVC用のクラスの生成</span> var c = <span class="synConstant">1</span>; var svm = <span class="synStatement">new</span> libsvm.C_SVC(training, kernel, c); <span class="synComment">// テストデータの読み込み(面倒だったのでトレーニングデータをそのまま使ってる)</span> var test = libsvm.ProblemHelper.ReadProblem(<span class="synConstant">&quot;fourclass&quot;</span>); <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; test.l; i++) { <span class="synComment">// 予測値</span> var z = svm.Predict(test.x[i]); <span class="synComment">// 入力ファイルについているラベル</span> var y = test.y[i]; <span class="synComment">// 予測値と正解値を出力</span> Console.WriteLine(<span class="synConstant">&quot;{0}:{1} {2}&quot;</span>, i, z, y); } </pre><p>トレーニングデータとテストデータは同じものを使った.実行すると,予測値と正解値が出力される.</p><p>上記コードではパラメータ選択とかまでは行っていないが,結構簡単に使えそう.他にも回帰 (ϵ-SVR)や外れ値検出 (One-Class SVM) が出来るようである.</p> </div> whoopsidaisies C# LINQでFIRフィルタ hatenablog://entry/12921228815728446895 2014-07-18T23:32:42+09:00 2014-07-18T23:32:42+09:00 LINQを使った,FIRフィルタ演算を行う関数. ソースコード /// <summary> /// FIRフィルタをかけたデータを返す /// </summary> /// <param name="data">入力データ</param> /// <param name="coefficients">フィルタ係数</param> /// <returns>FIRフィルタをかけたデータ</returns> List<double> FiniteImpulseResponseFilter( List<double> data, List<double> coefficients) { return… <p>LINQを使った,FIRフィルタ演算を行う関数.</p> <div class="section"> <h3>ソースコード</h3> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">summary</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// FIRフィルタをかけたデータを返す</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;/</span><span class="synStatement">summary</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">param</span><span class="synIdentifier"> </span><span class="synType">name</span>=<span class="synConstant">&quot;data&quot;</span><span class="synIdentifier">&gt;</span><span class="synComment">入力データ</span><span class="synIdentifier">&lt;/</span><span class="synStatement">param</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">param</span><span class="synIdentifier"> </span><span class="synType">name</span>=<span class="synConstant">&quot;coefficients&quot;</span><span class="synIdentifier">&gt;</span><span class="synComment">フィルタ係数</span><span class="synIdentifier">&lt;/</span><span class="synStatement">param</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">returns</span><span class="synIdentifier">&gt;</span><span class="synComment">FIRフィルタをかけたデータ</span><span class="synIdentifier">&lt;/</span><span class="synStatement">returns</span><span class="synIdentifier">&gt;</span> List&lt;<span class="synType">double</span>&gt; FiniteImpulseResponseFilter( List&lt;<span class="synType">double</span>&gt; data, List&lt;<span class="synType">double</span>&gt; coefficients) { <span class="synStatement">return</span> Enumerable.Range(<span class="synConstant">0</span>, data.Count - coefficients.Count) .Select(i =&gt; data.Skip(i).Take(coefficients.Count) .Zip(coefficients, (d, c) =&gt; d * c).Sum()) .ToList(); } </pre><p><a href="http://whoopsidaisies.hatenablog.com/entry/2014/07/18/225436"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2014%2F07%2F18%2F225436" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2014/07/18/225436">C# LINQ&#x3067;&#x79FB;&#x52D5;&#x5E73;&#x5747; - whoopsidaisies&#39;s diary</a><br /> をベースにした.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>.Zip(coefficients, (d, c) =&gt; d * c).Sum() </pre><p>の部分で入力データとフィルタ係数の積和演算を行っている.</p> </div> whoopsidaisies C# LINQで移動平均 hatenablog://entry/12921228815728442770 2014-07-18T22:54:36+09:00 2014-07-18T22:54:36+09:00 LINQを使った,移動平均を計算する関数. ソースコード /// <summary> /// 移動平均を格納した配列を返す /// </summary> /// <param name="data">入力データ</param> /// <param name="num">何個分の平均をとるか</param> /// <returns>移動平均をとったデータ</returns> List<double> MovingAverage( List<double> data, int num) { return Enumerable.Range(0, data.Count - num) .Select… <p>LINQを使った,移動平均を計算する関数.</p> <div class="section"> <h3>ソースコード</h3> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">summary</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// 移動平均を格納した配列を返す</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;/</span><span class="synStatement">summary</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">param</span><span class="synIdentifier"> </span><span class="synType">name</span>=<span class="synConstant">&quot;data&quot;</span><span class="synIdentifier">&gt;</span><span class="synComment">入力データ</span><span class="synIdentifier">&lt;/</span><span class="synStatement">param</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">param</span><span class="synIdentifier"> </span><span class="synType">name</span>=<span class="synConstant">&quot;num&quot;</span><span class="synIdentifier">&gt;</span><span class="synComment">何個分の平均をとるか</span><span class="synIdentifier">&lt;/</span><span class="synStatement">param</span><span class="synIdentifier">&gt;</span> <span class="synComment">/// </span><span class="synIdentifier">&lt;</span><span class="synStatement">returns</span><span class="synIdentifier">&gt;</span><span class="synComment">移動平均をとったデータ</span><span class="synIdentifier">&lt;/</span><span class="synStatement">returns</span><span class="synIdentifier">&gt;</span> List&lt;<span class="synType">double</span>&gt; MovingAverage( List&lt;<span class="synType">double</span>&gt; data, <span class="synType">int</span> num) { <span class="synStatement">return</span> Enumerable.Range(<span class="synConstant">0</span>, data.Count - num) .Select(i =&gt; data.Skip(i).Take(num).Average()) .ToList(); } </pre><p>LINQの練習用なので効率が良いかとかは知らない.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>Enumerable.Range(<span class="synConstant">0</span>, data.Count - num) </pre><p>で,0~総データ数-平均を求めるときのデータの個数までの整数のシーケンスを生成する.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>data.Skip(i).Take(num).Average() </pre><p>で,入力データのi番目のデータからnum個データを抽出して平均をとる.</p> </div> <div class="section"> <h3>その他</h3> <p>FIRフィルタは以下の記事.<br /> <a href="http://whoopsidaisies.hatenablog.com/entry/2014/07/18/233242"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2014%2F07%2F18%2F233242" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2014/07/18/233242">C# LINQ&#x3067;FIR&#x30D5;&#x30A3;&#x30EB;&#x30BF; - whoopsidaisies&#39;s diary</a></p> </div> whoopsidaisies C#でExcelファイルを作成・グラフを挿入する NetOfficeによる方法 hatenablog://entry/12921228815726400684 2014-06-19T10:10:32+09:00 2014-06-19T10:10:32+09:00 C#からExcelファイルを作って,グラフも挿入したい.以前,以下の記事でClosedXmlというライブラリを使ってC#から簡単にExcelファイルを作る方法を紹介したが,グラフの挿入が出来ないのがグラフの挿入が出来ないのが気になっていた. C#でExcelファイルを作成する ClosedXmlを使用 - whoopsidaisies's diaryNetOfficeというライブラリを使えば,ClosedXmlと同じくらい簡単にExcelファイルが作成でき,さらにグラフの挿入も行えるので,今回はその方法を紹介する. NetOfficeのインストール NetOfficeはMicrosoft Of… <p>C#からExcelファイルを作って,グラフも挿入したい.</p><p>以前,以下の記事で<a href="https://closedxml.codeplex.com/">ClosedXml</a>というライブラリを使ってC#から簡単にExcelファイルを作る方法を紹介したが,グラフの挿入が出来ないのがグラフの挿入が出来ないのが気になっていた.<br /> <a href="http://whoopsidaisies.hatenablog.com/entry/2013/11/12/092843"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2013%2F11%2F12%2F092843" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2013/11/12/092843">C#&#x3067;Excel&#x30D5;&#x30A1;&#x30A4;&#x30EB;&#x3092;&#x4F5C;&#x6210;&#x3059;&#x308B; ClosedXml&#x3092;&#x4F7F;&#x7528; - whoopsidaisies&#39;s diary</a></p><p><a href="http://netoffice.codeplex.com/">NetOffice</a>というライブラリを使えば,ClosedXmlと同じくらい簡単にExcelファイルが作成でき,さらにグラフの挿入も行えるので,今回はその方法を紹介する.</p> <div class="section"> <h3>NetOfficeのインストール</h3> <p><a href="http://netoffice.codeplex.com/">NetOffice</a>はMicrosoft Officeにアクセスするための.NETのライブラリで,今回紹介するExcel以外にも,Word, PowerPoint等にもアクセスできるらしい.</p><p>インストールはNuget経由で可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから検索て「NetOffice.Excel」をインストールする.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140619/20140619095605.png" alt="f:id:whoopsidaisies:20140619095605p:plain" title="f:id:whoopsidaisies:20140619095605p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>動作確認</h3> <p>以下,動作確認用のソースコードと生成されたExcelファイルの中身.実行環境ではExcel2010がインストール済み.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synType">class</span> Program { <span class="synType">static</span> <span class="synType">void</span> Main(<span class="synType">string</span>[] args) { <span class="synComment">// Excelを開く</span> <span class="synStatement">using</span> (var excelApplication = <span class="synStatement">new</span> NetOffice.ExcelApi.Application()) { <span class="synComment">// ワークブックを追加</span> var workBook = excelApplication.Workbooks.Add(); <span class="synComment">// ワークシートを取得</span> var workSheet = (NetOffice.ExcelApi.Worksheet)workBook.Worksheets[<span class="synConstant">1</span>]; <span class="synComment">// データの入力</span> workSheet.Cells[<span class="synConstant">1</span>, <span class="synConstant">2</span>].Value = <span class="synConstant">&quot;ブラウザシェア&quot;</span>; workSheet.Cells[<span class="synConstant">2</span>, <span class="synConstant">1</span>].Value = <span class="synConstant">&quot;IE&quot;</span>; workSheet.Cells[<span class="synConstant">2</span>, <span class="synConstant">2</span>].Value = <span class="synConstant">&quot;52.56%&quot;</span>; workSheet.Cells[<span class="synConstant">3</span>, <span class="synConstant">1</span>].Value = <span class="synConstant">&quot;Chrome&quot;</span>; workSheet.Cells[<span class="synConstant">3</span>, <span class="synConstant">2</span>].Value = <span class="synConstant">&quot;24.7%&quot;</span>; workSheet.Cells[<span class="synConstant">4</span>, <span class="synConstant">1</span>].Value = <span class="synConstant">&quot;Firefox&quot;</span>; workSheet.Cells[<span class="synConstant">4</span>, <span class="synConstant">2</span>].Value = <span class="synConstant">&quot;12.92%&quot;</span>; workSheet.Cells[<span class="synConstant">5</span>, <span class="synConstant">1</span>].Value = <span class="synConstant">&quot;その他&quot;</span>; workSheet.Cells[<span class="synConstant">5</span>, <span class="synConstant">2</span>].Value = <span class="synConstant">&quot;=1-B2-B3-B4&quot;</span>; <span class="synComment">// グラフオブジェクトの追加</span> var chart = ((NetOffice.ExcelApi.ChartObjects)workSheet.ChartObjects()).Add(<span class="synConstant">70</span>, <span class="synConstant">100</span>, <span class="synConstant">375</span>, <span class="synConstant">225</span>); <span class="synComment">// 円グラフに設定</span> chart.Chart.ChartType = NetOffice.ExcelApi.Enums.XlChartType.xlPie; <span class="synComment">// データ範囲を指定</span> chart.Chart.SetSourceData(workSheet.Range(<span class="synConstant">&quot;A1:B5&quot;</span>)); <span class="synComment">// 保存(環境に合わせて拡張子xlsとかでも大丈夫みたい)</span> workBook.SaveAs(<span class="synSpecial">@</span><span class="synConstant">&quot;d:\test.xlsx&quot;</span>); <span class="synComment">// Excelを終了する</span> excelApplication.Quit(); } } } </pre><p>出来上がったExcelファイルの中身はこんな感じ.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140619/20140619094620.png" alt="f:id:whoopsidaisies:20140619094620p:plain" title="f:id:whoopsidaisies:20140619094620p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>その他</h3> <p>以下のページにグラフ以外のサンプルも多数ある.<br /> <a href="http://netoffice.codeplex.com/wikipage?title=Excel_Examples_EN"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fnetoffice.codeplex.com%2Fwikipage%3Ftitle%3DExcel_Examples_EN" alt="" class="http-favicon" /></a><a href="http://netoffice.codeplex.com/wikipage?title=Excel_Examples_EN">NetOffice - MS Office in .NET - Home</a><br /> <a href="http://pro.art55.jp/?eid=1304102"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fpro.art55.jp%2F%3Feid%3D1304102" alt="" class="http-favicon" /></a><a href="http://pro.art55.jp/?eid=1304102">&#x3010;NetOffice&#x3011;&#x3010;Excel&#x3011;NetOffice&#x306E;&#x307E;&#x3068;&#x3081; | &#x5275;&#x9020;&#x7684;&#x30D7;&#x30ED;&#x30B0;&#x30E9;&#x30DF;&#x30F3;&#x30B0;&#x3068;&#x7C98;&#x571F;&#x7D30;&#x5DE5;</a>(こっちは日本語)</p> </div> whoopsidaisies C#でグラフを描く OxyPlotのFunctionSeriesによる方法 hatenablog://entry/12921228815718131111 2014-02-10T12:29:39+09:00 2014-02-10T12:29:39+09:00 .NETフレームワーク用のグラフ描画ライブラリであるOxyPlotを使ってグラフを描く. その中でもFunctionSeriesクラスを使って与えられた関数のグラフを描く方法を記す.OxyPlotはWindows Formアプリケーションだけでなく,WPF,Silverlight,Windows8等様々な環境で使える. Chartコントロールとの比較 Chartコントロールによるグラフの描画方法は以下の別の記事で紹介したことがあるが,比較してOxyPlotの方が良いなと思っている点をあげる. 関数を渡してこの範囲を表示するとかが楽(今回の記事のメイン.詳細は後述.たとえば のの範囲のグラフを描… <p>.NETフレームワーク用のグラフ描画ライブラリである<a href="http://oxyplot.codeplex.com/">OxyPlot</a>を使ってグラフを描く.<br /> その中でもFunctionSeriesクラスを使って与えられた関数のグラフを描く方法を記す.</p><p>OxyPlotはWindows Formアプリケーションだけでなく,WPF,Silverlight,Windows8等様々な環境で使える.</p> <div class="section"> <h3>Chartコントロールとの比較</h3> <p>Chartコントロールによるグラフの描画方法は以下の<a href="http://whoopsidaisies.hatenablog.com/entry/2013/11/26/030331">&#x5225;&#x306E;&#x8A18;&#x4E8B;</a>で紹介したことがあるが,比較してOxyPlotの方が良いなと思っている点をあげる.</p> <ul> <li>関数を渡してこの範囲を表示するとかが楽(今回の記事のメイン.詳細は後述.たとえば</li> </ul><p><img src="http://chart.apis.google.com/chart?cht=tx&chl=y%3Dx%5E3%2B2x%5E2-3" alt="y=x^3+2x^2-3"/>の<img src="http://chart.apis.google.com/chart?cht=tx&chl=-2%5Cle%20x%5Cle%202" alt="-2\le x\le 2"/>の範囲のグラフを描画とか)</p> <ul> <li>マウス操作によるグラフの拡大・縮小,移動等の機能が最初からついている</li> <li>ベクター画像できれいにグラフを保存できる(ChartコントロールでもEMFで保存できるがグラフの種類によっては汚い)</li> <li>配列データ等にバインディングさせて,複数のグラフを描画するとき便利な気がする(今度記事にまとめようと思います)</li> </ul> </div> <div class="section"> <h3>OxyPlotのインストール</h3> <p>NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「OxyPlot」を検索.自分に合った環境のパッケージをインストール.(この記事ではOxyPlot.WindowsFormsを使った)</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140210/20140210110630.png" alt="f:id:whoopsidaisies:20140210110630p:plain" title="f:id:whoopsidaisies:20140210110630p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>Plotコントロールの追加</h3> <p>グラフ描画用のPlotというコントロールが用意されているので使う.</p><p>ツールボックスの適当なところで右クリックして「アイテムの選択(I)...」を選択.「.NET Framework コンポーネント」タブの「参照(B)...」ボタンを押して,「(ソリューションフォルダ)\packages\OxyPlot.WindowsForms.yyyy.x.xxx.x\lib\NET45\OxyPlot.WindowsForms.dll」を選択したらOK.</p><p><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/whoopsidaisies/20140210111230" class="hatena-fotolife" itemprop="url"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140210/20140210111230.png" alt="f:id:whoopsidaisies:20140210111230p:image:w275" title="f:id:whoopsidaisies:20140210111230p:image:w275" class="hatena-fotolife" style="width:275px" itemprop="image"></a></span> <span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/whoopsidaisies/20140210111034" class="hatena-fotolife" itemprop="url"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140210/20140210111034.png" alt="f:id:whoopsidaisies:20140210111034p:image:w275" title="f:id:whoopsidaisies:20140210111034p:image:w275" class="hatena-fotolife" style="width:275px" itemprop="image"></a></span></p><p>すると,ツールボックスに「Plot」ができるので,Formに配置する.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140210/20140210111336.png" alt="f:id:whoopsidaisies:20140210111336p:plain" title="f:id:whoopsidaisies:20140210111336p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>FunctionSeries</h3> <p>OxyPlotには,<a href="http://msdn.microsoft.com/ja-jp/library/bb549151(v=vs.110).aspx">Func&lt;double, double&gt;</a>のメソッドのグラフを描画してくれる<a href="http://www.oxyplot.org/doc/API/OxyPlot.Series.FunctionSeries.html">FunctionSeries</a>クラスがあるのでその使い方を記す.<br /> Func&lt;double, double&gt;という書き方になじみがない人もいるかもしれないので,とりあえず標準正規分布<br /> <img src="http://chart.apis.google.com/chart?cht=tx&chl=f%5C%28x%5C%29%3D%5Cfrac%7B1%7D%7B%5Csqrt%7B2%5Cpi%7D%7Dexp%5C%28-%5Cfrac%7Bx%5E%7B2%7D%7D%7B2%7D%5C%29" alt="f\(x\)=\frac{1}{\sqrt{2\pi}}exp\(-\frac{x^{2}}{2}\)"/><br /> を描くサンプルを以下に示す.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synType">private</span> <span class="synType">static</span> <span class="synType">double</span> StandardNormalDistribution(<span class="synType">double</span> x) { <span class="synStatement">return</span> <span class="synConstant">1</span> / Math.Sqrt(<span class="synConstant">2</span> * Math.PI) * Math.Exp(-x * x / <span class="synConstant">2</span>); } <span class="synType">private</span> <span class="synType">void</span> Form1_Load(<span class="synType">object</span> sender, EventArgs e) { plot1.Model = <span class="synStatement">new</span> OxyPlot.PlotModel { PlotType = OxyPlot.PlotType.XY }; var series = <span class="synStatement">new</span> OxyPlot.Series.FunctionSeries( StandardNormalDistribution, <span class="synComment">// 引数double,戻り値doubleの関数</span> -<span class="synConstant">3</span>, <span class="synComment">// x座標の最小値</span> <span class="synConstant">3</span>, <span class="synComment">// x座標の最大値</span> <span class="synConstant">0.01</span>, <span class="synComment">// x座標の刻み幅</span> <span class="synConstant">&quot;標準正規分布&quot;</span>); <span class="synComment">// グラフタイトル</span> plot1.Model.Series.Add(series); } </pre><p>実行すると以下のようなグラフが表示される.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140210/20140210114639.png" alt="f:id:whoopsidaisies:20140210114639p:plain" title="f:id:whoopsidaisies:20140210114639p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>StandardNormalDistributionという引数がdouble型,戻り値もdouble型の関数を定義している.これがFunc&lt;double, double&gt;のメソッドである.<br /> これと,グラフ描画をしたい範囲をFunctionSeriesクラスのコンストラクタに渡してやるだけでグラフを描画してくれて非常に便利である.</p> </div> <div class="section"> <h3>ラムダ式による方法</h3> <p>メソッドの部分を<a href="http://msdn.microsoft.com/ja-jp/library/bb397687.aspx">&#x30E9;&#x30E0;&#x30C0;&#x5F0F;</a>で表現することも当然出来るので,StandardNormalDistributionメソッドをわざわざ定義しないでも以下のように書くこともできる.(ここではラムダ式の説明は省略.わからない人は<a href="http://ufcpp.net/study/csharp/sp3_lambda.html">&#x3053;&#x3053;&#x3089;&#x306E;&#x3078;&#x3093;&#x306E;&#x30DA;&#x30FC;&#x30B8;</a>を参照)</p> <pre class="code lang-cs" data-lang="cs" data-unlink> var series = <span class="synStatement">new</span> OxyPlot.Series.FunctionSeries( x =&gt; <span class="synConstant">1</span> / Math.Sqrt(<span class="synConstant">2</span> * Math.PI) * Math.Exp(-x * x / <span class="synConstant">2</span>), <span class="synComment">// 引数double,戻り値doubleの関数</span> -<span class="synConstant">3</span>, <span class="synComment">// x座標の最小値</span> <span class="synConstant">3</span>, <span class="synComment">// x座標の最大値</span> <span class="synConstant">0.01</span>, <span class="synComment">// x座標の刻み幅</span> <span class="synConstant">&quot;標準正規分布&quot;</span>); <span class="synComment">// グラフタイトル</span> </pre> </div> <div class="section"> <h3>媒介変数表示された関数のグラフ描画</h3> <p>これも簡単に出来るので例を示す.例として以下の<a href="http://www.phoenix-c.or.jp/~tokioka/Epicycloid/Epicycloid.html">&#x30AB;&#x30FC;&#x30B8;&#x30AA;&#x30A4;&#x30C9;</a>を表示させてみる.<br /> <img src="http://chart.apis.google.com/chart?cht=tx&chl=x%3Da%5C%282%5Ccos%5Ctheta%20-%20%5Ccos2%5Ctheta%5C%29" alt="x=a\(2\cos\theta - \cos2\theta\)"/><br /> <img src="http://chart.apis.google.com/chart?cht=tx&chl=y%3Da%5C%282%5Csin%5Ctheta%20-%20%5Csin2%5Ctheta%5C%29" alt="y=a\(2\sin\theta - \sin2\theta\)"/></p><p>ソースコードは以下のようになる.(ラムダ式使用)</p> <pre class="code lang-cs" data-lang="cs" data-unlink>= <span class="synStatement">new</span> OxyPlot.PlotModel { PlotType = OxyPlot.PlotType.XY }; var series = <span class="synStatement">new</span> OxyPlot.Series.FunctionSeries( t =&gt; <span class="synConstant">2</span> * Math.Cos(t) - Math.Cos(<span class="synConstant">2</span> * t), <span class="synComment">// x座標の関数</span> t =&gt; <span class="synConstant">2</span> * Math.Sin(t) - Math.Sin(<span class="synConstant">2</span> * t), <span class="synComment">// y座標の関数</span> <span class="synConstant">0</span>, <span class="synComment">// tの最小値</span> <span class="synConstant">2</span> * Math.PI, <span class="synComment">// tの最大値</span> Math.PI / <span class="synConstant">32</span>, <span class="synComment">// tの刻み幅</span> <span class="synConstant">&quot;カージオイド&quot;</span>); <span class="synComment">// グラフタイトル</span> plot1.Model.Series.Add(series); </pre><p>実行すると以下のようなグラフが表示される.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140210/20140210122606.png" alt="f:id:whoopsidaisies:20140210122606p:plain" title="f:id:whoopsidaisies:20140210122606p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>その他</h3> <p>PlotTypeの設定によって極座標表示とかもできるがそれはまたの機会に.</p> </div> whoopsidaisies C#で地球を表示する(vtkTexturedSphereSourceによる方法) hatenablog://entry/12921228815718096784 2014-02-09T20:34:07+09:00 2014-02-09T20:34:07+09:00 VTKのvtkTexturedSphereSourceで球に世界地図のテクスチャを貼り付けることで地球を表示させる.テクスチャを使わずにvtkEarthSourceによって表示する方法は以下のページを参照. C#で地球を表示する(VTKのEarthSourceによる方法) - whoopsidaisies's diary ActiViz ActiVizは,3Dコンピュータグラフィックスの可視化ライブラリVTK(The Visualization ToolKit)のC#ラッパである.NuGetからインストールできる.簡単な解説は以下のページを参照. C#で3Dモデル表示(VTKのC#ラッパAct… <p>VTKのvtkTexturedSphereSourceで球に世界地図のテクスチャを貼り付けることで地球を表示させる.</p><p>テクスチャを使わずにvtkEarthSourceによって表示する方法は以下のページを参照.<br /> <a href="http://whoopsidaisies.hatenablog.com/entry/2014/02/09/185536"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2014%2F02%2F09%2F185536" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2014/02/09/185536">C#&#x3067;&#x5730;&#x7403;&#x3092;&#x8868;&#x793A;&#x3059;&#x308B;&#xFF08;VTK&#x306E;EarthSource&#x306B;&#x3088;&#x308B;&#x65B9;&#x6CD5;&#xFF09; - whoopsidaisies&#39;s diary</a><br /> </p> <div class="section"> <h3>ActiViz</h3> <p><a href="http://www.kitware.com/opensource/avdownload.php">ActiViz</a>は,3Dコンピュータグラフィックスの可視化ライブラリ<a href="http://www.vtk.org/">VTK&#xFF08;The Visualization ToolKit&#xFF09;</a>のC#ラッパである.NuGetからインストールできる.簡単な解説は以下のページを参照.<br /> <a href="http://whoopsidaisies.hatenablog.com/entry/2013/12/28/131053"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2013%2F12%2F28%2F131053" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2013/12/28/131053">C#&#x3067;3D&#x30E2;&#x30C7;&#x30EB;&#x8868;&#x793A;&#xFF08;VTK&#x306E;C#&#x30E9;&#x30C3;&#x30D1;ActiViz&#x306B;&#x3088;&#x308B;&#x65B9;&#x6CD5;&#xFF09; - whoopsidaisies&#39;s diary</a><br /> </p> </div> <div class="section"> <h3>RenderWindowControl</h3> <p>NuGetからActiVizをインストールし,RenderWindowControlをフォームに追加する.</p> </div> <div class="section"> <h3>vtkTexturedSphereSource</h3> <p>VTKには<a href="http://www.vtk.org/doc/nightly/html/classvtkTexturedSphereSource.html">vtkTexturedSphereSource</a>という,テクスチャを貼り付けることが出来る球オブジェクトのクラスがあるためそれを利用する.ソースコードは以下のようになる.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>sing (var sphere = <span class="synStatement">new</span> Kitware.VTK.vtkTexturedSphereSource()) <span class="synStatement">using</span> (var texture = <span class="synStatement">new</span> Kitware.VTK.vtkTexture()) <span class="synStatement">using</span> (var image = <span class="synStatement">new</span> Kitware.VTK.vtkPNGReader()) <span class="synStatement">using</span> (var mapper = <span class="synStatement">new</span> Kitware.VTK.vtkCompositePolyDataMapper()) <span class="synStatement">using</span> (var actor = <span class="synStatement">new</span> Kitware.VTK.vtkActor()) { <span class="synComment">// 球の滑らかさ(数字が多いほど分割数が多く滑らかになる)</span> sphere.SetThetaResolution(<span class="synConstant">64</span>); sphere.SetPhiResolution(<span class="synConstant">64</span>); mapper.SetInputConnection(sphere.GetOutputPort()); actor.SetMapper(mapper); <span class="synComment">// 世界地図画像の読み込みとテクスチャの設定</span> image.SetFileName(<span class="synSpecial">@</span><span class="synConstant">&quot;WorldMap_ja.png&quot;</span>); texture.SetInputConnection(image.GetOutputPort()); actor.SetTexture(texture); renderWindowControl1.RenderWindow.GetRenderers().GetFirstRenderer().AddActor(actor); } </pre><p>実行すると以下のように地球が表示される.世界地図画像は<a href="http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:WorldMap_ja.png">&#x30A6;&#x30A3;&#x30AD;&#x30DA;&#x30C7;&#x30A3;&#x30A2;</a>にあったものを使った.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140209/20140209202615.png" alt="f:id:whoopsidaisies:20140209202615p:plain" title="f:id:whoopsidaisies:20140209202615p:plain" class="hatena-fotolife" itemprop="image"></span></p><p>以下のように拡大表示もできるが,この方法だとベクターグラフィックの読み込みが(たぶん)できないので拡大表示する際は何かしら工夫が必要そう.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140209/20140209203055.png" alt="f:id:whoopsidaisies:20140209203055p:plain" title="f:id:whoopsidaisies:20140209203055p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> whoopsidaisies C#で地球を表示する(VTKのEarthSourceによる方法) hatenablog://entry/12921228815718088740 2014-02-09T18:55:36+09:00 2014-02-09T18:55:36+09:00 C#でVTKのvtkEarthSourceクラスによって地球を表示させる. ActiViz ActiVizは,3Dコンピュータグラフィックスの可視化ライブラリVTK(The Visualization ToolKit)のC#ラッパである.NuGetからインストールできる.簡単な解説は以下のページを参照. C#で3Dモデル表示(VTKのC#ラッパActiVizによる方法) - whoopsidaisies's diary RenderWindowControl NuGetからActiVizをインストールし,RenderWindowControlをフォームに追加する. vtkEarthSource… <p>C#でVTKのvtkEarthSourceクラスによって地球を表示させる.</p> <div class="section"> <h3>ActiViz</h3> <p><a href="http://www.kitware.com/opensource/avdownload.php">ActiViz</a>は,3Dコンピュータグラフィックスの可視化ライブラリ<a href="http://www.vtk.org/">VTK&#xFF08;The Visualization ToolKit&#xFF09;</a>のC#ラッパである.NuGetからインストールできる.簡単な解説は以下のページを参照.<br /> <a href="http://whoopsidaisies.hatenablog.com/entry/2013/12/28/131053"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2013%2F12%2F28%2F131053" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2013/12/28/131053">C#&#x3067;3D&#x30E2;&#x30C7;&#x30EB;&#x8868;&#x793A;&#xFF08;VTK&#x306E;C#&#x30E9;&#x30C3;&#x30D1;ActiViz&#x306B;&#x3088;&#x308B;&#x65B9;&#x6CD5;&#xFF09; - whoopsidaisies&#39;s diary</a><br /> </p> </div> <div class="section"> <h3>RenderWindowControl</h3> <p>NuGetからActiVizをインストールし,RenderWindowControlをフォームに追加する.</p> </div> <div class="section"> <h3>vtkEarthSource</h3> <p>VTKには<a href="http://www.vtk.org/doc/release/5.0/html/a01341.html">vtkEarthSource</a>という,地球が表示されるオブジェクトがあるので使う.ソースコードは以下のようになる.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synStatement">using</span> (var earth = <span class="synStatement">new</span> Kitware.VTK.vtkEarthSource()) <span class="synStatement">using</span> (var mapper = <span class="synStatement">new</span> Kitware.VTK.vtkCompositePolyDataMapper()) <span class="synStatement">using</span> (var actor = <span class="synStatement">new</span> Kitware.VTK.vtkActor()) { mapper.SetInputConnection(earth.GetOutputPort()); actor.SetMapper(mapper); renderWindowControl1.RenderWindow.GetRenderers().GetFirstRenderer().AddActor(actor); } </pre><p>実行すると以下のように地球が表示される.ドラッグで視点変更が出来る.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140209/20140209185406.png" alt="f:id:whoopsidaisies:20140209185406p:plain" title="f:id:whoopsidaisies:20140209185406p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> whoopsidaisies C++でLINQライクな処理(LINQ for C++による方法) hatenablog://entry/12921228815716655711 2014-01-17T01:12:13+09:00 2014-01-17T01:12:13+09:00 LINQ for C++ LINQは.NET Framework3.5から組み込まれた機能で,C#等の言語でSQLのデータベース操作のようなことを可能とする.「C# is LINQ」と言う方までいほどに便利な機能.しかし,C++/CLIはLINQに対応する予定はないとのこと.そこで,LINQに似た機能をC++に提供してくれるのがLINQ for C++である.というわけでLINQ for C++を使ってみる. 導入 LINQ for C++はヘッダファイルひとつで実装されているので,以下のページからダウンロードしてきてインクルードするだけで使用できる.NuGetからのインストールも取得可能であ… <div class="section"> <h3>LINQ for C++</h3> <p><a href="http://ja.wikipedia.org/wiki/%E7%B5%B1%E5%90%88%E8%A8%80%E8%AA%9E%E3%82%AF%E3%82%A8%E3%83%AA">LINQ</a>は.NET Framework3.5から組み込まれた機能で,C#等の言語でSQLのデータベース操作のようなことを可能とする.「<a href="http://www.slideshare.net/neuecc/the-history-of-linq/19">C# is LINQ</a>」と言う方までいほどに便利な機能.</p><p>しかし,<a href="http://ja.wikipedia.org/wiki/%E7%B5%B1%E5%90%88%E8%A8%80%E8%AA%9E%E3%82%AF%E3%82%A8%E3%83%AA">C++/CLI&#x306F;LINQ&#x306B;&#x5BFE;&#x5FDC;&#x3059;&#x308B;&#x4E88;&#x5B9A;&#x306F;&#x306A;&#x3044;</a>とのこと.そこで,LINQに似た機能をC++に提供してくれるのが<a href="http://cpplinq.codeplex.com/">LINQ for C++</a>である.というわけでLINQ for C++を使ってみる.</p> </div> <div class="section"> <h3>導入</h3> <p>LINQ for C++はヘッダファイルひとつで実装されているので,以下のページからダウンロードしてきてインクルードするだけで使用できる.NuGetからのインストールも取得可能である.</p><p><a href="http://cpplinq.codeplex.com/"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fcpplinq.codeplex.com%2F" alt="" class="http-favicon" /></a><a href="http://cpplinq.codeplex.com/">LINQ for C++ - Home</a><br /> </p> </div> <div class="section"> <h3>使用例1</h3> <p>以下に使用例を示す.LINQ for C++を使って,テストの成績のうち国語と英語がともに50点以上の人のリストを取得している.</p><p>普通の配列に対して使うことが出来る.コード補完も微妙だし,型明記しなくちゃいけないし,メソッド形式ないしでC#のLINQほど軽快には書けないものの,便利ではある.</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synPreProc">#include </span><span class="synConstant">&lt;cpplinq.hpp&gt;</span> <span class="synType">void</span> main() { <span class="synStatement">using</span> <span class="synType">namespace</span> cpplinq; <span class="synType">struct</span> Seiseki { <span class="synType">char</span> Name[<span class="synConstant">256</span>]; <span class="synType">int</span> Kokugo; <span class="synType">int</span> Sansuu; <span class="synType">int</span> Eigo; <span class="synType">int</span> Rika; <span class="synType">int</span> Shakai; }; Seiseki seisekiList[] = { {<span class="synConstant">&quot;Yamada&quot;</span>,<span class="synConstant">98</span>,<span class="synConstant">78</span>,<span class="synConstant">61</span>,<span class="synConstant">83</span>,<span class="synConstant">70</span>}, {<span class="synConstant">&quot;Tanaka&quot;</span>,<span class="synConstant">20</span>,<span class="synConstant">33</span>,<span class="synConstant">16</span>,<span class="synConstant">39</span>,<span class="synConstant">48</span>}, {<span class="synConstant">&quot;Yoshida&quot;</span>,<span class="synConstant">72</span>,<span class="synConstant">65</span>,<span class="synConstant">92</span>,<span class="synConstant">13</span>,<span class="synConstant">26</span>}, {<span class="synConstant">&quot;Suzuki&quot;</span>,<span class="synConstant">49</span>,<span class="synConstant">82</span>,<span class="synConstant">55</span>,<span class="synConstant">11</span>,<span class="synConstant">96</span>}, {<span class="synConstant">&quot;Sasaki&quot;</span>,<span class="synConstant">83</span>,<span class="synConstant">47</span>,<span class="synConstant">61</span>,<span class="synConstant">23</span>,<span class="synConstant">60</span>} }; <span class="synType">auto</span> result = from_array(seisekiList) &gt;&gt; where([](Seiseki s) <span class="synError">{</span><span class="synStatement">return</span> s.Kokugo &gt; <span class="synConstant">50</span> &amp;&amp; s.Eigo &gt; <span class="synConstant">50</span>;}) &gt;&gt; to_vector(); <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; result.size(); ++ i) printf(<span class="synConstant">&quot;</span><span class="synSpecial">%s</span><span class="synConstant"> : 国語</span><span class="synSpecial">%d</span><span class="synConstant"> 英語</span><span class="synSpecial">%d\n</span><span class="synConstant">&quot;</span>, result[i].Name, result[i].Kokugo, result[i].Eigo); } </pre><p>結果は以下のように表示される.</p> <pre class="code" data-lang="" data-unlink>Yamada : 国語98 英語61 Yoshida : 国語72 英語92 Sasaki : 国語83 英語61</pre> </div> <div class="section"> <h3>使用例2</h3> <p>無理やりOpenCVで使ってみる.BRISKで特徴点抽出し,オリエンテーションの向きによって表示する際の色を変えている.</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/opencv.hpp&gt;</span> <span class="synPreProc">#include </span><span class="synConstant">&lt;cpplinq.hpp&gt;</span> <span class="synType">void</span> main() { <span class="synStatement">using</span> <span class="synType">namespace</span> cpplinq; <span class="synType">auto</span> image = cv::imread(<span class="synConstant">&quot;Penguins.jpg&quot;</span>); <span class="synType">auto</span> detector = cv::FeatureDetector::create(<span class="synConstant">&quot;BRISK&quot;</span>); std::vector&lt;cv::KeyPoint&gt; keyPoints; detector-&gt;detect(image, keyPoints); <span class="synType">auto</span> key1 = from(keyPoints) &gt;&gt; where([](cv::KeyPoint k) <span class="synError">{</span> <span class="synStatement">return</span> <span class="synConstant">0</span> &lt;= k.angle &amp;&amp; k.angle &lt; <span class="synConstant">90</span>;}) &gt;&gt; to_vector(); <span class="synType">auto</span> key2 = from(keyPoints) &gt;&gt; where([](cv::KeyPoint k) <span class="synError">{</span> <span class="synStatement">return</span> <span class="synConstant">90</span> &lt;= k.angle &amp;&amp; k.angle &lt; <span class="synConstant">180</span>;}) &gt;&gt; to_vector(); <span class="synType">auto</span> key3 = from(keyPoints) &gt;&gt; where([](cv::KeyPoint k) <span class="synError">{</span> <span class="synStatement">return</span> <span class="synConstant">180</span> &lt;= k.angle &amp;&amp; k.angle &lt; <span class="synConstant">270</span>;}) &gt;&gt; to_vector(); <span class="synType">auto</span> key4 = from(keyPoints) &gt;&gt; where([](cv::KeyPoint k) <span class="synError">{</span> <span class="synStatement">return</span> <span class="synConstant">270</span> &lt;= k.angle &amp;&amp; k.angle &lt; <span class="synConstant">360</span>;}) &gt;&gt; to_vector(); cv::drawKeypoints(image, key1, image, cv::Scalar(<span class="synConstant">255</span>,<span class="synConstant">0</span>,<span class="synConstant">0</span>), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::drawKeypoints(image, key2, image, cv::Scalar(<span class="synConstant">0</span>,<span class="synConstant">255</span>,<span class="synConstant">0</span>), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::drawKeypoints(image, key3, image, cv::Scalar(<span class="synConstant">0</span>,<span class="synConstant">0</span>,<span class="synConstant">255</span>), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::drawKeypoints(image, key4, image, cv::Scalar(<span class="synConstant">255</span>,<span class="synConstant">255</span>,<span class="synConstant">0</span>), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::imshow(<span class="synConstant">&quot;Key Point&quot;</span>, image); <span class="synStatement">while</span>(cv::waitKey(<span class="synConstant">1</span>) == -<span class="synConstant">1</span>); } </pre><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140117/20140117010914.png" alt="f:id:whoopsidaisies:20140117010914p:plain" title="f:id:whoopsidaisies:20140117010914p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> whoopsidaisies C# 名前付きの色一覧を配列に取得してRGB値をDataGridViewに表示する hatenablog://entry/12921228815716589098 2014-01-15T20:24:29+09:00 2014-01-15T20:24:29+09:00 Color構造体 .NET FrameworkのColor構造体はRGB値で色の指定もできるが,あらかじめRGB値が指定されていて名前を指定して使える色がある.「Color.Red」とか「Color.Green」といった感じで使うことが出来る.本記事では,名前が付いた色の一覧を取得してColor構造体の配列に取得,さらにRGB値と色をDataGridViewに表示する方法を紹介する. 名前付きの色の取得 名前付きの色は,Color構造体の静的プロパティとして定義されている.色の一覧をColor構造体の配列に格納するコードは以下のようになる. var colors = typeof(Color)… <div class="section"> <h3>Color構造体</h3> <p>.NET Frameworkの<a href="http://msdn.microsoft.com/ja-jp/library/system.drawing.color(v=vs.110).aspx">Color&#x69CB;&#x9020;&#x4F53;</a>はRGB値で色の指定もできるが,あらかじめRGB値が指定されていて名前を指定して使える色がある.「Color.Red」とか「Color.Green」といった感じで使うことが出来る.</p><p>本記事では,名前が付いた色の一覧を取得してColor構造体の配列に取得,さらにRGB値と色をDataGridViewに表示する方法を紹介する.</p> </div> <div class="section"> <h3>名前付きの色の取得</h3> <p>名前付きの色は,Color構造体の静的プロパティとして定義されている.色の一覧をColor構造体の配列に格納するコードは以下のようになる.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>var colors = <span class="synStatement">typeof</span>(Color).GetProperties(BindingFlags.Static | BindingFlags.Public) .Select(p =&gt; Color.FromName(p.Name)) .ToList(); </pre><p>1行目では,<a href="http://msdn.microsoft.com/ja-jp/library/kyaxdd3x(v=vs.110).aspx">GetProperties</a>メソッドを使って,Color構造体のパブリックな静的プロパティの型情報の一覧を取得している.<a href="http://msdn.microsoft.com/ja-jp/library/system.reflection.bindingflags(v=vs.110).aspx">BindingFlags</a>構造体を使って取得するプロパティの検索方法を指定できるが,StaticとPublicを指定することでパブリックな静的プロパティを取得している.</p><p>2行目では,<a href="http://ufcpp.net/study/csharp/sp3_linq.html">LINQ</a>の<a href="http://msdn.microsoft.com/ja-jp/library/bb548891(v=vs.110).aspx">Select</a>メソッドと<a href="http://msdn.microsoft.com/ja-jp/library/system.drawing.color.fromname(v=vs.110).aspx:Color.FromaName">http://msdn.microsoft.com/ja-jp/library/system.drawing.color.fromname(v=vs.110).aspx:Color.FromaName</a>メソッドを使って色の名前から,その色のColorオブジェクトを生成している.</p><p>3行目で,結果をList<Color>に変換している.(ListとかArrayとかに変換したほうが後の処理が楽なので)</p> </div> <div class="section"> <h3>DataGridViewで表示</h3> <p>取得した色の一覧を<a href="http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridview(v=vs.110).aspx">DataGridView</a>コントロールに表示する.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>dataGridView1.DataSource = colors; </pre><p>上記の一行を追加すると以下のように色の名前とRGB値が表示される.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140115/20140115195242.png" alt="f:id:whoopsidaisies:20140115195242p:plain" title="f:id:whoopsidaisies:20140115195242p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>表示するプロパティの選択</h3> <p>上の画像だと「IsKnownColor」とかの余計なプロパティも表示されているので,表示しないようにする.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synStatement">foreach</span> (DataGridViewColumn col <span class="synStatement">in</span> dataGridView1.Columns) <span class="synStatement">if</span> (col.Name != <span class="synConstant">&quot;R&quot;</span> &amp;&amp; col.Name != <span class="synConstant">&quot;G&quot;</span> &amp;&amp; col.Name != <span class="synConstant">&quot;B&quot;</span> &amp;&amp; col.Name != <span class="synConstant">&quot;Name&quot;</span>) col.Visible = <span class="synConstant">false</span>; </pre><p>DataGridViewの各列は<a href="http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridviewcolumn.visible(v=vs.110).aspx">Visible</a>プロパティによって表示・非表示を切り替えられるので,RGBと名前以外の列を非表示に設定している.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140115/20140115200155.png" alt="f:id:whoopsidaisies:20140115200155p:plain" title="f:id:whoopsidaisies:20140115200155p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>セルの色付け</h3> <p>名前とRGB値だけだとどんな色か想像がつきにくいので,セルに色を付ける.ついでに名前が表示されている列を先頭にする.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; colors.Count; ++i) dataGridView1[<span class="synConstant">&quot;Name&quot;</span>, i].Style.BackColor = colors[i]; dataGridView1.Columns[<span class="synConstant">&quot;Name&quot;</span>].DisplayIndex = <span class="synConstant">0</span>; </pre><p>DataGridViewの各<a href="http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridviewcell(v=vs.110).aspx">&#x30BB;&#x30EB;</a>は<a href="http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridviewcell.style(v=vs.110).aspx">Style</a>プロパティによって<a href="http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridviewcellstyle(v=vs.110).aspx">&#x8272;&#x3084;&#x30D5;&#x30A9;&#x30F3;&#x30C8;&#x7B49;&#x306E;&#x66F8;&#x5F0F;</a>を指定出来る.ここでは<a href="http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridviewcellstyle.backcolor(v=vs.110).aspx">BackColor</a>プロパティによって背景色を指定している.</p><p>また,<a href="http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridviewcolumn.displayindex(v=vs.110).aspx">DisplayIndex</a>プロパティによって名前の表示列を先頭にしている.</p><p>実行すると以下のように名前のセルに色がついて表示される.(Transparentのところは後ろのウィンドウが表示されている.)</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140115/20140115201854.png" alt="f:id:whoopsidaisies:20140115201854p:plain" title="f:id:whoopsidaisies:20140115201854p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>ソースコード</h3> <p>上記コードをまとめると以下のようになる.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>var colors = <span class="synStatement">typeof</span>(Color).GetProperties(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public) .Select(p =&gt; Color.FromName(p.Name)) .ToList(); dataGridView1.DataSource = colors; <span class="synStatement">foreach</span> (DataGridViewColumn col <span class="synStatement">in</span> dataGridView1.Columns) <span class="synStatement">if</span> (col.Name != <span class="synConstant">&quot;R&quot;</span> &amp;&amp; col.Name != <span class="synConstant">&quot;G&quot;</span> &amp;&amp; col.Name != <span class="synConstant">&quot;B&quot;</span> &amp;&amp; col.Name != <span class="synConstant">&quot;Name&quot;</span>) col.Visible = <span class="synConstant">false</span>; <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; colors.Count; ++i) dataGridView1[<span class="synConstant">&quot;Name&quot;</span>, i].Style.BackColor = colors[i]; dataGridView1.Columns[<span class="synConstant">&quot;Name&quot;</span>].DisplayIndex = <span class="synConstant">0</span>; </pre> </div> whoopsidaisies C#でOpenCVを使う(C++/CLIによる方法) hatenablog://entry/12921228815716339920 2014-01-12T11:30:50+09:00 2014-01-12T11:30:50+09:00 OpenCVラッパクラス C#でOpenCVを手軽に使うにはOpenCvSharpをつかう その17(NuGetで導入) - schima.hatenablog.com C#でOpenCVを動かす~NuGetでOpenCV.Netをインストール - whoopsidaisies's diaryのページのように,NuGetからC#ラッパをインストールして使う方法があるが,必要な機能がラッピングされていないことがある.このページでは,C++/CLIでOpenCVの必要な機能だけ持つラッパクラスを自分で作り,C#から呼び出す方法を紹介する. C++/CLI 通常のC++のライブラリをC#から呼び出そ… <div class="section"> <h3>OpenCVラッパクラス</h3> <p>C#でOpenCVを手軽に使うには</p><p><a href="http://schima.hatenablog.com/entry/2013/12/15/110513"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fschima.hatenablog.com%2Fentry%2F2013%2F12%2F15%2F110513" alt="" class="http-favicon" /></a><a href="http://schima.hatenablog.com/entry/2013/12/15/110513">OpenCvSharp&#x3092;&#x3064;&#x304B;&#x3046; &#x305D;&#x306E;17(NuGet&#x3067;&#x5C0E;&#x5165;) - schima.hatenablog.com</a><br /> <a href="http://whoopsidaisies.hatenablog.com/entry/2013/10/25/005953"><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fwhoopsidaisies.hatenablog.com%2Fentry%2F2013%2F10%2F25%2F005953" alt="" class="http-favicon" /></a><a href="http://whoopsidaisies.hatenablog.com/entry/2013/10/25/005953">C#&#x3067;OpenCV&#x3092;&#x52D5;&#x304B;&#x3059;&#xFF5E;NuGet&#x3067;OpenCV.Net&#x3092;&#x30A4;&#x30F3;&#x30B9;&#x30C8;&#x30FC;&#x30EB; - whoopsidaisies&#39;s diary</a></p><p>のページのように,NuGetからC#ラッパをインストールして使う方法があるが,必要な機能がラッピングされていないことがある.</p><p>このページでは,C++/CLIでOpenCVの必要な機能だけ持つラッパクラスを自分で作り,C#から呼び出す方法を紹介する.</p> </div> <div class="section"> <h3>C++/CLI</h3> <p>通常のC++のライブラリをC#から呼び出そうとするとDllImport属性で宣言が必要だったりして面倒であるが,<a href="http://ja.wikipedia.org/wiki/C%2B%2B/CLI">C++/CLI</a>で作ったDLLであれば参照に追加するだけで使用できる.</p> </div> <div class="section"> <h3>手順</h3> <p>手順は以下の通りである.</p> <div class="section"> <h5>C#プロジェクト作成</h5> <p>実行されるC#のプロジェクト</p> </div> <div class="section"> <h5>C++/CLIのDLL用プロジェクト作成</h5> <p>OpenCVをラップするクラス用のプロジェクト</p> </div> <div class="section"> <h5>プロジェクトの参照の設定</h5> <p>作成したクラスをC#から読み込むための設定</p> </div> <div class="section"> <h5>OpenCVのインストール</h5> <p>OpenCVのインストール</p> </div> <div class="section"> <h5>C++/CLIでラッパクラスの作成</h5> <p>OpenCVによる処理部分の実装</p> </div> <div class="section"> <h5>C#のプロジェクトの出力パスの変更</h5> <p>OpenCVのDLLの場所とかの関係上の設定</p> </div> <div class="section"> <h5>C#から呼び出す</h5> <p>C#からの呼び出し部分とGUIの実装</p><br /> <p>以下に各手順の詳細を記す.</p> </div> </div> <div class="section"> <h3>C#プロジェクト作成</h3> <p>Visual Studioで新しいプロジェクトを作成する.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140112/20140112101313.png" alt="f:id:whoopsidaisies:20140112101313p:plain" title="f:id:whoopsidaisies:20140112101313p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> <div class="section"> <h3>C++/CLIのDLL用プロジェクト作成</h3> <p>ソリューションを右クリックして,「追加」の「新しいプロジェクト(N)...」でC++/CLIのDLL作成用のプロジェクトを作成する.「Visual C++」の「CLR」の「クラス ライブラリ」を選択.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140112/20140112101334.png" alt="f:id:whoopsidaisies:20140112101334p:plain" title="f:id:whoopsidaisies:20140112101334p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> <div class="section"> <h3>プロジェクトの参照の設定</h3> <p>C++/CLIで作成したDLLをC#から呼び出すための参照設定を行う.C#のプロジェクト内の「参照設定」を右クリックし「参照の追加(R)...」を選択する.開いたダイアログで「ソリューション」の「プロジェクト」を選択し,C++/CLIのプロジェクトの名前のところにチェックを入れる.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140112/20140112101620.png" alt="f:id:whoopsidaisies:20140112101620p:plain" title="f:id:whoopsidaisies:20140112101620p:plain" class="hatena-fotolife" itemprop="image"></span><br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140112/20140112102324.png" alt="f:id:whoopsidaisies:20140112102324p:plain" title="f:id:whoopsidaisies:20140112102324p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> <div class="section"> <h3>OpenCVのインストール</h3> <p>C++/CLIのプロジェクトを右クリックし「NuGet パッケージの管理」を選択.ダイアログで「オンライン」を選択し,検索窓で「OpenCV」を検索,インストールする.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140112/20140112101806.png" alt="f:id:whoopsidaisies:20140112101806p:plain" title="f:id:whoopsidaisies:20140112101806p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> <div class="section"> <h3>C#のプロジェクトの出力パスの変更</h3> <p>NuGetでインストールしたOpenCVのDLLが,C#プロジェクトで作成した実行ファイルから参照できる位置に配置されないため,実行ファイルの出力パスを変えてやる.C#のプロジェクトを右クリックし「プロパティ(R)」を選択.「ビルド」の「出力パス」を「..\Debug\」に変える(Releaseモードなら..\Release\).<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140112/20140112110351.png" alt="f:id:whoopsidaisies:20140112110351p:plain" title="f:id:whoopsidaisies:20140112110351p:plain" class="hatena-fotolife" itemprop="image"></span><br /> この手順を忘れると,実行時に以下のようなエラーメッセージが表示されてOpenCVの呼び出しに失敗する.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140112/20140112110400.png" alt="f:id:whoopsidaisies:20140112110400p:plain" title="f:id:whoopsidaisies:20140112110400p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> <div class="section"> <h3>C++/CLIでラッパクラスの作成</h3> <p>C++/CLIでOpenCVの処理のコードを書く.C++/CLIのプロジェクトを作成したときに色々とファイルが生成されているので,そのうちの「OpenCvClrLibrary.h」(プロジェクト名.h)を以下のようにする.画像をファイルから読み込んで,BRISK特徴点を抽出して表示するサンプルである.</p> <pre class="code lang-cpp" data-lang="cpp" data-unlink><span class="synComment">// OpenCvClrLibrary.h</span> <span class="synPreProc">#pragma once</span> <span class="synPreProc">#include </span><span class="synConstant">&lt;opencv2/opencv.hpp&gt;</span> <span class="synStatement">using</span> <span class="synType">namespace</span> System; <span class="synType">namespace</span> OpenCvClrLibrary { <span class="synStatement">public</span> ref <span class="synType">class</span> TestClass { <span class="synStatement">public</span>: <span class="synType">static</span> <span class="synType">void</span> TestMethod() { <span class="synType">auto</span> image = cv::imread(<span class="synConstant">&quot;Penguins.jpg&quot;</span>); <span class="synType">auto</span> brisk = cv::BRISK(); std::vector&lt;cv::KeyPoint&gt; keyPoint; brisk.detect(image, keyPoint); cv::drawKeypoints(image, keyPoint, image); cv::imshow(<span class="synConstant">&quot;image&quot;</span>, image); <span class="synStatement">while</span> (cv::waitKey(<span class="synConstant">1</span>) == -<span class="synConstant">1</span>); cv::destroyAllWindows(); } }; } </pre><p>「ref class」はC++/CLI用のクラス.詳細は省略するが,こういう書き方をすることでC#でそのまま使えるクラスを作れる.<br /> 「auto」はc++11から追加された機能で,変数の初期値から型推論を行ってくれる.Visual Studio 2012以降では使えるみたい.横に長くなりがちなOpenCV(に限らないけど)のコードではこれを使えるのは嬉しい.</p> </div> <div class="section"> <h3>C#から呼び出す</h3> <p>C#から上記の特徴点抽出処理を呼び出すコードを以下のように書く.</p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synStatement">using</span> System; <span class="synStatement">using</span> System.Windows.Forms; <span class="synType">namespace</span> OpenCvFromCSharp { <span class="synType">public</span> <span class="synStatement">partial</span> <span class="synType">class</span> Form1 : Form { <span class="synType">public</span> Form1() { InitializeComponent(); } <span class="synType">private</span> <span class="synType">void</span> button1_Click(<span class="synType">object</span> sender, EventArgs e) { OpenCvClrLibrary.TestClass.TestMethod(); } } } </pre><p>Buttonコントロールを配置して,クリックすると特徴点が書き込まれた画像が以下のように表示される.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140112/20140112104341.png" alt="f:id:whoopsidaisies:20140112104341p:plain" title="f:id:whoopsidaisies:20140112104341p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> whoopsidaisies C#でAI,PSD,EPS,SVG,PDF等の画像ファイルを開く(ImageMagickのC#ラッパMagick.NETによる方法) hatenablog://entry/12921228815716075117 2014-01-08T21:32:52+09:00 2014-01-08T21:32:53+09:00 Magick.NET 100種類以上の画像を操作したり表示したりできるライブラリImageMagickのC#ラッパMagick.NETを使って,C#でAI,PSD,EPS,SVG,PDF等の画像ファイルを開く. インストール NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「Magick.NET」を検索してインストール. プラットフォームを変える プロジェクトのプラットフォームをインストールしたパッケージ(「x64」か「x86」)に変える.「Any CPU」だと動かない場合があるので注意. サンプルコード 以下にepsファイ… <div class="section"> <h3>Magick.NET</h3> <p>100種類以上の画像を操作したり表示したりできるライブラリ<a href="http://www.imagemagick.org/script/index.php">ImageMagick</a>のC#ラッパ<a href="https://magick.codeplex.com/">Magick.NET</a>を使って,C#でAI,PSD,EPS,SVG,PDF等の画像ファイルを開く.</p> </div> <div class="section"> <h3>インストール</h3> <p>NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「Magick.NET」を検索してインストール.</p><p><span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140108/20140108210712.png" alt="f:id:whoopsidaisies:20140108210712p:plain" title="f:id:whoopsidaisies:20140108210712p:plain" class="hatena-fotolife" itemprop="image"></span><br /> </p> </div> <div class="section"> <h3>プラットフォームを変える</h3> <p>プロジェクトのプラットフォームをインストールしたパッケージ(「x64」か「x86」)に変える.「Any CPU」だと動かない場合があるので注意.</p> </div> <div class="section"> <h3>サンプルコード</h3> <p>以下にepsファイルを開いて,PictureBoxに表示するサンプルを示す.ファイル名の部分を変えれば,eps以外のファイルも読み込むことが出来る.</p> <pre class="code lang-cs" data-lang="cs" data-unlink>var magickImage = <span class="synStatement">new</span> ImageMagick.MagickImage( <span class="synSpecial">@</span><span class="synConstant">&quot;blossom tree.eps&quot;</span>, <span class="synStatement">new</span> ImageMagick.MagickReadSettings() { Density = <span class="synStatement">new</span> ImageMagick.MagickGeometry(<span class="synConstant">300</span>, <span class="synConstant">300</span>) }); pictureBox1.Image = magickImage.ToBitmap(); </pre><p>ImageMagick.MagickGeometry(300, 300)の数字の部分を大きくすると,AI,EPS,PDF等のベクター画像の読み込み後の解像度を高くすることが出来る.</p><p>以下のように,ベクター画像を高解像度にすると拡大してもきれいに表示出来る.<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140108/20140108211811.jpg" alt="f:id:whoopsidaisies:20140108211811j:plain" title="f:id:whoopsidaisies:20140108211811j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/w/whoopsidaisies/20140108/20140108211819.png" alt="f:id:whoopsidaisies:20140108211819p:plain" title="f:id:whoopsidaisies:20140108211819p:plain" class="hatena-fotolife" itemprop="image"></span></p> </div> whoopsidaisies