ffttyy
ffttyy

Reputation: 864

Trackbar to choose color. Using C++, opencv

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?

enter image description here

Upvotes: 2

Views: 3504

Answers (2)

Winand
Winand

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.

HSV slider example

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

Miki
Miki

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

Related Questions