RGB颜色范围到HSV颜色范围

时间:2020-02-27 14:28:14

标签: python opencv rgb mask hsv

我想检测视频中的一些颜色标记。 Example Frame。 为此,我让用户在“第一帧”中选择色点并获取rgb值。

# User input for each point
flag, frame = capture.read()
frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
x1, y1, r1, g1, b1 = SupportMainClasses.Pixelcollector(frame).getXY()
x2, y2, r2, g2, b2 = SupportMainClasses.Pixelcollector(frame).getXY()
x3, y3, r3, g3, b3 = SupportMainClasses.Pixelcollector(frame).getXY()

P1是环悬挂的静态点,P2和P3是我要检测的颜色标记。然后,我从rgb切换到grb并应用一个范围。

#define Color Range in GRB
colorRange = 30
picked_p2 = (b2, g2, r2)
upper_p2 = (b2 + colorRange if b2 + colorRange < 255 else 255, g2 + colorRange if g2 + colorRange < 255 else 255, r2 + colorRange if r2 + colorRange < 255 else 255)
lower_p2 = (b2 - colorRange if b2 - colorRange > 0 else 0, g2 - colorRange if g2 - colorRange > 0 else 0, r2 - colorRange if r2 - colorRange > 0 else 0)
picked_p3 = (b3, g3, r3)
upper_p3 = (b3 + colorRange if b3 + colorRange < 255 else 255, g3 + colorRange if g3 + colorRange < 255 else 255, r3 + colorRange if r3 + colorRange < 255 else 255)
lower_p3 = (b3 - colorRange if b3 - colorRange > 0 else 0, g3 - colorRange if g3 - colorRange > 0 else 0, r3 - colorRange if r3 - colorRange > 0 else 0)

到目前为止一切都很好,直到这里它按预期工作。 Display of picked color and Range

但是在我尝试将grb范围转换为hsv范围并构建该特定范围的Mask

之后,
#Color Masks
p2Mask = cv.inRange(cv.cvtColor(frame, cv.COLOR_BGR2HSV), cv.cvtColor(np.uint8([[list(lower_p2)]]), cv.COLOR_BGR2HSV), cv.cvtColor(np.uint8([[list(upper_p2)]]), cv.COLOR_BGR2HSV))
p3Mask = cv.inRange(cv.cvtColor(frame, cv.COLOR_BGR2HSV), cv.cvtColor(np.uint8([[list(lower_p3)]]), cv.COLOR_BGR2HSV), cv.cvtColor(np.uint8([[list(upper_p3)]]), cv.COLOR_BGR2HSV))

它不会检测到我的颜色,并尝试打印值

print(lower_p2)
print(upper_p2)

print(cv.cvtColor(np.uint8([[list(lower_p2)]]), cv.COLOR_BGR2HSV))
print(cv.cvtColor(np.uint8([[list(upper_p2)]]), cv.COLOR_BGR2HSV))

返回:

lowerP2GRB:         (126, 149, 110)
upperP2GRB:         (186, 209, 170)
lowerP2HSV:         [[[ 72  67 149]]]
upperP2HSV:         [[[ 72  48 209]]]

在较早的版本中,我首先转换为hsv,并使hsv女巫中的范围工作正常。有趣的是,上,下色调是72。对我而言,这意味着rgb体积已转换为hsv中的一个区域。 Conversion

但是我需要hsv中的Volume来构建掩码(?)。 Conversion

我该如何实现?

1 个答案:

答案 0 :(得分:0)

整个代码:

import logging as log
import argparse as arg
import cv2 as cv
import math as math
import os as os
import numpy as np
from PIL import Image
from PIL import ImageFilter

import SupportMainFunctions
import SupportMainClasses

'-------------------------------------------------------------------------------------'
'setup logger'
log.basicConfig(level=log.DEBUG, filename='temp/log.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')

'-------------------------------------------------------------------------------------'
'setup csv to log detected point data'

try:
    os.remove('temp/pointData.csv')
    csvWriter = open('temp/pointData.csv', 'a', newline='')
except:
    print("Error while deleting file ", 'temp/pointData.csv')

csvWriter = open('temp/pointData.csv', 'a', newline='')


