NB: Specific to OpenCV 3.x
The second result from cv2.findContours
is a list of contours.
The second parameter of cv.drawContours
should be a list of contours.
A contour is represented as a list (or array) of points. Each point is a list of coordinates.
There are multiple ways how to draw only a single contour:
import cv2
src_img = cv2.imread("blob.png")
gray_img = cv2.cvtColor(src_img, cv2.COLOR_BGR2GRAY)
contours = cv2.findContours(gray_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)[1]
print(contours)
# Choose one:
# Draw only first contour from the list
cv2.drawContours(src_img, contours, 0, (0,255,0), 2)
# Pass only the first contour (v1)
cv2.drawContours(src_img, [contours[0]], -1, (0,255,0), 2)
# Pass only the first contour (v2)
cv2.drawContours(src_img, contours[0:1], -1, (0,255,0), 2)
cv2.imshow("Contour", src_img)
cv2.waitKey()
Sample input image:
When we inspect the result of cv2.findContours
, the reason why you were seeing dots becomes apparent -- there are 4 levels of nesting.
[
array([
[[ 95, 61]], # Point 0
[[ 94, 62]], # Point 1
[[ 93, 62]],
... <snip> ...
[[ 98, 61]],
[[ 97, 61]],
[[ 96, 61]]
]) # Contour 0
]
According to the definitions at the beginning of this answer, we can see that the points in this case are wrapped in an additional list, e.g. [[ 98, 61]]
. OpenCV apparently deals with this correctly - I suppose this was intended as a feature.
If we remove the outer list by using only the first element of contours
, we effectively turn each point into a separate contour containing a single point.
array([
[
[ 95, 61] # Point 0
], # Contour 0
[
[ 94, 62] # Point 0
], # Contour 1
... and so on
])