Mask R-CNNを試す

はじめに

Mask R-CNNとはICCV 2017 Best Paper に選出された手法で、物体検出Object Dectectionやセマンティック・セグメンテーションSemantic Segmentationを実現するための手法である。COCOデータセットにより学習した、Matterport Mask_RCNNモデルを利用して、デモ画像より物体検出、セグメンテーションデモをGoogle colabで動かしてみよう。

デモを動かそう

Matterport Mask_RCNN、COCO API・Datasetのインストール、デフォルトのデモを動かす手順の以下の通り。

・Mask_RCNNのインストール、セットアップ

%cd /content/drive/My Drive
!git clone https://github.com/matterport/Mask_RCNN.git
%cd ./Mask_RCNN
!pip install -r requirements.txt
%run -i setup.py install

・COCO APIのインストール、セットアップ

%cd ..
!git clone https://github.com/waleedka/coco.git
%cd ./coco/PythonAPI
%run -i setup.py build_ext --inplace

・COCO Datasetで学習したMask_RCNNモデルのインストール

import os
import sys
import random
import math
import numpy as np
import skimage.io
import matplotlib
import matplotlib.pyplot as plt

# Root directory of the project
ROOT_DIR = os.path.abspath("/content/drive/My Drive/Mask_RCNN")

<pre class="brush: actionscript3; gutter: false">
# Import Mask RCNN
sys.path.append(ROOT_DIR)  # To find local version of the library
from mrcnn import utils
import mrcnn.model as modellib
from mrcnn import visualize
# Import COCO config
sys.path.append(os.path.join(ROOT_DIR, "samples/coco/"))  # To find local version
import coco

%matplotlib inline 

# Directory to save logs and trained model
MODEL_DIR = os.path.join(ROOT_DIR, "logs")

# Local path to trained weights file
COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco.h5")
# Download COCO trained weights from Releases if needed
if not os.path.exists(COCO_MODEL_PATH):
    utils.download_trained_weights(COCO_MODEL_PATH)

# Directory of images to run detection on
IMAGE_DIR = os.path.join(ROOT_DIR, "images")

class InferenceConfig(coco.CocoConfig):
    # Set batch size to 1 since we'll be running inference on
    # one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU
    GPU_COUNT = 1
    IMAGES_PER_GPU = 1

config = InferenceConfig()
# config.display()

いよいよ認識しようと、以下のpythonコードを実行する。

# Create model object in inference mode.
model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)

# Load weights trained on MS-COCO
model.load_weights(COCO_MODEL_PATH, by_name=True)

# COCO Class names
# Index of the class in the list is its ID. For example, to get ID of
# the teddy bear class, use: class_names.index('teddy bear')
class_names = ['BG', 'person', 'bicycle', 'car', 'motorcycle', 'airplane',
               'bus', 'train', 'truck', 'boat', 'traffic light',
               'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird',
               'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear',
               'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie',
               'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball',
               'kite', 'baseball bat', 'baseball glove', 'skateboard',
               'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup',
               'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
               'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza',
               'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed',
               'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote',
               'keyboard', 'cell phone', 'microwave', 'oven', 'toaster',
               'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors',
               'teddy bear', 'hair drier', 'toothbrush']
# Load a random image from the images folder
file_names = next(os.walk(IMAGE_DIR))[2]
for file_name in file_names:
  image = skimage.io.imread(os.path.join(IMAGE_DIR, file_name))

  # Run detection
  results = model.detect([image], verbose=1)

  # Visualize results
  r = results[0]
  visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], 
                              class_names, r['scores'])

うまくいけばSemantic Segmentationでマスクしたデモ画像が表示される。

Mask_RCNNデモ
Mask_RCNNデモ

※ Mask_RCNNの利用は、以下のとおりtensorflowバージョンを1.xに、

%tensorflow_version 1.x
import tensorflow
print(tensorflow.__version__)

ランタイムのタイプをGPUに設定して再起動して、またもう1回tensorflowバージョンを1.xにして確認する。

%tensorflow_version 1.x
import tensorflow
print(tensorflow.__version__)

デモの画像を入れ替えてみよう

images直下のデモ画像を入れ替えて上記pythonコードを実行してたら、以下画像のようにDining tableの一部が未検出であった。

Mask_RCNNテーブル一部検出
Mask_RCNNテーブル一部検出

Notebook ipynbファイルがGithubへ公開済み。