'-------------------------------------------------------------------------------------'
'setup arguments'
parser = arg.ArgumentParser()
parser.add_argument('--inputPath', help="path to input Video" ,default='resources/test_video2.MOV')

args = parser.parse_args()

log.info("Video Path : '{}'" .format(args.inputPath))

'-------------------------------------------------------------------------------------'
'Video Capture Init'
capture = cv.VideoCapture(args.inputPath)

'Background substraction init'
backSub = cv.createBackgroundSubtractorKNN()

'Get Video Properties'
frame_count = capture.get(cv.CAP_PROP_FRAME_COUNT)
frame_width = capture.get(cv.CAP_PROP_FRAME_WIDTH)
frame_height = capture.get(cv.CAP_PROP_FRAME_HEIGHT)
fps = capture.get(cv.CAP_PROP_FPS)
video_codec = capture.get(cv.CAP_PROP_FOURCC)
video_name = args.inputPath.split(".")[0].split("/")[1]

'Log Properties'
log.info("Total Number of Frames : '{}'" .format(frame_count))
log.info("Frame width : '{}'" .format(frame_width))
log.info("Frame height : '{}'" .format(frame_height))
log.info("FPS : '{}'" .format(fps))
log.info("Video Codec : '{}'" .format(SupportMainFunctions.decode_fourcc(video_codec)))
log.info("Video Name : '{}'" .format(video_name))

'-------------------------------------------------------------------------------------'
'Video Writer Init'
fourcc = cv.VideoWriter_fourcc(*'avc1')
writer = cv.VideoWriter('temp/output.MOV', fourcc, int(fps), (int(frame_width), int(frame_height)), True)

# User input for each point
flag, frame = capture.read()
frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
x1, y1, r1, g1, b1 = SupportMainClasses.Pixelcollector(frame).getXY()
x2, y2, r2, g2, b2 = SupportMainClasses.Pixelcollector(frame).getXY()
x3, y3, r3, g3, b3 = SupportMainClasses.Pixelcollector(frame).getXY()


#define Color Range in GRB
colorRange = 30
picked_p2 = (b2, g2, r2)
upper_p2 = (b2 + colorRange if b2 + colorRange < 255 else 255, g2 + colorRange if g2 + colorRange < 255 else 255, r2 + colorRange if r2 + colorRange < 255 else 255)
lower_p2 = (b2 - colorRange if b2 - colorRange > 0 else 0, g2 - colorRange if g2 - colorRange > 0 else 0, r2 - colorRange if r2 - colorRange > 0 else 0)
picked_p3 = (b3, g3, r3)
upper_p3 = (b3 + colorRange if b3 + colorRange < 255 else 255, g3 + colorRange if g3 + colorRange < 255 else 255, r3 + colorRange if r3 + colorRange < 255 else 255)
lower_p3 = (b3 - colorRange if b3 - colorRange > 0 else 0, g3 - colorRange if g3 - colorRange > 0 else 0, r3 - colorRange if r3 - colorRange > 0 else 0)

#define window size
cv.namedWindow('video', cv.WINDOW_NORMAL)
cv.resizeWindow('video', 960, 540)

