Search code examples
pythonopencvtrackbar

Creating multiple trackbars in Opencv Python


Trying to create 3 trackbars for 1 window.

Im taking an image. Coverting it to gray. Using non local means aka blurring it. Passing it thru a threshold called bino. Doing an edge detection on it. Using the edge detection to find contours. Sorting thise contours by area. Taking only the largest contour. And displaying it preferably over the canny or thresholded image.

I need a track bar for the nlm blur, the threshold, and the canny lines all on the same image but I dont know how to do it and cant figure it out. Please your my only hope!

import numpy as np
import cv2 as cv

def thresh_callback(val):
    nlm_thresh = val
    bino_thresh = val
    canny_thresh = val

    img = cv.imread('test.jpg')
    imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    nlm = cv.fastNlMeansDenoising(imgray,nlm_thresh,nlm_thresh,11,21)
    bino = cv.adaptiveThreshold(nlm,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,\
                             cv.THRESH_BINARY,bino_thresh,8)
    canny_output = cv.Canny(bino, canny_thresh, canny_thresh * 2)
    _, contours, hierarchy = cv.findContours(canny_output,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
    cnt = sorted(contours, key=cv.contourArea, reverse=True)
    cnts = cnt[0]
    area = cv.contourArea(cnts)
    print (area)

    drawing = cv.drawContours(img, cnt, 0, (0,255,0), 3)

    cv.imshow('Contours2', canny_output)
    cv.imshow(source_window, drawing)


source_window = 'Source'
cv.namedWindow(source_window)
max_thresh = 255
thresh = 100 # initial threshold
cv.createTrackbar('nlm_thresh:', source_window, thresh, max_thresh, thresh_callback)
cv.createTrackbar('bino_thresh:', source_window, thresh, max_thresh, thresh_callback)
cv.createTrackbar('canny_thresh:', source_window, thresh, max_thresh, thresh_callback)

thresh_callback(thresh)

cv.waitKey(0) & 0xFF  
cv.destroyAllWindows()

Solution

  • Have the trackbars call separate functions that update the relevant (global) variable and then call the function that processes the image.

    import numpy as np
    import cv2 as cv
    
    #initialise variables with a default
    nlm_thresh = 5
    bino_thresh = 5
    canny_thresh = 5
    
    # functions that update a variable, 
    # then call image processing function
    def change_nlm(val):
        global nlm_thresh
        nlm_thresh = val
        thresh_callback()
    
    def change_bino(val):
        global bino_thresh
        bino_thresh = val
        thresh_callback()
    
    def change_canny(val):
        global canny_thresh
        canny_thresh = val
        thresh_callback()
    
    # your function that processes the image
    def thresh_callback():
        img = cv.imread('test.jpg')
        imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
        nlm = cv.fastNlMeansDenoising(imgray,nlm_thresh,nlm_thresh,11,21)
        bino = cv.adaptiveThreshold(nlm,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,          cv.THRESH_BINARY,bino_thresh,8)
        canny_output = cv.Canny(bino, canny_thresh, canny_thresh * 2)
        _, contours, hierarchy = cv.findContours(canny_output,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
        cnt = sorted(contours, key=cv.contourArea, reverse=True)
        cnts = cnt[0]
        area = cv.contourArea(cnts)
        print (area)
    
        drawing = cv.drawContours(img, cnt, 0, (0,255,0), 3)
    
        cv.imshow('Contours2', canny_output)
        cv.imshow(source_window, drawing)
    
    
    source_window = 'Source'
    cv.namedWindow(source_window)
    max_thresh = 255
    thresh = 100
    # create trackbars
    cv.createTrackbar('nlm_thresh:', source_window, thresh, max_thresh, change_nlm)
    cv.createTrackbar('bino_thresh:', source_window, thresh, max_thresh, change_bino)
    cv.createTrackbar('canny_thresh:', source_window, thresh, max_thresh, change_canny)
    
    thresh_callback()
    
    cv.waitKey(0) & 0xFF  
    cv.destroyAllWindows()