'Odd numbers only on OpenCV trackbar for Python?

I am learning how to use OpenCV on Python for skin segmentation and right now I am mostly in the experimental phase, where I am playing with the Gaussian Blue to reduce the sharp contrasts which I am getting with Otsu's Binarization.

One stratergy that I found very useful in my experimentation was to use the trackbar functionality on the display window to change various parameters such as selection of the kernel size and standard deviation of the Gaussian function. The trackbar works great when I change the std, but my program crashes when I do the same for kernel size.

The reason for this is that kernel size takes only odd numbers > 1 as a tuple of two values. Since the track bar is continuous, when I move it and the trackbar reads an even number, the Gaussian function throws an error.

I was hoping that you could provide me with a solution to create a trackbar with only odd numbers or even only numbers from an array, if possible. Thanks!

# applying otsu binerization to video stream
feed = cv2.VideoCapture(0)

# create trackbars to control the amount of blur 
cv2.namedWindow('blur')
# callback function for trackbar
def blur_callback(trackbarPos):
    pass
# create the trackbar 
cv2.createTrackbar('Blur Value', 'blur', 1, 300, blur_callback)
# cv2.createTrackbar('Kernel Size', 'blur', 3, 51, blur_callback)

while True:
    vid_ret, frame = feed.read()
    # flip the frames 
    frame = cv2.flip(frame, flipCode=1)

    # convert the feed to grayscale
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # get blur value from trackbar and apply gaussian blur to frame_gray
    blurVal = cv2.getTrackbarPos('Blur Value', 'blur')
#     kernelSize = cv2.getTrackbarPos('Kernel Size', 'blur')
    frame_blur = cv2.GaussianBlur(frame_gray, (11, 11), blurVal)

    # apply Otsu binerization on vanilla grayscale
    otsu_ret, otsu = cv2.threshold(frame_gray, 0, 255, cv2.THRESH_OTSU)

    # apply Otsu binerization on blurred grayscale
    otsu_blue_ret, otsu_blur = cv2.threshold(frame_blur, 0, 255, cv2.THRESH_OTSU)


    # show the differnt images
    cv2.imshow('color', frame)
#     cv2.imshow('gray', frame_gray)
    cv2.imshow('blur', frame_blur)
    cv2.imshow('otsu', otsu)
    cv2.imshow('otsu_blur', otsu_blur)
    # exit key
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

# release the feed and close all windows
feed.release()
cv2.destroyAllWindows()


Solution 1:[1]

I know this is an old post but here is my solution:

def on_blockSize_trackbar(val):
    global blockSize
    if (val%2)==0:
        blockSize = val+1
        cv2.setTrackbarPos(blockSize_name, window_detection_name, blockSize)
    else:
        blockSize=val
        cv2.setTrackbarPos(blockSize_name, window_detection_name, blockSize)
    blockSize = max(blockSize, 1)

with the line to create the Trackbar

cv2.createTrackbar(blockSize_name, window_detection_name , blockSize, 100, on_blockSize_trackbar)

You will see that the number you pick on the trackbar will remain incremental with odd or even numbers but the real value sent in the code will only be odd numbers.

Solution 2:[2]

Use remainder function & add 1 value for even number, so you won't crash

Here you go:

cv2.createTrackbar('Blur Value', 'blur', 1, 20, blur_callback)

while True:

    gaus = cv2.getTrackbarPos('Blur Value', 'blur')

    if gaus == 0:
        ......
    else:
        count = gaus % 2 

        if (count == 0):
            gaus += 1
            frame_blur = cv2.GaussianBlur(frame_gray, (gaus, gaus), 0)
        else:
            frame_blur = cv2.GaussianBlur(frame_gray, (gaus, gaus), 0)

I've been doing this function, not really perfect but it runs. Do check it out on my Github: https://github.com/jiasuan/opencv/blob/master/Trackbar.py

It's easier for you to observe image when you use trackbar. But the arrangement of each functions will affect result of your data. For example, blur before grayscale and blur after grayscale, result will be vary. You have to carefully arrange it before you run.

Solution 3:[3]

To add to Louis' answer, you can move the trackbar to the odd position by using setTrackbarPos()

see: https://docs.opencv.org/trunk/d7/dfc/group__highgui.html#ga67d73c4c9430f13481fd58410d01bd8d

Solution 4:[4]

Try this:

cv2.createTrackbar('Blur Value', 'blur', 1, 20, blur_callback)

while True:
    gaus = cv2.getTrackbarPos('Blur Value', 'blur')
    if gaus%2 == 0:
        gaus+=1 # here all even numbers will be converted to odd. Make range as 1-19 than 1-20 

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 S.B
Solution 2 louis
Solution 3 Arnþór Gíslason
Solution 4