Выбор правильной верхней и нижней границ ВПГ для определения цвета с помощью `cv::inRange` (OpenCV)

У меня есть изображение кофейной банки с оранжевой крышкой, положение которой я хочу найти. Вот образ,

Утилита 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()

10 ответов

Решение

Проблема 1: Различные приложения используют разные шкалы для HSV. Например, GIMP использует H = 0-360, S = 0-100 and V = 0-100, Но OpenCV использует H: 0 - 180, S: 0 - 255, V: 0 - 255, Здесь я получил значение оттенка 22 в GIMP. Поэтому я взял половину, 11, и определил диапазон для этого. т.е. (5,50,50) - (15,255,255),

Проблема 2: А также, OpenCV использует формат BGR, а не RGB. Поэтому измените код, который преобразует RGB в HSV, следующим образом:

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

Теперь запустите это. Я получил вывод следующим образом:

Надеюсь, это то, что вы хотели. Есть несколько ложных обнаружений, но они маленькие, поэтому вы можете выбрать самый большой контур, которым является ваша крышка.

РЕДАКТИРОВАТЬ:

Как сказал в своем комментарии Карл Филипп, было бы неплохо добавить новый код. Но есть изменение только одной строки. Итак, я хотел бы добавить тот же код, реализованный в новом 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)

Это дает тот же результат, что и выше. Но код намного проще.

Ок, найди цвет в HSV Пространство это старый, но общий вопрос. я сделал hsv-colormap быстро искать специальный цвет. Вот:

введите описание изображения здесь

Ось X представляет Hue в [0,180), ось Y представляет Saturation в [0,255], ось Y2 представляет S = 255, пока держу V = 255,

Чтобы найти цвет, обычно просто ищите диапазон H а также Sи установите v в диапазоне (20, 255).

Чтобы найти оранжевый цвет, мы ищем карту и находим лучший диапазон: H :[10, 25], S: [100, 255], and V: [20, 255], Итак, маска cv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )

Затем мы используем найденный диапазон для поиска оранжевого цвета, это результат:

введите описание изображения здесь


Метод прост, но распространен в использовании:

#!/usr/bin/python3
# 2018.01.21 20:46:41 CST
import cv2

img = cv2.imread("test.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv,(10, 100, 20), (25, 255, 255) )
cv2.imshow("orange", mask);cv2.waitKey();cv2.destroyAllWindows()

Подобные ответы:

  1. Как определить пороговое значение для обнаружения только объектов зеленого цвета на изображении:Opencv

  2. Выбор правильных значений HSV для порогового значения OpenCV с InRangeS

Вот простой скрипт порогового значения цвета HSV для определения нижнего / верхнего цветовых диапазонов с помощью полос прокрутки для любого изображения на диске. Просто измените путь к изображению вcv2.imread()

ht tps:https://stackru.com/images/fd6e0780c7bbf930971ecafdda6f052e041e8ac0.png

import cv2
import numpy as np

def nothing(x):
    pass

# Load image
image = cv2.imread('1.jpg')

# Create a window
cv2.namedWindow('image')

# Create trackbars for color change
# Hue is from 0-179 for Opencv
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)
cv2.createTrackbar('SMin', 'image', 0, 255, nothing)
cv2.createTrackbar('VMin', 'image', 0, 255, nothing)
cv2.createTrackbar('HMax', 'image', 0, 179, nothing)
cv2.createTrackbar('SMax', 'image', 0, 255, nothing)
cv2.createTrackbar('VMax', 'image', 0, 255, nothing)

# Set default value for Max HSV trackbars
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)

# Initialize HSV min/max values
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0

while(1):
    # Get current positions of all trackbars
    hMin = cv2.getTrackbarPos('HMin', 'image')
    sMin = cv2.getTrackbarPos('SMin', 'image')
    vMin = cv2.getTrackbarPos('VMin', 'image')
    hMax = cv2.getTrackbarPos('HMax', 'image')
    sMax = cv2.getTrackbarPos('SMax', 'image')
    vMax = cv2.getTrackbarPos('VMax', 'image')

    # Set minimum and maximum HSV values to display
    lower = np.array([hMin, sMin, vMin])
    upper = np.array([hMax, sMax, vMax])

    # Convert to HSV format and color threshold
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    result = cv2.bitwise_and(image, image, mask=mask)

    # Print if there is a change in HSV value
    if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
        print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
        phMin = hMin
        psMin = sMin
        pvMin = vMin
        phMax = hMax
        psMax = sMax
        pvMax = vMax

    # Display result image
    cv2.imshow('image', result)
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

Я создал эту простую программу, чтобы получить коды HSV в режиме реального времени

import cv2
import numpy as np


cap = cv2.VideoCapture(0)

def nothing(x):
    pass
# Creating a window for later use
cv2.namedWindow('result')

# Starting with 100's to prevent error while masking
h,s,v = 100,100,100

# Creating track bar
cv2.createTrackbar('h', 'result',0,179,nothing)
cv2.createTrackbar('s', 'result',0,255,nothing)
cv2.createTrackbar('v', 'result',0,255,nothing)

