python: OpenCVで画像をHSV形式で取り込み物体の検出を行う

今回取り出す画像 プログラミング
スポンサーリンク




こんにちは、おみです。

今回は、画像認識でよく使う色空間である「HSV色空間」で画像を取り込み、画像から物体の検出を行ってみたいと思います。

スポンサーリンク

HSV形式とは

色を表現する方法の1つ。色を

  • 色相(Hue) … どんな色か(赤、青等)
  • 彩度(Saturation) … 色がはっきりしているか(はっきりしていないほど白に近づく
  • 明度(Value) … 色がどのくらい明るいか(くらいほど黒に近づく)

の3つの要素で表す。

 

BGR形式では色を青(Blue)、緑(Green)、赤(Red)で表すため色を表現するのに3つの要素が必要になるが、HSV形式では色そのものを表現するのは色相のみである。そのため、色を表現するのが簡単であり、画像処理でよく用いられる。

OpenCVでHSV形式に変換する方法

OpenCVで画像をHSV形式に変換するのは簡単です。

# 画像をHSV形式に変換
# img ... cv2.imreadで読み込んだ画像
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

画像から物体を検出する

↓この画像から、鳥のみを抽出します。

画像の特徴

  • 鳥は、白と青で書かれている
  • 鳥以外の部分は、緑と黄で書かれている

 

以上の特徴より、

  「画像のうち、色相が緑と黄の部分以外を抽出する」

ことができれば、鳥を検出できると考えられます。

 

検出の手順

以下の手順で鳥の抽出を行います。

  1. 画像を読み込み、HSV形式に変換する
  2. 画像を2値化する
  3. 検出を行う

 

手順1 画像を読み込み、HSV形式に変換する

画像を読み込み、HSV形式に変換します。

# 画像のパスを指定
file_path = "bird.png"

# 画像を読み込む
img = cv2.imread(file_path)

# HSV形式に変換
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

↓HSV形式に変換した画像

手順2 画像を2値化する

画像の2値化を行います。

今回は、緑と黄を白、それ以外を黒として扱います。

# 消去する色をHSV形式で指定
l_green = (0, 0, 0)
h_green = (90, 255, 255)

# 2値化を行う
nichi = cv2.inRange(hsv, l_green, h_green)
nichi = cv2.bitwise_not(nichi)

手順3 検出を行う

画像中の鳥の輪郭に、線を引きます。

# 輪郭のみを検出する
cons = cv2.findContours(nichi,
cv2.RETR_LIST,
cv2.CHAIN_APPROX_NONE)[0]

# 輪郭を描画する
for con in cons:
# 面積が閾値を超えない場合、輪郭としない
if cv2.contourArea(con) < 2000:
continue

# 描画処理
cv2.polylines(img, con, True, (255, 0, 0), 5)

↓鳥の輪郭に線を引いた画像

一部不要な部分も鳥とみなされていますが、ほぼ正確に抽出することができました。

ソースコード

ここまでの一連の処理を、一つのプログラムにまとめたものがこちらです。

import cv2
import math
import os
import numpy as np

# 画像のパスを指定
file_path = "bird.png"

# 画像が存在するかを確認
if not os.path.exists(file_path):
print("画像が存在しません。")

# 画像を読み込む
img = cv2.imread(file_path)

# 画像のサイズを変更
height, width = img.shape[:2]
img = cv2.resize(img, (math.floor(width / 2), math.floor(height / 2)))

# HSV形式に変換
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 消去する色をHSV形式で指定
l_green = (0, 0, 0)
h_green = (90, 255, 255)

# 2値化を行う
nichi = cv2.inRange(hsv, l_green, h_green)
nichi = cv2.bitwise_not(nichi)

# 輪郭のみを検出する
cons = cv2.findContours(nichi,
cv2.RETR_LIST,
cv2.CHAIN_APPROX_NONE)[0]

# 輪郭を描画する
for con in cons:
# 面積が閾値を超えない場合、輪郭としない
if cv2.contourArea(con) < 2000:
continue

# 描画処理
cv2.polylines(img, con, True, (255, 0, 0), 5)

cv2.imshow("result", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

参考文献

https://ja.wikipedia.org/wiki/HSV色空間

https://tzmi.hatenablog.com/entry/2020/01/07/230036
https://www.pynote.info/entry/opencv-inrange

 

コメント

  1. […] 【画像認識初心者必見!】OpenCVで画像をHSV形式で取り込み、物体の検出を行… […]

タイトルとURLをコピーしました