0

I am still new to OpenCV(Python) and am trying out cv2.adaptiveThreshold() to draw proper contours with a webcam running when lighting is changing. The main problem is the insane amount of noise I am getting when drawing contours so I tried to set a cv2.countourArea() threshold but this seems not like the best solution.

Later on I deciced to try and manipulate the values of cv2.adaptiveThreshold with a simple trackbar.

Specifically the blockSize and CValue. Everything works fine on the CValue but I do really struggle on the blockSize since it needs to be an odd number. I tried something along the line of checking if the value of the empty callback function is even and adding +1. But this does not seem to work properly. Later on I will most likely use machine-learning to change these values but for now I'd like the trackbars to work for debugging purposes.

What is the best solution here to manipulate the blockSize with a trackbar?

Thank you in advance! :)

import cv2
import numpy as np

#####################################
winWidth = 640
winHeight = 840
brightness = 100

cap = cv2.VideoCapture(0)
cap.set(3, winWidth)
cap.set(4, winHeight)
cap.set(10, brightness)

kernel = (5, 5)
bSize_default = 1


#######################################################################
def empty(a):
    pass


cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars", 640, 240)
cv2.createTrackbar("cVal", "TrackBars", 2, 20, empty)


def preprocessing(frame, cVal):
    imgGray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # mask = cv2.inRange(imgHsv, lower, upper)
    imgBlurred = cv2.GaussianBlur(imgGray, kernel, 3)
    gaussC = cv2.adaptiveThreshold(imgBlurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, cVal)
    imgDial = cv2.dilate(gaussC, kernel, iterations=3)
    imgErode = cv2.erode(imgDial, kernel, iterations=1)

    return imgDial


def getContours(imPrePro):
    contours, hierarchy = cv2.findContours(imPrePro, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area > 60:
            cv2.drawContours(imgCon, cnt, -1, (255, 0, 0), 3)


#######################################################################################################

while (cap.isOpened()):
    success, frame = cap.read()
    cVal = cv2.getTrackbarPos("cVal", "TrackBars")

    if success == True:
        frame = cv2.flip(frame, 1)
        imgCon = frame.copy()
        imPrePro = preprocessing(frame, cVal)
        getContours(imPrePro)
        cv2.imshow("Preprocessed", imPrePro)
        cv2.imshow("Original", imgCon)

        if cv2.waitKey(1) & 0xFF == ord("q"):
            cv2.destroyAllWindows()
            break
itsolidude
  • 1,119
  • 3
  • 11
  • 22
  • If the value needs to be odd, then the value is `2k + 1` for some `k`, so how about using `k` as the trackbar value instead of the real value itself? In other words, always take the trackbar value and then multiply it by 2 and add 1. Then it will always be odd. If you wanted the odd numbers between 10 and 20 for e.g., those values are `2k + 1` where `k` is at least 5 and less than 10. – alkasm Jan 27 '21 at 20:46
  • I tried that but that does crash the whole program. – itsolidude Jan 27 '21 at 20:56

2 Answers2

2

The minimum value of blocksize must be 3 and also blocksize must be odd therefore:

    value_BSize= cv2.getTrackbarPos("bSize", "TrackBars")
    value_BSize = max(3,value_BSize)
    if (value_BSize % 2 == 0):
          
            value_BSize  += 1
         
Andrewgmz
  • 355
  • 3
  • 11
  • Oh wow, I did not know the min value has to be 3! I only thought it had to be odd. Thanks! Now all my other methods work as well lol – itsolidude Jan 27 '21 at 22:02
0
tbar = (cv2.getTrackbarPos('trackbar', 'window')&~1)+3  # for smooth operation
tbar = cv2.getTrackbarPos('trackbar', 'window')*2+3  # for fast operation
JVod
  • 151
  • 5