感想

デモ画像がよさそうに検出できたように見えますが、入れ替えたらそうでもない結果となった。やはり検出の正確性が学習モデルに大いに相関することで、専用学習データで学習モデルを作成しないと納得いく結果が得られず。画像データアノテーションImage Data Annotation業務が請負可能な業者さんがドンドン増えているらしい。

参考文献

Matterport Mask_RCNN on Github.

以上

1+

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア

struct2depth~単眼カメラ2D camera Visual SLAM

はじめに

Google がTensorflowのResearch Modelとしてstruct2depth、vid2depthを公開したので、struct2depthを利用して単眼カメラMonocular Cameraで撮った写真から深度Depthを推定してみよう。struct2depth、vid2depthは、KITTIまたは、CITYSCAPEの学習データを通してVisual Odometry、Depthの推定を習得するモデルである。また他の学習データを入れ替えてもあり得ると考えられる。SFM:Structure From Motionに基づく技術で、Depth深度まで推定できれば、3D Recontruction3次元復元まで使われる。

実測

雑居ビール内、ドラッグストア前および、ホールで写真を撮って完了とした。

推定

画像サイズを416×128に縮小して、推定の時間を短縮する。

環境

・ Google Colab, 18.04.3 LTS Bionic Beaver, GPU Tesla k80
・ Tensorflow 1.15.2
・ Research model struct2depth/KITTI

手順

学習せずKITTIモデルをそのまま利用したので、推定手順は以下のとおり。
・tensorflow_versionを1.xに合わせる。

・ランタイムを再起動。

%tensorflow_version 1.x
import tensorflow
print(tensorflow.__version__)

・以下確認できるまで、またランタイムを再起動する。

TensorFlow 1.x selected.
1.15.2

・インファレンス

!python inference.py --logtostderr --file_extension png --depth --egomotion true --input_dir image --output_dir output --model_ckpt model/KITTI/model-199160

結果

単眼カメラで撮ったRGB写真、レンダリングした深度推定イメージを結果として出力される。点群データの3Dイメージは別途プログラムを作成してレンダリングRenderingとする。

うまくいく例

完璧ではないが、扉、旗まで殆ど良く推定できている。

struct2depth_depth_ok_case
struct2depth_depth_ok_case

mayaviで点群Point Cloudデータの3D表現

Mayaviは、matplotlibよりパワーアップして、強力なエンジンVTKを利用した3Dツールである。

point_cloud_3d_plot
point_cloud_3d_plot

上図のように3Dで写真を細かく表現できた。点群データ(npyファイル)による3D表現のpythonソースは、Githubへ公開済み。

うまくいかない例

左下に推定が失敗と見られる。他の場所はなんとなく推定てきている。

struct2depth_depth_ng_case
struct2depth_depth_ng_case

原因を探る

・ KITTIモデルは屋外モデルでそのままでは屋内に向かない場合ある。測定環境にふさわしい学習データセット(モデル)が必要である。
・ 照明の強弱、特徴量に大きく関わること。
・ ついてはまだ実験が不十分だが、商用可能なVisual SLAMに道が長く感じさせられる。

参考文献

Depth Prediction Without the Sensors: Leveraging Structure for Unsupervised Learning from Monocular Videos, Auther: Vincent Casser etc
github google tensorflow model struct2depth

以上

1+

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア

屋内3D地図で可視化、空間情報をスマート管理

インドアマップが活躍の時代に

オフィスビル、デパート、工場など建物の内部は構造が複雑で、通常の2D地図では各場所の違いを十分に表現できない課題がある。地理情報システムとビッグデータ技術の進歩により、3D地図が室内外の空間情報の可視化技術で設備管理のスマート化やIoTのソリューションを提供することで、この課題を解決する日が近づいている。商業施設、産業IoTの他、交通監視、観光、旅行、セキュリティ、消防、会議、展示、娯楽、公共サービス等の分野で活躍する時代が訪れる。

屋内3D地図が活躍の時代に
屋内3D地図が活躍の時代に

プロダクト・サービス

お客様に対して地図可視化プラットフォームを提供して、クラウド上で各シーンに対応した情報システムを構築する。弊社とFengMap社と連携して、屋内外の3Dマップの作成サービスを提供する。また、開発者向けには専用のエンジンを提供してより簡単に各OS環境に対応したマップアプリの開発ができるようになる。

