Reputation: 155
I was working on the example of finding and drawing contours in opencv python. But when I run the code, I see just a dark window with no contours drawn. I don't know where I am going wrong. The code is:
import numpy as np
import cv2
im = cv2.imread('test.png')
imgray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
img=cv2.drawContours(image,contours,0,(0,255,0),3)
cv2.imshow('draw contours',img)
cv2.waitKey(0)
test.png
is just a white rectangle in black background.
Any help would be appreciated.
Edit: I am using Opencv 3.0.0 and Python 2.7
Upvotes: 9
Views: 17253
Reputation: 1094
If your image has only one channel, you can't draw colors on it, because it's grayscale.
As @Scott mentioned, It's a good idea to check your image shape:
print(image.shape)
So if you want to draw colored contour, you have to convert 1 channel grayscale image to 3 channel image:
import cv2
# read image as grayscale, so I don't have to use cv2.cvtColor
gray = cv2.imread("test.png", cv2.IMREAD_GRAYSCALE)
# threshold image
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# find contours
cnts, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# this does the magic
# convert 1 channel grayscale image to 3 channel colored image
color = cv2.cvtColor(gray, cv2.COLOR_GRAY2RGB)
# draw contours on it
cv2.drawContours(color, cnts, -1, (0, 255, 0), -1)
cv2.imshow("contours", color)
cv2.waitKey(0)
cv2.destroyAllWindows()
Or if you just want to draw grayscaled colors, you don't have to convert it to 3 channel image:
import cv2
# read image as grayscale, so I don't have to use cv2.cvtColor
gray = cv2.imread("test.png", cv2.IMREAD_GRAYSCALE)
# threshold image
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# find contours
cnts, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# draw black contours on it
cv2.drawContours(color, cnts, -1, (0,), -1)
cv2.imshow("contours", color)
cv2.waitKey(0)
cv2.destroyAllWindows()
Upvotes: 4
Reputation: 5858
Just make sure that image
is 3 channel here:
img = cv2.drawContours(image, contours, -1, (0, 255, 0), 3)
Check image shape:
print(image.shape)
# (400, 300) -> Error
# (400, 300, 3) -> Works
Upvotes: 8
Reputation: 126
I believe the problem is with the drawContours
command. As currently written, the image destination is both image
and img
. You are also attempting to draw a colored box onto a single channel 8-bit image. In addition, it is worth noting that the findContours
function actually modifies the input image in the process of finding the contours, so it is best not to use that image in later code.
I would also recommend creating a new image copy to set as your destination for the drawContours
function if you intend on doing further analysis on your image so you don't write over the only copy to which your program currently has access.
import numpy as np
import cv2
im = cv2.imread('test.png')
imCopy = im.copy()
imgray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(imCopy,contours,-1,(0,255,0))
cv2.imshow('draw contours',imCopy)
cv2.waitKey(0)
These two quick fixes worked for me on a similar image of a black square with a white background.
Upvotes: 11