1. ホーム
  2. python

[解決済み] cv::inRange` を用いた色検出において,HSV の上下の境界を正しく選択する方法 (OpenCV)

2022-12-21 18:45:13

質問

オレンジ色の蓋をしたコーヒー缶の画像を探したい。 以下はそれである .

gcolor2ユーティリティは、ふたの中心でのHSVを(22, 59, 100)と表示します。 問題は、そのときに色の限界をどのように選択するかです。min = (18, 40, 90) と max = (27, 255, 255) を試しましたが、予期しない結果になってしまいました。

以下はPythonのコードです。

import cv

in_image = 'kaffee.png'
out_image = 'kaffee_out.png'
out_image_thr = 'kaffee_thr.png'

ORANGE_MIN = cv.Scalar(18, 40, 90)
ORANGE_MAX = cv.Scalar(27, 255, 255)
COLOR_MIN = ORANGE_MIN
COLOR_MAX = ORANGE_MAX

def test1():
    frame = cv.LoadImage(in_image)
    frameHSV = cv.CreateImage(cv.GetSize(frame), 8, 3)
    cv.CvtColor(frame, frameHSV, cv.CV_RGB2HSV)
    frame_threshed = cv.CreateImage(cv.GetSize(frameHSV), 8, 1)
    cv.InRangeS(frameHSV, COLOR_MIN, COLOR_MAX, frame_threshed)
    cv.SaveImage(out_image_thr, frame_threshed)

if __name__ == '__main__':
    test1()

どのように解決するのですか?

問題1. アプリケーションによって、HSVのスケールは異なります。例えば gimp では H = 0-360, S = 0-100 and V = 0-100 . しかし,OpenCV は H: 0-179, S: 0-255, V: 0-255 . ここでは、GIMPで22の色相値を得ました。そこで,その半分の11を取り出し,それに対して範囲を定義しました. (5,50,50) - (15,255,255) .

問題2. また、OpenCVはRGBではなくBGR形式を使用しています。そこで、RGBをHSVに変換するコードを以下のように変更します。

cv.CvtColor(frame, frameHSV, cv.CV_BGR2HSV)

では、実行してみましょう。以下のように出力されました。

ご希望に添えたでしょうか?誤検出はありますが、小さいので、一番大きい輪郭を選べばいいと思います。

編集中です。

として カール・フィリップ がコメントで述べているように、新しいコードを追加するのは良いことでしょう。しかし、たった1行の変更です。そこで、私は同じコードを新しい cv2 モジュールに実装されたものと同じコードを追加して、ユーザーが新しい cv2 モジュールの使いやすさと柔軟性を比較することができます。

import cv2
import numpy as np

img = cv2.imread('sof.jpg')

ORANGE_MIN = np.array([5, 50, 50],np.uint8)
ORANGE_MAX = np.array([15, 255, 255],np.uint8)

hsv_img = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

frame_threshed = cv2.inRange(hsv_img, ORANGE_MIN, ORANGE_MAX)
cv2.imwrite('output2.jpg', frame_threshed)

上記と同じ結果になります。しかし、コードはよりシンプルになります。