Reputation: 864
In my project, user should select a color for some process. There are some applications on the internet. They create three trackbars for RGB values of color but I don't want to do it like that. I want to create a trackbar below or something similar.
How can I create a trackbar like that? and
How can I get RGB values the color which marker on?
Upvotes: 2
Views: 3504
Reputation: 2433
I generate image, then I use setMouseCallback
to get mouse click position and draw a slider manually. Sorry, I cannot provide a C++ code snippet.
Just for reference here's source code in Python. See on_mouse_event
method:
import cv2
import numpy as np
class SliderHSV:
SLIDER_H = 16 # px
sliding = False
def __init__(self, window_name):
self.window_name = window_name
self.pt = 0, 0
h_comp = np.uint8([np.linspace([0, 255, 255], [179, 255, 255], 180)])
h_comp = np.broadcast_to(h_comp, (self.SLIDER_H, 180, 3))
self.h_comp = cv2.cvtColor(h_comp, cv2.COLOR_HSV2BGR)
self.tpl_hsv = np.uint8( # This is very very slow!
[(0, i, j) for i in np.linspace(0, 255, 256) for j in np.linspace(0, 255, 256)]
).reshape(256, 256, 3)
self.set_value(0)
cv2.setMouseCallback(window_name, self.on_mouse_event, param=self.window_name)
cv2.setMouseCallback("Sat-Bri", self.on_mouse_event)
def on_mouse_event(self, event, x, y, flags, param):
# https://docs.opencv.org/4.x/db/d5b/tutorial_py_mouse_handling.html
if event == cv2.EVENT_LBUTTONDOWN:
self.sliding = True
if param == self.window_name:
self.set_value(x)
else:
self.pt = x, y
elif event == cv2.EVENT_MOUSEMOVE:
if self.sliding:
if param == self.window_name:
self.set_value(x)
else:
self.set_rect(self.pt, (x, y))
elif event == cv2.EVENT_LBUTTONUP:
self.sliding = False
def set_rect(self, pt1, pt2):
pt1 = max(min(pt1[0], 255), 0), max(min(pt1[1], 255), 0)
pt2 = max(min(pt2[0], 255), 0), max(min(pt2[1], 255), 0)
sv = self.sv.copy()
cv2.rectangle(sv, pt1, pt2, (255, 255, 255))
sh_y1 = (24, 12) if pt2[1] > pt1[1] else (-12, 0)
sh_y2 = (0, -12) if pt2[1] > pt1[1] else (24, 12)
cv2.putText(sv, f"Sat.{pt1[1]}", (pt1[0], pt1[1] + sh_y1[1]), cv2.FONT_HERSHEY_PLAIN, 0.75, 0, lineType=cv2.LINE_AA)
cv2.putText(sv, f"Br.{pt1[0]}", (pt1[0], pt1[1] + sh_y1[0]), cv2.FONT_HERSHEY_PLAIN, 0.75, 0, lineType=cv2.LINE_AA)
cv2.putText(sv, f"Sat.{pt2[1]}", (pt2[0] - 45, pt2[1] + sh_y2[1]), cv2.FONT_HERSHEY_PLAIN, 0.75, 0, lineType=cv2.LINE_AA)
cv2.putText(sv, f"Br.{pt2[0]}", (pt2[0] - 45, pt2[1] + sh_y2[0]), cv2.FONT_HERSHEY_PLAIN, 0.75, 0, lineType=cv2.LINE_AA)
cv2.imshow("Sat-Bri", sv)
def set_value(self, hue):
hue = min(hue, 179)
hue = max(hue, 0)
h_comp = self.h_comp.copy()
cv2.line(h_comp, (hue, 0), (hue, self.SLIDER_H), (255, 255, 255), 2)
cv2.putText(h_comp, f"Hue {hue}", (0, self.SLIDER_H), cv2.FONT_HERSHEY_PLAIN, 1, 0, lineType=cv2.LINE_AA)
self.sv = self.create_sat_br_rect(hue)
cv2.imshow(self.window_name, h_comp)
cv2.imshow("Sat-Bri", self.sv)
def create_sat_br_rect(self, hue):
self.tpl_hsv[:, :, 0] = hue
return cv2.cvtColor(self.tpl_hsv, cv2.COLOR_HSV2BGR)
SliderHSV("HSV slider")
while(1):
if cv2.waitKey(100) & 0xFF == 27:
break
Upvotes: 1
Reputation: 41775
OpenCV GUI capabilities are not that rich. You may want to use Qt or similar to create a nice GUI, and still do your image processing in OpenCV.
Regarding the trackbar on OpenCV, you may probably want to use the HSV (Hue, Saturation, Value) color space instead of RGB. Fixing S=255
and V=255
, you can select the color by changing the H
in the range [0, 180]
. Note that in OpenCV for CV_8UC3
images, the ranges of HSV are:
H in [0, 180]
S,V in [0, 255]
The following example might give you some hints on how to play with the trackbar and the Hue value:
#include <opencv2/opencv.hpp>
using namespace cv;
Mat3b rgb;
Mat3b hsv;
void on_trackbar(int hue, void*)
{
hsv.setTo(Scalar(hue, 255, 255));
cvtColor(hsv, rgb, COLOR_HSV2BGR);
imshow("HSV", rgb);
}
int main(int argc, char** argv)
{
// Init images
rgb = Mat3b(100, 300, Vec3b(0,0,0));
cvtColor(rgb, hsv, COLOR_BGR2HSV);
/// Initialize values
int sliderValue = 0;
/// Create Windows
namedWindow("HSV", 1);
/// Create Trackbars
createTrackbar("Hue", "HSV", &sliderValue, 180, on_trackbar);
/// Show some stuff
on_trackbar(sliderValue, NULL);
/// Wait until user press some key
waitKey(0);
return 0;
}
Upvotes: 2