while(1):

    _, frame = cap.read()

    #converting to HSV
    hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)

    # get info from track bar and appy to result
    h = cv2.getTrackbarPos('h','result')
    s = cv2.getTrackbarPos('s','result')
    v = cv2.getTrackbarPos('v','result')

    # Normal masking algorithm
    lower_blue = np.array([h,s,v])
    upper_blue = np.array([180,255,255])

    mask = cv2.inRange(hsv,lower_blue, upper_blue)

    result = cv2.bitwise_and(frame,frame,mask = mask)

    cv2.imshow('result',result)

    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cap.release()

cv2.destroyAllWindows()

Для этой цели я создал простой (более правильный) инструмент, используя opencv-python. Подумал, что это будет полезно для кого-то, кто наткнулся здесь, как я в начале этого года.

Поскольку сам инструмент написан с использованием python cv2, он гарантированно будет использовать тот же диапазон. Также есть ползунок для erodeи dilateтак как обычно проект компьютерного зрения нуждается в этих двух функциях

Вы можете клонировать инструмент отсюда https://github.com/hariangr/HsvRangeTool .

Диапазон OpenCV HSV: H: от 0 до 179 S: от 0 до 255 В: от 0 до 255

На цветовой гамме Gimp (или другой фотомонтажной программе) диапазон оттенков от 0 до 360, поскольку opencv помещает информацию о цвете в один байт, максимальное числовое значение в одном байте равно 255, поэтому значения оттенков openCV эквивалентны значениям оттенков от gimp, деленным на 2,

При обнаружении объекта на основе цветового пространства HSV я обнаружил, что диапазон 5 (диапазон opencv) достаточен для фильтрации определенного цвета. Я бы посоветовал вам использовать цветовой вкус HSV, чтобы определить диапазон, который лучше всего подходит для вашего применения.

Цветовое небо HSV с распознаванием цвета в пространстве HSV

Чтобы найти значение HSV для Green, попробуйте следующие команды в терминале Python

green = np.uint8([[[0,255,0 ]]])
hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
print hsv_green
[[[ 60 255 255]]]

Вы можете использовать GIMP или PaintDotNet, чтобы получить точный диапазон HSV. Но проблема в том, что диапазон HSV в графическом программном обеспечении отличается от того же диапазона в OpenCV, поэтому вам нужна функция, чтобы исправить это за вас. Для этого вы можете использовать следующую функцию.

      def fixHSVRange(h, s, v):
    # Normal H,S,V: (0-360,0-100%,0-100%)
    # OpenCV H,S,V: (0-180,0-255 ,0-255)
    return (180 * h / 360, 255 * s / 100, 255 * v / 100)

Например, вы можете использовать это примерно так:

      im=cv2.imread("image.jpg",1)
im_hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
color1 = fixHSVRange(h=10, s=20, v=0)
color2 = fixHSVRange(h=30, s=70, v=100)
mask = cv2.inRange(im_hsv, color1, color2)
cv2.imwrite("mask.jpg",mask)

Я также изо всех сил пытался найти, какие значения HSV выбрать (чтобы в конечном итоге выбрать регионы). Немного погуглив, я создал этот небольшой скрипт для проверки значений HSV на моем изображении.

Он открывает ваше изображение (отрегулируйте путь в). Когда вы щелкаете по интересующей точке изображения, оно печатает место щелчка мыши и значения HSV в этом месте изображения.

      import cv2

def on_mouse(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        print("HSV values at ({}, {}): {}".format(x, y, hsv[y, x]))

img = cv2.imread(‘\path\to\your\image\piccie.png’)
cv2.namedWindow("image")
cv2.setMouseCallback("image", on_mouse)

while True:
    cv2.imshow("image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

Большинство методов, упомянутых выше, обычно требуют некоторого знания цветового диапазона для определенного цвета с последующим методом проб и ошибок, чтобы получить правильный диапазон. Но официальная документация OpenCV предлагает лучший способ найти нижнюю и верхнюю границы HSV даже для цветов, которые не очень распространены.

Как найти значения HSV для отслеживания?

Это распространенный вопрос, который можно найти на stackoverflow.com. Это очень просто, и вы можете использовать ту же функцию cv.cvtColor(). Вместо передачи изображения вы просто передаете нужные значения BGR. Например, чтобы найти значение HSV для Green, попробуйте выполнить следующие команды в терминале Python:

Вы можете найти точные значения пикселей (BGR) требуемого объекта и использовать их, например, зеленый (0, 255, 0)

      green = np.uint8([[[0,255,0 ]]])
hsv_green = cv.cvtColor(green,cv.COLOR_BGR2HSV)
print(hsv_green)
      [[[60 255 255]]]

Теперь вы берете [H-10, 100,100] и [H+10, 255, 255] в качестве нижней и верхней границ соответственно. Помимо этого метода, вы можете использовать любые инструменты редактирования изображений, такие как GIMP или любые онлайн-конвертеры, чтобы найти эти значения, но не забудьте настроить диапазоны HSV.

Источник:
Цветовые пространства OpenCV и отслеживание объектов
GIMP — инструмент для управления изображениями

Другие вопросы по тегам