opencvrusthsvhighgui

How to implement HSV slider with OpenCV using BGR2HSV and opencv:highgui::create_trackbar in Rust


Please bear with me as this is my first post to stack overflow.

I am attempting to learn rust with a fairly elementary background in OpenCV through python.

In my original python script I could use createTrackbar() pretty easily but when converting to rust I am having trouble understanding how to use the "value", and "on_change" parameters from the Rust OpenCV documentation here

pub fn create_trackbar(
    trackbarname: &str,
    winname: &str,
    value: Option<&mut i32>,
    count: i32,
    on_change: TrackbarCallback
) -> Result<i32>

My end goal is to then use opencv::highgui::get_trackbar_pos to control Hue max and min, saturation max and min, and value max and min like I do in the python example below:

while True:

    cv2.namedWindow("HSV")
    cv2.resizeWindow("HSV",640,480)
    cv2.createTrackbar("HUE MIN","HSV",0,179,empty)
    cv2.createTrackbar("HUE MAX","HSV",0,179,empty)
    cv2.createTrackbar("SAT MIN","HSV",0,255,empty)
    cv2.createTrackbar("SAT MAX","HSV",0,255,empty)
    cv2.createTrackbar("VAL MIN","HSV",0,255,empty)
    cv2.createTrackbar("VAL MAX","HSV",0,255,empty)

    while(cap.isOpened()):
        ret, frame = cap.read()
        if ret==True:
            
            hsvframe = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

            h_min = cv2.getTrackbarPos("HUE MIN","HSV")
            h_max = cv2.getTrackbarPos("HUE MAX","HSV")
            s_min = cv2.getTrackbarPos("SAT MIN","HSV")
            s_max = cv2.getTrackbarPos("SAT MAX","HSV")
            v_min = cv2.getTrackbarPos("VAL MIN","HSV")
            v_max = cv2.getTrackbarPos("VAL MAX","HSV")
        

            lower = np.array([h_min,s_min,v_min])
            upper = np.array([h_max,s_max,v_max])
            mask = cv2.inRange(hsvframe,lower,upper)
            result = cv2.bitwise_and(frame,frame,mask=mask)

            print(lower,upper)

            out.write(mask)
            cv2.imshow('mask',mask)
            pass
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        else:
            break

I understand that trackbar name is going to be a string that I choose myself, winname is the hsv window I created, I know count is 179 as I want 180 values from 0 to 179, but don't really understand what Option and TrackbarCallback are supposed to be put in as.

Here is my code below.


use opencv::{ highgui::{self, WINDOW_AUTOSIZE}, imgproc, prelude::*, videoio, Result};

fn run() -> Result<()> {

    let window = "video capture";
    let hsv = "HSV";

    
    highgui::named_window(window, 1)?;
    
    highgui::named_window(hsv, WINDOW_AUTOSIZE)?;
    highgui::create_trackbar("HUE MAX", hsv, )?;
    highgui::create_trackbar("HUE MIN", hsv, )?;

    opencv::opencv_branch_32! {
        let mut cam = videoio::VideoCapture::new_default(0)?; // 0 is the default camera
    }
    opencv::not_opencv_branch_32! {
        let mut cam = videoio::VideoCapture::new(0, videoio::CAP_ANY)?; // 0 is the default camera
    }
    let opened = videoio::VideoCapture::is_opened(&cam)?;
    if !opened {
        panic!("Unable to open default camera!");
    }

    loop {
        let mut frame = Mat::default();
        cam.read(&mut frame)?;
        if frame.size()?.width > 0 {
            let mut gray = Mat::default();
            imgproc::cvt_color(&frame, &mut gray, imgproc::COLOR_BGR2HSV, 0)?;
            highgui::imshow(window, &gray)?;
        }
        if highgui::wait_key(10)? > 0 {
            break;
        }
    }
    Ok(())

}

fn main() {

    run().unwrap()

}


As far as I can tell, Option seems to be an arbitrary starting position so I think i32 = 0 could work but I'm not sure, then when going through the TrackbarCallback documentation I'm not sure if I should be putting in the word "pos"

Im sure the answer is rather simple but please understand my exposure is very limited and I am doing my best to learn as much as I can without getting overwhelmed too fast.


Solution

  • If you intend to read the value with get_trackbar_pos, then you can put None for both value and on_change.

    In C/C++, value is intended to be a variable in which OpenCV writes the value each time it changes so that you can read it instead of calling get_trackbar_pos. Not sure how that translates to Rust since the existence of a mutable reference to it in OpenCV makes it undefined behaviour to read it elsewhere.

    on_change is intended to be the address of a function that OpenCV will call when the value changes, so that you can process the change immediately. You don't need it if you read the value with get_trackbar_pos.