プロダクト・サービス
プロダクト・サービス

商業施設へ展開の例

商業施設では、CADデータによって室内のデータモデルを構築して各店舗の経営内容を組み込むことで空間データモデルを形成する。それにより、ショッピング案内、店舗管理、経営状況などの情報を共有し、可視化できる。スマート現場クラウド監視プラットフォームを提供する。

スマート現場クラウド監視プラットフォーム
スマート現場クラウド監視プラットフォーム

産業IoTへ展開の例

産業用として、Fengmapは可視化技術をIoTと融合し、設備の位置確認機能構内の設備、車両、人員の所在地と状態を把握して作業のモニタリング、消費エネルギー量の管理、データ統計などを行うことができる。スマート工場可視化管理システムを提案する。

スマート工場可視化管理システム
スマート工場可視化管理システム

フェングマップ社について

Beijing FengMap Technology Co.LTDは、2013年に設立された、北京に拠点を置く技術会社です。同社は、屋内および屋外の空間情報の可視化研究と開発に焦点を当て、地図データの作成、地図の編集、 ストレージ、マップ統合ソフトウェアアプリケーション開発。 空間情報の可視化技術に基づいて、資産管理、人事管理、施設および環境の監視、リモート制御、データ分析を含むさまざまな管理ソフトウェアシステムを多くの顧客に提供しました。創業以来、同社は商業用不動産、工業用IoT、工業団地から、家庭および幅広い公共サービスまで、多くの顧客を獲得した。500社、8000案件を開発した実績をもつという。
英文サイト→ https://www.fengmap.com/en/

日本総代理店

フェングマップ3Dマッピング作成サービスおよびSDK販売。
株式会社翔雲 令和2年3月1日から新住所↓
〒260-0026 千葉市中央区千葉みなと2-2-1502
代表取締役 柳建雄 電話 050-3598-8286
会社サイト https://soarcloud.com
技術情報サイト https://memo.soarcloud.com
販売サイト https://store.soarcloud.com

令和2年4月~5月特別キャンペーンお知らせ

上記時間限定、利益なし特別価格で3D地図作成サービスをご利用いただけます。どうぞお気軽にお問合せされるよう宜しくお願い申し上げます。

1+

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア

機械学習の13、SVD特異値分解

はじめに

本文には、大文字表現=行列/マトリクス、\(\boldsymbol{bold}\)小文字表現=ベクトル\(R^d\)、普通小文字表現=スカラー\(R\) と記す。

SVD(Singular Value Decomposition)は機械学習の分野で広く使用されているアルゴリズムで、次元削減アルゴリズムの特徴分解だけでなく、推薦システム(Recommender System)や自然言語処理(Nature Language Process)にも使用される。

原理

SVDは前述した特徴分解同じく行列を分解するが、SVDは分解する行列が正方行列にする必要ない。行列Aの形状が\(m×n\)であると仮定すると、行列AのSVDを次のように定義する。
$$ A = UΣV^T $$
ただし、\(U\)は\(m×m\)の行列\((u_1, u_2,…, u_m)\)、\(Σ\)は\(m×n\)の行列、主対角線上の要素を除く全ての要素が実数ゼロ\(0\)であり、主対角線上の各要素は特異値(Singular Value)という、\(V\)は\(n×n\)行列\((v_1, v_2,…, v_n)\)。

\(A\)の転置\(A^T\)と\(A\)を行列で乗算すると、\(n×n\)の正方行列\(A^T A\)が得られる。\(A^T A\)は正方行列であるため、特徴の分解を実行でき、得られた固有値と固有ベクトルは次の式を満たす。
$$ (A^T A)\boldsymbol{v_i}=λ_i\boldsymbol{v_i} $$
これで行列\(A^T A\)の\(n\)個の固有値と対応する\(n\)個の固有ベクトル\(v_i\)を取得できる。

\(A\)と\(A\)の転置\(A^T\)を行列で乗算すると、\(m×m\)の正方行列\(AA^T\)が得られる。\(AA^T\)は正方行列であるため、特徴の分解を実行でき、得られた固有値と固有ベクトルは次の式を満たす。
$$ (AA^T) \boldsymbol{u_i}=λ_i\boldsymbol{u_i} $$
これで行列\(AA^T\)の\(m\)個の固有値と対応する\(m\)個の固有ベクトル\(u_i\)を取得できる。

