We are part of a FIRST robotics team that is using OpenCV for vision detection. Other teams have posted a working detection software This can be found on team2053tigertronics's Github (/2016Code/blob/master/Robot2016/src/vision/vision.cpp) and we are attempting to convert their code into Python as using this code as sample code that we can adjust later. While converting, we ran into a weird issue.
For debugging purposes we are using a print statement to print the contours so that we knew why we got the error when we tried to put the code into the boundingRectangle method
Here is our code so far:http://pastebin.com/7zh4c7Ej
Here is our output: http://pastebin.com/5fRQhC28
The error we are getting:
Traceback:
in line 146, processImage()
in line 98: rec = cv2.boundingRect(i[x])
index 256 is out of bounds for axis 0 with size 15/
Our output has been a list of different numpy arrays that hold integer values. We are confused on how to use these values to draw rectangles and eventually use these values for coordinates for use during the robotics game.
We appreciate any help!!!
Thanks!
Axton (and Team)
EDIT:
As asked for by other members, here is a more simpler question:
Here is our code that we are having problems with:
filler, contours, heirarchy = cv2.findContours(matThresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for i in contours:
for x in i:
rec = Rect()
print i[x]
rec = cv2.boundingRect(i[x])
We would like to know how to use the contour values as points to use the boundingRect method.
Thanks again!
it is indeed as easy as #Miki said above.
since contours is a list of contours, you only need one loop to access a single contour, and get the bounding rect of that:
for contour in contours:
rec = cv2.boundingRect(contour)
print rec
## now, just for the fun, let's look
## at a *single* contour, it consists of points:
for point in contour:
print point
Related
I am an absolute beginner in image processing.I want to detect a nested shape among various different edges.from my program I have successfully detected my expected contour through hierarchy relation.but my problem arises when I am going to detect the shape.for contour approximation, I am using cv2.approxpolyDP() method/function on my desired contour using its index number.but every time it is resulting in the same output, which is "1".I don't know where I am mistaking.please have a look and suggest me some.The code is given below and the images to be detected is also given in those links. please help me...
import cv2
import numpy as np
maxx=0
original_color=cv2.imread("tri.jpg",1)
original=cv2.cvtColor(original_color,cv2.COLOR_BGR2GRAY)
#cv2.imshow("original",original)
blur=cv2.GaussianBlur(original,(5,5),0)
ret,thresh=cv2.threshold(blur,50,255,cv2.THRESH_BINARY)
edges = cv2.Canny(thresh,100,200)
image,contours,hierarchy=cv2.findContours(edges.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print len(contours)
##for c in range(0,len(hierarchy)) :
## a=zip(hierarchy[c],contours[c])
for i in range(0,len(hierarchy[0])):
if hierarchy[0][i][2]>=maxx :
if(hierarchy[0][i][3]==(hierarchy[0][i][2]-2)):
maxx=hierarchy[0][i][2]
index=i
cnt=contours[index]
for c in cnt :
peri=cv2.arcLength(c,True)
approx=cv2.approxPolyDP(c,0.04*peri,True)
print hierarchy
print maxx
print len(approx)
cv2.drawContours(original_color,contours,index,(0,255,0),3)
cv2.imshow("Show",original_color)
cv2.waitKey()
cv2.destroyAllWindows()
Before Detection
Succesfully Detected
The result of findContours is a list of list of points, this means that the problem is here:
cnt=contours[index]
for c in cnt :
peri=cv2.arcLength(c,True)
approx=cv2.approxPolyDP(c,0.04*peri,True)
Here you select a contour(list of pointS) and then loop for each point and do the approxPolyDP with only 1 point. You should do it to the contour. So, if you want it to do it for the selected contour, you should do:
cnt=contours[index]
peri=cv2.arcLength(cnt,True)
approx=cv2.approxPolyDP(cnt,0.04*peri,True)
If you want to do it for each contour then do like this (keeping the print inside the loop, if not it will show only the last one):
for c in contours:
peri=cv2.arcLength(c,True)
approx=cv2.approxPolyDP(c,0.04*peri,True)
print len(approx)
When we want to find the contours of a given image according to a certain threshold, we use the function cv2.findContours() which returns among other things, the list of contours (a Pythonic list of arrays representing contours of the picture).
Here is how to use of the function:
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
My question:
What is the order that OpenCV uses toorder the countours ?
I mean on which criterion it says this contour is in position 0, the other in position 1 and so on ?
I need this information because I want to know which contour I am dealing with in my program and why it is given this or that position.
Hope you won't close my question, I am just a beginner.
I do not fully understand the question but from my understanding the Contour positions are based on the x and y pixel coordinates of the image which is what the returned vector list contain. So surely the criterion is they're position on the image. (Please consider this as a comment)
I am trying to use contours without using the standard openCV contour functions.
At the moment I am trying to take out the first "line" and the last "line" in each contour and I have got a bit stuck on how to read the numpy array correctly. After a lot of messing about this is the current state of the code which doesn't work. Can anyone provide an example of how I should be doing this?
contours,hierarchy = cv2.findContours(mask, 1, 2)
for cnt in contours:
#draw first line
img = cv2.line(img,(cnt[0][0],cnt[0][1]),(cnt[1][0], cnt[1][1]),(255,0,0),2)
#draw last line
img = cv2.line(img,(cnt[cnt.size-1][0],cnt[cnt.size-1][1]),(cnt[cnt.size-1][0], cnt[cnt.size-1][1]),(255,0,0),2)
I'm working on an image of parasite eggs. I need to identify as many eggs as I can individually, I've managed to decent borders around them using the watershed algorithm, but I want to look at the oval egg as a whole, rather than just the yolk part which is generally what the watershed algorithm picks out. I have tried ellipse detection but it only gets the water bubbles (the round black bits with a white dot in the middle) which I actually want to ignore (but am planning to implement later).
What would be the best method to achieve this, I've looked into image mapping but it only returns the best match, I've also considered shape recognition but it apparently isn't implemented in OpenCV.
Here is what my result I get using the watershed algorithm:
http://imgur.com/7ptyIOL
And here is an idea of what I'm wanting to get: http://imgur.com/XPLUixa
All right I've been hacking away at it today and this is the solution I've found. I threshold the image, and then I find the contours. After I have found the contours I will draw an ellipse around each of them if it passes a little check function I have made. This currently works quite well, but I will need to improve my method of thresholding the image before I can expect any real progress.
This code generates the contours and draws them
_, contours, hierarchy = cv2.findContours(opening.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
#will give an error if there are less than 5 points
if len(c) > 4:
elip = cv2.fitEllipse(c)
if check_ellipse(elip):
cv2.ellipse(img, elip, (255, 0, 0))
This is the function used to check the correctness
def check_ellipse(ellipse):
h = ellipse[1][0]
w = ellipse[1][1]
#make sure it's not too large, or too circular
if abs(h-w) < 2 or h > 30 or w > 30:
return False
return True
Later on I may change this so it first gets rid off all of the ellipses which don't pass the test, that way I can have a list of their coordinates which is what I really need if I want to progress with this program.
I am currently using FindContours and DrawContours function in order to segment an image.
I only extract external contours, and want to save only the contour which contains a given point.
I use h_next to move through the cv_seq structure and test if the point is contained using PointPolygonTest
I actually can find the contour that interests me, but my problem is to extract it.
Here is the python code :
def contour_from_point(contours, point, in_img):
"""
Extract the contour from a sequence of contours which contains the point.
For this to work in the eagle road case, the sequence has to be performed using the
FindContours function with CV_RETR_EXTERNAL
"""
if contours:
# We got at least one contour. Search for the one which contains point
contour = contours # first contour of the list
distance = cv.PointPolygonTest(contour, point, 0)
while distance < 0: # 0 means on eadge of contour
contour = contour.h_next()
if contour: # avoid end of contours
distance = cv.PointPolygonTest(contour, point, 0)
else :
contour = None
else:#
contour = None
return contour
At the end, I got contour. But this structure still contains all the contours that have not been tested yet.
How can I do to keep only the first contour of my output sequence?
Thanks by advance !
There is finally a way to get only one contour. Juste use another function that needs a cvseq in input, as ConvexHull for example. The output will be only the first contour of the sequence.