Выбор правильной верхней и нижней границ HSV для определения цвета с помощью ' 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()
Переведено автоматически
Ответ 1
Проблема 1 : Разные приложения используют разные масштабы для HSV. Например, gimp использует H = 0-360, S = 0-100 and V = 0-100
. Но OpenCV использует H: 0-179, 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)
Это дает тот же результат, что и выше. Но код намного проще.
Ответ 2
Хорошо, поиск цвета в HSV
пространстве - старый, но распространенный вопрос. Я создал hsv-colormap
для быстрого поиска специальный цвет. Вот он:
Ось x представляет Hue
в [0,180), ось y1 представляет 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()
Похожие ответы:
Ответ 3
Вот простой скрипт определения порогового значения цвета HSV для определения нижнего / верхнего диапазонов цветов с помощью трекбаров для любого изображения на диске. Просто измените путь к изображению в cv2.imread()
. Пример выделения оранжевого:
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
(hMin = 0 , sMin = 164, vMin = 0), (hMax = 179 , sMax = 255, vMax = 255)
После того, как вы определили свой lower
и upper
цветовые диапазоны HSV, вы можете сегментировать желаемые цвета следующим образом:
import numpy as np
import cv2
image = cv2.imread('1.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 164, 0])
upper = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, mask=mask)
cv2.imshow('result', result)
cv2.waitKey()
Ответ 4
Я создал эту простую программу для получения кодов 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()