質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

静止画内のシール数を色別にその場でカウントしたい+静止画をその場で解析して対象の太さを大体知りたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,175

n-kk

score 10

お世話になっております。

今回は、python3 + opencv + tensorflow にて以下のようなことをやりたいと考えているのですが
どのようにすれば実現できるのか分からない為、ご質問させて下さい。

(やりたいこと) 
1.USBカメラで撮影した静止画の中にある色の付いたシールの個数を色別にカウントしたい。
⇒赤:4、青:3、黄:3、緑:3、白:3 など 
イメージ説明

2.1.の静止画でシールを貼ってある対象の太さを知りたい(画像はシールを貼ってあるものと仮定する)
イメージ説明

イメージとしては
撮影⇒設備配管の径とその本数、太さ、シールの色が知りたいです。
シールの色は配管の太さによって変えます
赤:100mm
青:80mm
などです。

OpenCVとtensorflowを使えば出来そうだと思っておりますが 
OpenCVを殆ど使ったことがない為、どういった具合で処理をかけばいいのかさっぱり分かりません。
こんな関数あるよとか、こんなライブラリ使えば直ぐできるよとか、こんな参考HPあるよといった
ありましたら、ご教授頂ければと思います。
また、tensorflowもこう言ったニューラルネットワーク構築すると精度上がるよなどアドバイス頂けますと
大変助かります。

どうぞよろしくお願い致します。

10/03(水)追記致しました。

用途イメージとしては、こちらの画像の赤の数をカウントしたいと考えております。
↓これならば赤4つ、赤マーキングが付いているので太さは100㎜など
イメージ説明

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

 課題1について

シールの色は決まっているので、単純が画像処理でいいと思います。

 2値化する。

import cv2
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon

img = cv2.imread('image1.jpg')  # 画像を読み込む。

# 色基準で2値化する。
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)  # HSV 色空間に変換

red = cv2.inRange(hsv, np.array([145, 70, 0]), np.array([180, 255, 255]))
yellow = cv2.inRange(hsv, np.array([10, 80, 0]), np.array([50, 255, 255]))
green = cv2.inRange(hsv, np.array([30, 190, 0]), np.array([90, 255, 255]))
blue = cv2.inRange(hsv, np.array([108, 121, 0]), np.array([120, 255, 255]))
white = cv2.inRange(hsv, np.array([108, 21, 0]), np.array([255, 70, 255]))

# 白だけゴミがあるので、収縮演算
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
white = cv2.erode(white, kernel)


bin_imgs = {'red': red, 'yellow': yellow, 'green': green,
            'blue': blue, 'white': white}

# 2値化結果を可視化する。
####################################################
fig, axes_list = plt.subplots(2, 3, figsize=(10, 6))
axes_list[1, 2].remove()
for ax, (label, bin_img) in zip(axes_list.ravel(), bin_imgs.items()):
    ax.axis('off')
    ax.set_title(label)
    ax.imshow(bin_img, cmap=plt.cm.gray)
plt.show()

イメージ説明

 輪郭抽出して、輪郭の数を数える。

fig, ax = plt.subplots(figsize=(8, 5))
ax.axis('off')
ax.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

