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

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

新規登録して質問してみよう
ただいま回答率
85.35%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

4142閲覧

OpenCVである特定の色以外を抽出する方法

aya0514

総合スコア9

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/08/03 14:04

前提・実現したいこと

プログラミング初心者です。
現在、画像のからある範囲の色以外の部分を抽出するということをやろうとしているのですが、どのようにすればいいかがわかりません。
PythonでOpenCVを使用する予定です。
具体的に言うと、hsvの(0,0,0)から(0,0,255)の範囲以外を抽出したいです(画像の白黒部分を切り取り、色のついている部分のみを残したい)。
(下の画像のようにしたいです。)
いろいろ検索、検証しましたが、わかりませんでした。
もし、詳しい方がいれば教えてくださるとありがたいです。

イメージ説明

   ↓

イメージ説明

試したこと

いろいろ検索しましたが、ある範囲の色を抽出すると言うプログラムが多く、ある範囲以外の色を抽出すると言うのはありませんでした。
特定の範囲の色を判定してその座標を出すプログラムと特定の色を抽出するプログラムは作成したので、もしここから改良して作成できるようなら、そのようにしてくださるとありがたいです。

該当のソースコード

python

1#特定の範囲の色を判定してその範囲を求めて重心の座標を出すプログラム 2import cv2 3import numpy as np 4from time import sleep 5 6# 0 <= h <= 179 (色相) OpenCVではmax=179なのでR:0(180),G:60,B:120となる 7# 0 <= s <= 255 (彩度) 黒や白の値が抽出されるときはこの閾値を大きくする 8# 0 <= v <= 255 (明度) これが大きいと明るく,小さいと暗い 9# ここでは青色を抽出するので120±20を閾値とした 10LOW_COLOR = np.array([0, 0, 0]) 11HIGH_COLOR = np.array([0, 0, 255]) 12 13# 抽出する色の塊のしきい値 14AREA_RATIO_THRESHOLD = 0.005 15frame = cv2.imread("sample.jpg") 16 17# 高さ,幅,チャンネル数 18h,w,c = frame.shape 19 20# hsv色空間に変換 21hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV) 22 23# 色を抽出する 24img = cv2.inRange(hsv,LOW_COLOR,HIGH_COLOR) 25 26# 輪郭抽出 27contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 28 29# 面積を計算 30areas = np.array(list(map(cv2.contourArea,contours))) 31 32if len(areas) == 0 or np.max(areas) / (h*w) < AREA_RATIO_THRESHOLD: 33 # 見つからなかったらNoneを返す 34 print("the area is too small") 35else: 36 # 面積が最大の塊の重心を計算し返す 37 max_idx = np.argmax(areas) 38 max_area = areas[max_idx] 39 result = cv2.moments(contours[max_idx]) 40 x = int(result["m10"]/result["m00"]) 41 y = int(result["m01"]/result["m00"]) 42 43print(x) 44print(y) 45 46cv2.circle(frame,(x,y),10,(0,0,255),-1) 47 48# 画面に表示する 49cv2.imshow('frame', frame) 50sleep(1) 51 52while True: 53 # キー入力を1ms待って、keyが「q」だったらbreak 54 key = cv2.waitKey(1)&0xff 55 if key == ord('q'): 56 break 57 58cv2.destroyAllWindows() 59

python

1#ある範囲の色を抽出するプログラム 2#!/usr/bin/python 3import numpy as np 4import cv2 5from time import sleep 6 7# image info 8image_file = 'Sample.jpg' 9img = cv2.imread(image_file) 10 11# detect pink 12hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 13lower = np.array([0, 0, 0]) 14upper = np.array([0, 0, 255]) 15img_mask = cv2.inRange(hsv, lower, upper) 16img_color = cv2.bitwise_and(img, img, mask=img_mask) 17 18# debug 19cv2.imshow('HSV_test1', img_color) 20sleep(1) 21 22while True: 23 # キー入力を1ms待って、keyが「q」だったらbreak 24 key = cv2.waitKey(1)&0xff 25 if key == ord('q'): 26 break 27 28cv2.destroyAllWindows() 29

###利用環境
エディタ Atom

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

以下でできます。

  1. cv2.imread() で読み込み
  2. HSV 色空間に変換
  3. Hue の値をヒントに cv2.inRange() で2値化してマーカー部分を抽出
  4. cv2.findContour() で輪郭抽出
  5. 大きい輪郭だけ取り出す
  6. 輪郭に対して、cv2.boundingRect() で長方形フィッティング
  7. 長方形の範囲で画像を切り抜く
  8. cv2.imwrite() で保存

python

1import cv2 2import numpy as np 3 4# 画像を読み込む。 5img = cv2.imread("sample.png") 6 7# BGR -> HSV 8hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 9 10# 2値化 11bin_img = cv2.inRange(hsv, (5, 0, 0), (20, 255, 255)) 12 13# 輪郭抽出 14contours, hierarchy = cv2.findContours( 15 bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE 16) 17 18# 小さい輪郭は誤検出として無視 19contours = list(filter(lambda x: cv2.contourArea(x) > 100, contours)) 20 21print(f"{len(contours)} marker found!") 22 23for i, cnt in enumerate(contours): 24 # 長方形フィッティング 25 x, y, w, h = cv2.boundingRect(cnt) 26 27 # 切り抜き 28 crop_img = img[y : y + h, x : x + w] 29 30 # 保存 31 cv2.imwrite(f"crop_{i:02}.png", crop_img)

イメージ説明

イメージ説明

投稿2020/08/03 14:23

編集2020/08/03 14:29
tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aya0514

2020/08/03 14:36

夜分遅くにも関わらず、ありがとうございます! 無事画像を抽出することができました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問