Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cv2.drawContours will not draw filled contour

Tags:

python

opencv

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:

image linked. 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:

is uploaded here

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')`
like image 942
The man they call Jayne Avatar asked Jul 21 '17 20:07

The man they call Jayne


People also ask

How do you draw specific contours in OpenCV Python?

To draw the contours, cv. drawContours function is used. It can also be used to draw any shape provided you have its boundary points. Its first argument is source image, second argument is the contours which should be passed as a Python list, third argument is index of contours (useful when drawing individual contour.

How do you expand contour in OpenCV?

You can use cv::dilate() and cv::erode() then detect the contours again.


1 Answers

The function takes ArrayOfArrays as input.
Try: cv2.drawContours(mask, [cnt], -1, (0,255,255), -1)
instead of: cv2.drawContours(mask, cnt, -1, (0,255,255), -1).

like image 142
Neeraj Jain Avatar answered Oct 16 '22 18:10

Neeraj Jain