OpenCV - адаптивная установка пороговых значений / манипуляции с трекбаром

Я все еще новичок в OpenCV (Python) и пытаюсь cv2.adaptiveThreshold() рисовать правильные контуры с веб-камерой, работающей при изменении освещения. Основная проблема - это безумное количество шума, которое я получаю при рисовании контуров, поэтому я попытался установить порог cv2.countourArea(), но это не похоже на лучшее решение.

Позже я решил попробовать манипулировать значениями cv2.adaptiveThreshold с помощью простой трекбара.

В частности, blockSize и CValue. С CValue все работает нормально, но с blockSize мне действительно сложно, так как это должно быть нечетное число. Я попробовал что-то вроде проверки, является ли значение функции обратного вызова empty четным, и добавил +1. Но, похоже, это не работает должным образом. Позже я, скорее всего, воспользуюсь машинным обучением, чтобы изменить эти значения, но пока я бы хотел, чтобы трекбары работали в целях отладки.

Какое здесь лучшее решение для управления blockSize с помощью трекбара?

Заранее спасибо! :)

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


person itsolidude    schedule 27.01.2021    source источник
comment
Если значение должно быть нечетным, тогда значение будет 2k + 1 для некоторого k, так как насчет использования k в качестве значения трекбара вместо самого реального значения? Другими словами, всегда берите значение трекбара, а затем умножайте его на 2 и прибавляйте 1. Тогда оно всегда будет нечетным. Если вам нужны нечетные числа от 10 до 20, например, эти значения равны 2k + 1, где k - от 5 до 10.   -  person alkasm    schedule 27.01.2021
comment
Я пробовал это, но это приводит к сбою всей программы.   -  person itsolidude    schedule 27.01.2021


Ответы (1)


Минимальное значение размера блока должно быть 3, а также размер блока должен быть нечетным, поэтому:

    value_BSize= cv2.getTrackbarPos("bSize", "TrackBars")
    value_BSize = max(3,value_BSize)
    if (value_BSize % 2 == 0):
          
            value_BSize  += 1
         
person Andrewgmz    schedule 27.01.2021
comment
Ого, я не знал, что минимальное значение должно быть 3! Я только подумал, что это должно быть странно. Спасибо! Теперь все мои другие методы тоже работают, лол - person itsolidude; 28.01.2021