Reputation: 8775
I am learning to use the cv2.approxPolyDP function to segment an OpenCV contour into simpler more relevant curves. I want to illustrate this for myself to better understand what is going on. I am getting close, and the cv2.approxPolyDP function (implementing the RDP algorithm) seems to be working, but the output when drawn as a contour seems to be a series of dots rather than the curves I expected.
Feel free to contribute anything helpful.
This is the test-pattern.png file I am using:
import numpy as np
import cv2, cv
#read the test image - this one happens to be binary
img = cv2.imread("test-pattern.png",0)
#invert the image
img2 = cv2.bitwise_not(img)
cv2.imshow("after bitwise not",img2)
#find the contours of the image
contour,hier = cv2.findContours(img,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
#make a color image of the same size for displaying contours later on .... img3 and img4
height, width = img.shape # binary image is height, width; otherwise would be height, width, depth
img3 = np.zeros((height,width,3), np.uint8)
img4 = np.zeros((height,width,3), np.uint8)
#draw contours on the color image
cv2.drawContours(img3,contour[0],-1,(0,0,200),1)
cv2.imshow("contours",img3)
#print a bunch of stuff to the command line for diagnostic purposes
print "contour vector length: ", len(contour), "\n hier length: ", len(hier)
print "contour area: ", cv2.contourArea(contour[0])
print "canvas area: ", height*width
print "bounding rect: ", cv2.boundingRect(contour[0])
#get the RDP curve vector, and try to display it as a contour on img4
#I chose an epsilon value of 1.1 ... it can be tweaked later
#It will be best to draw these curves in a rainbow colorspace so I can see them
print "RDP curve:", cv2.approxPolyDP(contour[0], 1.1, 1)
print "RDP curve length: ", len(cv2.approxPolyDP(contour[0], 1.1, 1))
cv2.drawContours(img4,cv2.approxPolyDP(contour[0], 1.1, 1),-1,(0,90,200),1)
cv2.imshow("contours",img4)
cv2.waitKey(0)
Here is a cropped piece of the output produced by the last section of code. I cropped it so that you can see the dot pattern. I am not used to working with curves through OpenCV, but what I would like to do for understanding purposes is display the curves generated by the RDP algorithm (cv2.approxPolyDP) in some sort of rainbow colorspace. This way I can see all the individual curves being connected to form the contour. Later I will need to perform some operations on these curves, so visualizing them could be really useful.
Another interesting thing that I noticed initially when drawing the contours themselves is that if I used cv2.drawContours passing in all the contours cv2.drawContours(img3,contour,-1,(0,0,200),1)
I got a solid tracing of the shape, as well as the outside border of the frame:
On the other hand, if I chose the contour representing the shape itself (not the outside border of the frame) cv2.drawContours(img3,contour[0],-1,(0,0,200),1)
, I got more of a dotted tracing as output:
I guess I don't have a complete handle on what the drawContours function is doing here.
Upvotes: 2
Views: 3238
Reputation: 21
The reason why you get the dotted results is because you pass an incorrect data type to the drawContours
function. The approximation is a numpy array, while the function needs a list.
This should solve the problem:
cv2.drawContours(img3,[contour[0]],-1,(0,0,200),1)
Note that the second argument is now [contour[0]]
Upvotes: 2