Определение контура фигуры в изображении

#python #opencv

#python #opencv

Вопрос:

Я хочу определить внешний круг, который ограничивает фигуру, края фигуры и круг внутри фигуры.

Я использую этот код для порога:

     def adjustImage(img):
        src = adjust_gamma(img, 0.5)
        src_gray = src.copy()
        src_gray = cv.blur(src_gray, (5,5))
        hsv = cv.cvtColor(src_gray, cv.COLOR_BGR2HSV)
        h, s, v = cv.split(hsv)
        thresh = cv.adaptiveThreshold(v, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY_INV, 5, 3)
        return thresh
  
  

Однако этот код не всегда работает. Например, для этого изображения результат кода неверен:
Пример 3

Может ли кто-нибудь дать мне некоторые рекомендации о том, почему этот код не работает для всех этих изображений? Спасибо!

Комментарии:

1. Вы пробовали разные параметры для adaptiveThreshold() ?

2. @Powercoder Я пробовал использовать разные параметры для adaptiveThreshold() . Однако, когда я меняю параметры, некоторые изображения работают, а некоторые изображения не работают. Из того, что я могу сказать, не существует определенного набора параметров, которые работают для всех изображений.

3. Прикрепление исходных изображений без нарисованных кругов облегчит людям помощь вам

4. Ваш адаптивный порог должен быть настроен для каждого изображения. Попробуйте пороговое значение OTSU на его месте. Пропустите размытие, и если вам нужно избавиться от незначительных посторонних областей, используйте фильтрацию контуров по области или морфологии.

Ответ №1:

Предоставленные вами изображения несколько зашумлены, и кажется, что перед использованием им требуется фильтрация adaptiveThreshold() , что-то лучше, чем просто размытие. Возможно cv.fastNlMeansDenoising() , это кандидат. Проверьте разницу:

cv.blur: cv2. результат размытия, cv.fastnl означает уменьшение шума: cv.fastnl означает разочаровывающий результат

Если ваши входные изображения всегда такие, я имею в виду довольно однотонные, я бы рекомендовал вместо этого использовать этот способ определения порога:

 def adjustImage(img):
    src_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    v_avg = np.average(src_gray)
    v_max = np.max(src_gray)
    _, thresh = cv.threshold(src_gray, v_avg   (v_max - v_avg) / 2, 255, cv.THRESH_BINARY)
    thresh = cv.morphologyEx(thresh, cv.MORPH_CLOSE, np.ones((5, 5)))
    return thresh
  

Или, как упоминал @fmw42, OTSU — еще более естественное решение:

 def adjustImage(img):
    src_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    _, thresh = cv.threshold(src_gray, 0, 255, cv.THRESH_BINARY   cv.THRESH_OTSU)
    thresh = cv.morphologyEx(thresh, cv.MORPH_CLOSE, np.ones((5, 5)))
    return thresh
  

Опубликованный вами код по какой-то причине не рисует круги прямо после копирования, но взгляните на то, что мы получаем с помощью функции выше:

пример1 пример2 пример3

Комментарии:

1. Почему бы просто не использовать пороговое значение OTSU?

2. OTSU тоже отличное решение