cv2.drawContours will not draw filled contour
opencv, python
Solution
The function `drawContours` takes a list of contours as input. Try:
cv2.drawContours(
image=mask,
contours=[cnt],
contourIdx=-1,
color=(0,255,255),
thickness=cv2.FILLED)
instead of: `cv2.drawContours(mask, cnt, -1, (0,255,255), -1)`.
Problem
I'm trying to display a filled contour using the `cv2.drawContours` function in OpenCV. I've developed a list of contours from an edge image derived from a `Canny` detection, and am finding the contours with `RETR_EXTERNAL` enabled for the hierarchy definition. However I'm running into an issue that despite using the `-1` flag in the `cv2.drawContours` command to indicate a filled contour, only the contour itself(i.e. edge) is displayed. For example: ``` mask = np.zeros(rawimg.shape, np.uint8) cv2.drawContours(mask, contours[246], -1, (0,255,255), -1) ``` results in just the outline of contour 246 being displayed. As I am only retrieving the external contours I don't think I am seeing just the difference between the internal and external contours found at each edge, so I'm a bit confused as to why it is displaying the contour, but not filling as the `-1` flag would suggest it should. EDIT: The full code is included below. The issue is with the line: cv2.drawContours(mask, cnt, 2, (0,255,255), -1) While this is formatted in the manner suggested by Dan, it results in the following image: . cnt is a single contour, so this makes sense that it would be referring to a single point in the contour. When the line is changed to: ``` cv2.drawContours(mask, cnt, -1, (0,255,255), -1) ``` the contour prints as before, however the contour is still not filled as the -1 flag at the end of the command would suggest it should be. The test image: ``` import os import cv2 import numpy as np from matplotlib import pyplot as plt import copy as cp path = 'C:\\Users\\...deleted...\\Desktop\\testimage6.jpg' #Determine largest contour in the image def maxContour(contours): cnt_list = np.zeros(len(contours)) for i in range(0,len(contours)): cnt_list[i] = cv2.contourArea(contours[i]) max_value = np.amax(cnt_list) max_index = np.argmax(cnt_list) cnt = contours[max_index] return cnt, max_index if os.path.isfile(path): # Import the raw image to a working location and save to an isolated variable # Import the raw image to a working location and save to an isolated variable img = cv2.imread(path) rawimg = cv2.imread(path) saveimg = cv2.imread(path) imgray = cv2.cvtColor(saveimg, cv2.COLOR_BGR2GRAY) saveimgray = cp.copy(imgray) f1 = plt.figure(1) f1.set_size_inches(8,10) plt.title('Original Image') plt.xticks([]), plt.yticks([]) plt.imshow(rawimg, cmap='gray') plt.savefig('output1.jpg', dpi=300) cv2.imshow('Raw Image',rawimg) cv2.waitKey(0) cv2.destroyWindow('Raw Image') # Impose an opening function as a filter kernel = np.ones((3,3),np.uint8) opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) f2 = plt.figure(2) f1.set_size_inches(8,10) plt.title('Opened Image') plt.xticks([]), plt.yticks([]) plt.imshow(opening, cmap='gray') plt.savefig('output2.jpg', dpi=300) cv2.imshow('Opened Image', opening) cv2.waitKey(0) cv2.destroyWindow('Opened Image') #Extract the edges from the filtered image edges = cv2.Canny(opening,10,100) cv2.imshow('Edges', edges) cv2.waitKey(0) cv2.destroyWindow('Edges') f3=plt.figure(3) f3.set_size_inches(16,8) plt.title('Edge Image') plt.xticks([]), plt.yticks([]) plt.imshow(edges, cmap='gray') plt.savefig('output3.jpg', dpi=300) #Detect contours in the edge image image, contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) cv2.drawContours(img, contours, -1, (0,255,255), 2) cv2.imshow('Contours Image', img) cv2.waitKey(0) cv2.destroyWindow('Contours Image') f4=plt.figure(4) f4.set_size_inches(16,8) plt.title('Contour Image') plt.xticks([]), plt.yticks([]) plt.imshow(img) plt.savefig('output2.jpg', dpi=300) #Find maximum area contour cnt, max_index = maxContour(contours) print(max_index) # Calculate contour-based statistics # TBD #Test of removing max contour #grayimg = cv2.cvtColor(rawimg, cv2.COLOR_BGR2GRAY) mask = np.zeros(rawimg.shape, np.uint8) cv2.drawContours(mask, cnt, 2, (0,255,255), -1) #ret, mask = cv2.threshold(grayimg, 10, 255, cv2.THRESH_BINARY) mask_inv = cv2.bitwise_not(mask) cv2.imshow('Mask Image', mask) cv2.waitKey(0) cv2.destroyWindow('Mask Image') cv2.imshow('Mask Image', mask_inv) cv2.waitKey(0) cv2.destroyWindow('Mask Image') #Fit ellipse to contour and calculate ellipse statistics (x,y), (w,h), angle = cv2.fitEllipse(cnt) rect = cv2.minAreaRect(cnt) box = cv2.boxPoints(rect) box = np.int0(box) x = np.int0(x) y = np.int0(y) w = np.int0(0.5*w) h = np.int0(0.5*h) #output2 = cv2.ellipse(img, center, dim, angle, 0, 360, (255,0,0), 12) output2 = cv2.ellipse(img, (x,y), (w,h), angle, 0, 360, (255,0,0), 2) output3 = cv2.drawContours(output2, [box], 0, (0,255,0), 2) cv2.imshow('Ellipse Image',output2) cv2.waitKey(0) cv2.destroyWindow('Ellipse Image') else: print('file does not exist')` ```