\(Σ\)は対角線上の特異値を除いて全て\(0\)で、各特異値\(σ_i\)を見つけるだけで\(Σ\)が求められる。
$$ \sigma_i = \sqrt{λ_i} $$

各特異値\(σ_i\)のうち、比較的大きいほう(主成分)とそれに対応する特異ベクトル\(u_i, v_i\)を\(k\)個\((k << n)\)残すとAの次元を削減する。
$$ A_{m×n}=U_{m×m}Σ_{m×n}V^T_{n×n} ≈ U_{m×k}Σ_{k×k}V^T_{k×n} $$

実装

以下行列dataSetに対して、SVDアルゴリズムで\((U, \Sigma, V^T)\)を求めて、5次元→3次元つまり2次元を削減してが新しい\(\Sigma\)で\((U* \Sigma*V^T)\)が元の行列dataSetに戻せるかを確かめる。

from numpy import *
def loadExData():
    return[[0, 0, 0, 2, 2],
           [0, 0, 0, 3, 3],
           [0, 0, 0, 1, 1],
           [1, 1, 1, 0, 0],
           [2, 2, 2, 0, 0],
           [5, 5, 5, 0, 0],
           [1, 1, 1, 0, 0]]
dataSet = loadExData()
U, Sigma, VT = linalg.svd(dataSet)
print(f'dataSet:\n{dataSet}')
print(f'U:\n{U}\nSigma:\n{Sigma}\nVT:\n{VT}')
// 小さいSigmaを0にする(削除)
Sig3 = mat([[Sigma[0], 0, 0], [0, Sigma[1], 0], [0, 0, Sigma[2]]])
print(f'U[:,:3] * Sig3 * VT[:3,:]:\n{U[:,:3] * Sig3 * VT[:3,:]}')

ソースコード
https://github.com/soarbear/Machine_Learning/tree/master/svd

結果

\((U* \Sigma*V^T)\)は元のdataSetとほぼ同じ行列だと分かる。

dataSet:
[[0, 0, 0, 2, 2], [0, 0, 0, 3, 3], [0, 0, 0, 1, 1], [1, 1, 1, 0, 0], [2, 2, 2, 0, 0], [5, 5, 5, 0, 0], [1, 1, 1, 0, 0]]
U:
[[-2.22044605e-16  5.34522484e-01  8.41641151e-01 -1.37443101e-02
  -7.57428665e-02 -1.11022302e-16  1.38777878e-17]
 [ 0.00000000e+00  8.01783726e-01 -4.92426901e-01 -2.47257115e-01
   2.31349353e-01  3.15719673e-16 -2.77555756e-17]
 [ 0.00000000e+00  2.67261242e-01 -2.06001597e-01  7.69259966e-01
  -5.42562325e-01 -7.55450741e-16  1.09551769e-16]
 [-1.79605302e-01  2.77555756e-17 -3.00520660e-02 -2.15935735e-01
  -2.94749442e-01  9.05439185e-01 -1.16246358e-01]
 [-3.59210604e-01  5.55111512e-17 -6.01041319e-02 -4.31871470e-01
  -5.89498885e-01 -4.19124526e-01 -3.97074256e-01]
 [-8.98026510e-01  0.00000000e+00  3.60624791e-02  2.59122882e-01
   3.53699331e-01  5.40010673e-16 -6.71525577e-17]
 [-1.79605302e-01  2.77555756e-17 -3.00520660e-02 -2.15935735e-01
  -2.94749442e-01 -6.71901321e-02  9.10394870e-01]]
Sigma:
[9.64365076e+00 5.29150262e+00 8.36478329e-16 6.91811207e-17
 1.11917251e-33]
VT:
[[-5.77350269e-01 -5.77350269e-01 -5.77350269e-01  0.00000000e+00
   0.00000000e+00]
 [-2.46566547e-16  1.23283273e-16  1.23283273e-16  7.07106781e-01
   7.07106781e-01]
 [-7.01908483e-01 -1.02844064e-02  7.12192890e-01 -2.22044605e-16
  -1.66533454e-16]
 [-4.17122461e-01  8.16431808e-01 -3.99309347e-01  0.00000000e+00
  -1.11022302e-16]
 [-0.00000000e+00 -1.96261557e-16  1.96261557e-16  7.07106781e-01
  -7.07106781e-01]]