# 輪郭検出し、数を求める。
##############################################
for label, bin_img in bin_imgs.items():
    _, contours, _ = cv2.findContours(
        bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 輪郭を構成する頂点数で誤検出を除く。
    contours = list(filter(lambda cnt: len(cnt) > 30, contours))
    count = len(contours)

    print('color: {}, conunt: {}'.format(label, count))

    # 描画する。
    for cnt in contours:
        cnt = np.squeeze(cnt, axis=1)  # (N, 1, 2) -> (N, 2)
        ax.add_patch(Polygon(cnt, fill=None, lw=2., color=label))
plt.show()

イメージ説明

color: green, conunt: 3
color: blue, conunt: 3
color: red, conunt: 4
color: white, conunt: 3
color: yellow, conunt: 3

 課題2について

2.1.の静止画でシールを貼ってある対象の太さを知りたい(画像はシールを貼ってあるものと仮定する)

配管に貼ってあるシールで大きさを決めるということでしょうか?
それとも、配管の太さは別途検出するということでしょうか。

後者の場合、撮影する距離が固定とか限定された条件がない限り、画像からは実際のスケールはわからないので無理です。

 追記

CNN で物体の検出、分類を行う場合、以下のアプローチがあります。

  • クラス分類: 与えた画像からクラスを分類する。
  • 物体検出: 与えた画像から物体の位置及びクラスを矩形で検出する。
  • Semantic Segmentation: 与えた画像から物体の位置及びクラスをピクセル単位で分類する。
  • Instance Segmentation: 与えた画像から物体の位置及びインスタンスをピクセル単位で分類する。(同じクラスの物体が複数写っている場合、それぞれ区別する。)

難易度としては後者ほど難しくなります。
また物体検出や Segmentation は、大量の画像に対して人手でアノテーションを行わないといけないので、データセット作成にかなり労力がかかります。

イメージ説明
引用元 Semantic segmentation2

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/05 11:39

    回答者様
    御返信が遅れてしまい大変申し訳御座いません。
    教師データはかなりあり8000万枚程あるので、こちらである程度覚えこみをさせる特徴点は決めており、配管の節の層やΦ、それ以外にも撮影距離にもよって静止画上の太さは変わるので0.5m~2mの撮影距離を10cmピッチで画像を精査し、それを更に静止画を縦横のグリッドで分割して、特徴点の抽出をしようかと考えておりました。
    こちらに掲載した画像はあくまでも一例でした。
    ですが私自身考えた結果
    回答者様が2.の前者で仰っていた方法の方がなんだか良い気がしてきました。
    不躾で大変申し訳御座いませんが、マーカーを付けたパイプと太さをシールの色で紐付けすると言った解釈で相違ないでしょうか。
    恐れ入りますがよろしくお願い致します。

    キャンセル

  • 2018/10/05 12:12

    シール(=マーカー?)の意味(用途)がよくわからないのは私だけ……?

    実際に配管の検出を行うべき環境において「配管には須らくシールが貼ってあることが常に期待できる(!)」という話なのか,
    それともシールを張るというのは単に開発中のテスト環境の話なのか

    キャンセル

  • 2018/10/05 14:03

    > 教師データはかなりあり8000万枚程あるので
    8000万枚はすごいですね。データ量として十分だと思います。
    ただ Deep Learning の場合、画像に対して人手でアノテーション (正解データ作成) する必要があり、画像分類ならまだしも、物体検出、Segmentation の場合はかなり労力がかかります。

    > こちらである程度覚えこみをさせる特徴点は決めており、配管の節の層やΦ、それ以外にも撮影距離にもよって静止画上の太さは変わるので0.5m~2mの撮影距離を10cmピッチで画像を精査し、それを更に静止画を縦横のグリッドで分割して、特徴点の抽出をしようかと考えておりました。

    Deep Learning の場合、特徴点は自動で抽出するものなので、上記のように特徴が定義できるのではあれば、画像処理で行うのもありだと思います。

    > 回答者様が2.の前者で仰っていた方法の方がなんだか良い気がしてきました。
    > 不躾で大変申し訳御座いませんが、マーカーを付けたパイプと太さをシールの色で紐付けすると言った解釈で相違ないでしょうか。

    はい、マーカーを検出して、そのマーカーに紐付いた「パイプと太さ」の情報を得るのが一番手軽ではないかと思います。
    マーカーは大きさや色など変えて検出しやすいようなものを選ぶとよいでしょう。

    あと、もしかしたら類似事例で先行研究がないか論文調査もしてみるといいかと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる
  • トップ
  • Pythonに関する質問
  • 静止画内のシール数を色別にその場でカウントしたい+静止画をその場で解析して対象の太さを大体知りたい