Detecting different components:
If you're trying to detect the different components, there probably are other approaches to do them than detecting the contours. Here's an example in Mathematica. An erosion followed by dilation is used to close the gap in the second component before detection (if you don't do this, it won't detect it).
img = Binarize@Import["https://i.stack.imgur.com/yqDyu.png"];
The figure on the left below, shows imperfect object detection (without closing the gap) and on the right, shows the correct detection (running the above code).
Detecting the different contours:
However, if you indeed want to separate only the contours, here's an example. The erosion and dilation are performed as before to close the gap and the resulting image is run through a Canny edge detector. I've made the default options explicit, so that you can see what's being used.
img2 = EdgeDetect[Dilation[Erosion[img, 1], 1], Method -> "Canny"]
This will give you both the inside and the outside edge (see figure on the left below), since the pixel width is greater than 1 all around. I haven't had much luck trying to get it thinner, as the performance degrades (may be different for your other images). The inner contours are the ones you want, and the outer contour is just the combined contour of all 4 components. Now all we need to do is drop the outermost one with:
SelectComponents[img2, "EnclosingComponentCount", # > 0 &]
which gives you just the inner contours (see bottom right). In other words, it only picks those contours that are enclosed by at least one other contour, which automatically disqualifies the outermost one. I do not know the equivalent of these commands/operations in openCV.
Note that the apparent breaks in the figure are due to saving to jpeg in a smaller size. It does not look that way on my screen.