Обнаружение различных компонентов:
Если вы пытаетесь обнаружить различные компоненты, возможно, существуют другие подходы к их выполнению, кроме определения контуров. Вот пример в Mathematica. Эрозия с последующим расширением используется, чтобы закрыть зазор во втором компоненте до обнаружения (если вы этого не сделаете, он не обнаружит).
img = Binarize@Import["http://i.stack.imgur.com/yqDyu.png"];
Colorize[MorphologicalComponents[Dilation[Erosion[img,1],1]]]
На рисунке слева внизу показано обнаружение несовершенных объектов (без устранения разрыва), а справа показано правильное обнаружение (с использованием приведенного выше кода).
Обнаружение различных контуров:
Однако, если вы действительно хотите отделить только контуры, вот пример. Эрозия и расширение выполняются, как и прежде, чтобы закрыть зазор, и полученное изображение пропускается через детектор краев Canny. Я сделал параметры по умолчанию явными, чтобы вы могли видеть, что используется.
img2 = EdgeDetect[Dilation[Erosion[img, 1], 1], Method -> "Canny"]
Это даст вам как внутренний, так и внешний край (см. Рисунок слева ниже), поскольку ширина пикселя больше 1 вокруг. Мне не очень повезло, пытаясь сделать его тоньше, так как производительность ухудшается (может отличаться для других ваших изображений). Внутренние контуры - это те, которые вам нужны, а внешний контур - это просто объединенный контур всех 4 компонентов. Теперь все, что нам нужно сделать, это отбросить самый внешний с помощью:
SelectComponents[img2, "EnclosingComponentCount", # > 0 &]
который дает вам только внутренние контуры (см. справа внизу). Другими словами, он выбирает только те контуры, которые окружены хотя бы одним другим контуром, который автоматически дисквалифицирует самый внешний. Я не знаю эквивалента этих команд / операций в openCV.
Обратите внимание, что видимые разрывы на рисунке связаны с сохранением в формате JPEG в меньшем размере. На моем экране это выглядит не так.