GUI Features in OpenCV & Mouse Events / Creating a GUI for Extracting HSV Color Space Values

siromer
5 min readApr 13, 2024

--

When you start using OpenCV, you might want to interact with images and videos. By ‘interact’, you might want to draw shapes, take coordinates with your mouse, or pause a video and draw rectangles around the specific objects to extract meaningful data from these areas. For these purposes, OpenCV provides very useful functions. You don’t need to use different libraries for Gui features like Tkinter.

In this article, I am going to create 2 different HSV color extractor App(Gui) with OpenCV Gui features. I am going to use Python as a programming language.

Extracting HSV values from Image
Hue , Saturation and Value for Blue

You may ask yourself , what am I going to do with HSV values? Why they are important?

I always use HSV color space for object tracking. I have written a few articles about how to create an object tracker with the help of the HSV color space. If you want to see examples of object tracking with the HSV color space, you can click on the following links (HSV Object Tracker 1 , HSV Object Tracker 2)

HSV is particularly useful for color-based segmentation tasks. With HSV, you can define color ranges more intuitively compared to RGB. You can detect and track objects with HSV color space.

HSV Color Space is often used in image processing and computer vision tasks.

HSV color Space

HSV COLOR SPACE

HSV color space may seem a little weird at first glance. It is not like RGB. As you can see from the image in above, it has 3 parameters.

  • Hue (H): Hue describes the “type” of color, such as red, green, blue, etc.
  • Saturation (S): Saturation represents the intensity of color.
  • Value (V): Value represents the brightness of color.

Look at the image again, did you notice something? You can not obtain all the colors from HSV color space; it does not represent all possible colors that can be perceived by humans.

I am going to create 2 different GUI :

  1. Application(Gui) for finding HSV values for different colors
  2. Application(Gui) for extracting HSV values for specific objects

1. Finding HSV values for Different Colors

As I mentioned before, I commonly use the HSV color space for object tracking applications. To track objects based on their color features, you need to set lower and upper bounds for each parameter(Hue, Saturation, and Value in this case). Sometimes, it is hard to find these boundaries on the internet. Therefore creating a GUI for finding bounds for different colors can be very helpful.

import numpy as np
import cv2

def nothing(x):
pass

# Create a black image with padding, a window
padding = 50 # adjust as needed
img = np.zeros((300 + 2*padding, 512 + 2*padding, 3), np.uint8)
img[:] = (255, 255, 255) # Set padding color to white
cv2.namedWindow('image')

# create trackbars for HSV color change
cv2.createTrackbar('H', 'image', 0, 179, nothing) # Hue is in the range 0-179
cv2.createTrackbar('S', 'image', 0, 255, nothing)
cv2.createTrackbar('V', 'image', 0, 255, nothing)

# Resize the window
cv2.resizeWindow('image', 500, 500)

while True:
# get current positions of HSV trackbars
h = cv2.getTrackbarPos('H', 'image')
s = cv2.getTrackbarPos('S', 'image')
v = cv2.getTrackbarPos('V', 'image')

# Set pixel color in HSV space
hsv_color = np.uint8([[[h, s, v]]])
bgr_color = cv2.cvtColor(hsv_color, cv2.COLOR_HSV2BGR)

# Fill the image with the specified BGR color within the padding
img[padding:-padding, padding:-padding] = bgr_color[0][0]

cv2.imshow('image', img)

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

cv2.destroyAllWindows()

Imagine you want to track a blue plane, you would need to find lower and upper bounds for tracking. You can find lower and upper boundaries by adjusting 3 parameters (Hue, Saturation, and Value) in the HSV color space.

Ex: This values can be your lower bound for blue

2. Extracting HSV Values for specific objects

The first GUI works well, but if you want to know the exact values for specific objects, this one may be more helpful. In this GUI, the user draws a rectangle around the specific object, and from that area, HSV values are extracted. With this GUI, before creating an object tracker, you can find more precise HSV values for an object that you want to track.

import cv2
import numpy as np
import matplotlib.pyplot as plt

"""
After running code, press the right button to draw rectangle , you need to
Press 2 time to the right button.
After that, press the right button and you will see HSV values on screen:
- Hue , - Saturation , - Value
"""


frame=cv2.imread("resources/yellow.jpg")

# coordinates for rectangles, random initial values
x_min=1900
y_min=1900
x_max=0
y_max=0

# left mouse button
pressed=False

def drawing_function(event,x,y,flags,param):
global x_min , y_min, x_max , y_max,frame,h_text,s_text,v_text,pressed

if event==cv2.EVENT_LBUTTONDOWN:

pressed=True

# convert the frame to HSV color space
hsv_frame=cv2.cvtColor(frame[y_min+5:y_max,x_min+5:x_max],cv2.COLOR_BGR2HSV)

# take avg of hue values
h=hsv_frame[:,:,0].mean()
# take avg of saturation values
s=hsv_frame[:,:,1].mean()
# take avg of "value" values
v=hsv_frame[:,:,2].mean()

h_text=f"Hue Value : {int(h)}"
s_text=f"Saturation Value : {int(s)}"
v_text=f"Value(Brightness) Value : {int(v)}"


if event==cv2.EVENT_RBUTTONDOWN:
# Find min and max coordinates for rectangles
x_min=min(x,x_min)
y_min=min(y,y_min)
x_max=max(x,x_max)
y_max=max(y,y_max)

# Create window and mouse events
cv2.namedWindow('frame')
cv2.setMouseCallback('frame',drawing_function)

while True:
# If coordinates of rectangles not choice, just display the image
if not pressed:
frame=cv2.resize(frame,(600, 400))

# If the user chooses coordinates, and displays rectangle, default y_max is equal to 0, therefore when it changes it means user choiced some coordinates .
if y_max!=0:
cv2.rectangle(frame,(x_min,y_min),(x_max,y_max),(0,255,255),2)

# If the user pressed the left mouse click, display HSV values on screen as texts. These values are found when pressed to left mouse button
else:
frame = cv2.putText(frame, h_text, (10,30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,255), 1, cv2.LINE_AA)
frame = cv2.putText(frame, s_text, (10,60), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,255), 1, cv2.LINE_AA)
frame = cv2.putText(frame, v_text, (10,90), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,255), 1, cv2.LINE_AA)

# display frame
cv2.imshow("frame",frame)

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

cv2.destroyAllWindows()

plt.imshow(cv2.cvtColor(frame,cv2.COLOR_BGR2RGB))
  • The HSV values obtained from two different GUIs match perfectly.
Result of Gui 2 | image link
Result of Gui 1

--

--