'Work'
while capture.isOpened():
    flag, frame = capture.read()
    if flag is True:

        #Foreground Mask
        fgMask = backSub.apply(frame)

        print(lower_p3)
        print(upper_p3)

        print(cv.cvtColor(np.uint8([[list(lower_p3)]]), cv.COLOR_BGR2HSV))
        print(cv.cvtColor(np.uint8([[list(upper_p3)]]), cv.COLOR_BGR2HSV))

        #Color Masks
        p2Mask = cv.inRange(cv.cvtColor(frame, cv.COLOR_BGR2HSV), cv.cvtColor(np.uint8([[list(lower_p2)]]), cv.COLOR_BGR2HSV), cv.cvtColor(np.uint8([[list(upper_p2)]]), cv.COLOR_BGR2HSV))
        p3Mask = cv.inRange(cv.cvtColor(frame, cv.COLOR_BGR2HSV), cv.cvtColor(np.uint8([[list(lower_p3)]]), cv.COLOR_BGR2HSV), cv.cvtColor(np.uint8([[list(upper_p3)]]), cv.COLOR_BGR2HSV))

        #Final Mask
        p2Maske = cv.bitwise_and(p2Mask, fgMask, mask=None)
        p3Maske = cv.bitwise_and(p3Mask, fgMask, mask=None)

        # Apply HoughCircle transform on the blurred image.
        detected_circles_p2 = cv.HoughCircles(cv.blur(p2Maske, (3, 3)), cv.HOUGH_GRADIENT, 1, 20, param1=20, param2=10, minRadius=5, maxRadius=20)
        detected_circles_p3 = cv.HoughCircles(cv.blur(p3Maske, (3, 3)), cv.HOUGH_GRADIENT, 1, 20, param1=20, param2=10, minRadius=5, maxRadius=30)

        # calculate Point positions
        if detected_circles_p2 is not None and detected_circles_p3 is not None:

            # range between picked points
            lenghtP12 = round(math.hypot(x2 - x1, y2 - y1))
            lenghtP23 = round(math.hypot(x3 - x2, y3 - y2))

            # Calculate P2 by range of users inputrange and P1
            calclenghtP12 = []
            for pointP2 in detected_circles_p2[0]:
                calclenghtP12.append(round(math.hypot(pointP2[0] - x1, pointP2[1] - y1)))
            calcP2 = detected_circles_p2[0][SupportMainFunctions.find_nearest(calclenghtP12, lenghtP12)]

            # Calculate P3 by range of users Inputrange and P2
            calclenghtP23 = []
            for pointP3 in detected_circles_p3[0]:
                calclenghtP23.append(round(math.hypot(pointP3[0] - calcP2[0], pointP3[1] - calcP2[1])))
            calcP3 = detected_circles_p3[0][SupportMainFunctions.find_nearest(calclenghtP23, lenghtP23)]

            # Draw P1 by user input
            cv.circle(frame, (x1, y1), 1, (0, 0, 255), 3)

            # Draw the circumference of the circle.
            cv.circle(frame, (calcP2[0], calcP2[1]), calcP2[2], (0, 255, 0), 2)
            cv.circle(frame, (calcP3[0], calcP3[1]), calcP3[2], (0, 255, 0), 2)

            # Draw a small circle (of radius 1) to show the center.
            cv.circle(frame, (calcP2[0], calcP2[1]), 1, (0, 0, 255), 3)
            cv.circle(frame, (calcP3[0], calcP3[1]), 1, (0, 0, 255), 3)

            #Write Point Data to csv
            csvWriter.write(str(x1) + ", " + str(x2) + ", " + str(calcP2[0]) + ", " + str(calcP2[1]) + ", " + str(calcP3[0]) + ", " + str(calcP3[1]) + "\n")
        else:
            log.info("Missing Circle in frame Nr : '{}'".format(capture.get(cv.CAP_PROP_POS_FRAMES)))

        #show current frame with frame nr
        cv.rectangle(frame, (0, 0), (100, 25), (255, 255, 255), -1)
        cv.putText(frame,"Frame: " + str(capture.get(cv.CAP_PROP_POS_FRAMES)), (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))



        #draw rectangle to range identification
        cv.rectangle(frame, (0, 25), (25, 50), (255, 255, 255), -1)
        cv.putText(frame, str("P2"), (0, 40), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))
        cv.rectangle(frame, (25, 25), (50, 50), lower_p2, -1)
        cv.rectangle(frame, (50, 25), (75, 50), picked_p2, -1)
        cv.rectangle(frame, (75, 25), (100, 50), upper_p2, -1)

        cv.rectangle(frame, (0, 50), (25, 75), (255, 255, 255), -1)
        cv.putText(frame, str("P3"), (0, 70), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))
        cv.rectangle(frame, (25, 50), (50, 75), lower_p3, -1)
        cv.rectangle(frame, (50, 50), (75, 75), picked_p3, -1)
        cv.rectangle(frame, (75, 50), (100, 75), upper_p3, -1)

        cv.imshow('video', p2Mask)

        #quit hook
        if cv.waitKey(1) & 0xFF == ord('q'):
            break

        #write Frame to video
        writer.write(frame)

    else:
        break

'Release everything'
capture.release()
writer.release()
csvWriter.close()
cv.destroyAllWindows()