U[:,:3] * Sig3 * VT[:3,:]:
[[ 4.47427211e-17  1.57774942e-15  2.08638397e-15  2.00000000e+00
   2.00000000e+00]
 [-7.56974048e-16  5.27282824e-16  2.29691224e-16  3.00000000e+00
   3.00000000e+00]
 [-2.27747782e-16  1.76121044e-16  5.16267387e-17  1.00000000e+00
   1.00000000e+00]
 [ 1.00000000e+00  1.00000000e+00  1.00000000e+00  1.03851855e-16
   1.03851855e-16]
 [ 2.00000000e+00  2.00000000e+00  2.00000000e+00  2.07703709e-16
   2.07703709e-16]
 [ 5.00000000e+00  5.00000000e+00  5.00000000e+00 -6.69808260e-33
  -5.02356195e-33]
 [ 1.00000000e+00  1.00000000e+00  1.00000000e+00  1.03851855e-16
   1.03851855e-16]]

参考文献

[1] PeterHarrington. Machine Learning in Action.

2+

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア

機械学習の12、PCA主成分分析

はじめに

液晶画面に数百万画素で写された山の映像が目に入る途端に、脳が3次元の山にイメージするので、つまり多次元(数百万画素)のデータを主成分の3次元に削減(圧縮)すると考えられる。PCA(Principle Component Analysis)主成分分析は最も広く使用されている次元を削減するアルゴリズムで、\(n\)次元の特徴を\(m\)次元にマッピングすることである。主成分とも呼ばれるのは元のn次元の特徴から再構築された\(m\)次元の特徴である。そのうち最初の新しい座標軸の選択は元のデータで最大の分散を持つ方向であり、2番目の新しい座標軸の選択はこの座標軸における分散を最大化してかつ最初の座標軸と直交する座標軸であり、3番目の座標軸の選択はこの座標軸における分散を最大化してかつこれまで2つの軸と直交する座標軸であり、類推によってこのような座標軸を\(n\)個取得できる。殆どの分散が最初の軸\(m\)個に含まれて、後続の軸が騒音や相関などによりこれらの分散はゼロに近いことがわかる。従って残りの軸\((n-m)\)個を無視して最初の軸\(m\)個のみを残すと\(n\)次元の特徴をもつデータを\(m\)次元特徴空間に変換する。これで次元削減処理を実現することに相当する。

手順

・データの標準化、つまりデータからその特徴の平均値を差し引く
・共分散行列を計算
・共分散行列の固有値と固有ベクトルを計算
・固有値を大→小にソート
・最大の特徴ベクトルを保持
・データを特徴ベクトルによって構築された新しい空間に変換

実装

2次元のデータ6組\((-1, 1), (-2, -1), (-3, -2), (1, 1), (2, 1), (3, 2)\)の主成分を求める。

# Python PCA
import numpy as np
def pca(X,k):#k is remained components
  # Calculate mean of each feature
  n_samples, n_features = X.shape
  mean=np.array([np.mean(X[:,i]) for i in range(n_features)])
  # Calculate normalization
  norm_X = X - mean
  # Calculate cov matrix
  cov_matrix = np.dot(np.transpose(norm_X), norm_X)
  # Calculate eigen vectors and eigen values
  eig_val, eig_vec = np.linalg.eig(cov_matrix)
  eig_pairs = [(np.abs(eig_val[i]), eig_vec[:,i]) for i in range(n_features)]
  # Sort eig_vec based on eig_val from big to small
  eig_pairs.sort(reverse=True)
  # Select the top k eig_vec
  feature = np.array([ele[1] for ele in eig_pairs[:k]])
  # Get new data
  data = np.dot(norm_X, np.transpose(feature))
  return data
X = np.array([[-1, 1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
print(pca(X,1))

ソースコード
https://github.com/soarbear/Machine_Learning/tree/master/pca

結果

[[-0.50917706]
 [-2.40151069]
 [-3.7751606 ]
 [ 1.20075534]
 [ 2.05572155]
 [ 3.42937146]]

以下はsklearnを用いる例で、ソースは短くなるが結果の符号が逆になる。

# PCA with sklearn
from sklearn.decomposition import PCA
import numpy as np
X = np.array([[-1, 1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
pca=PCA(n_components=1)
pca.fit(X)
print(pca.transform(X))

参考文献

[1] PeterHarrington. Machine Learning in Action.

2+

ロボット・ドローン部品お探しなら
ROBOT翔・電子部品ストア