dimanche 26 mars 2017

Missing arrays from a multidimensional array

So apologies for the length of code here. Basically I have used opencv to analyse an image of 7 shapes and read 4 features from it.

The problem is that the code is only giving me out arrays for 5 shapes and I'm unsure why. I have left out the imports etc at the start to shorten the code.

img = cv2.imread("C:\\Users\\telli\\Desktop\\Shapetest.jpg")
#print(img)

#Converting the image to Grayscale
grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret,thresh = cv2.threshold(grey,127,255,1)

im2,contours, h = cv2.findContours(thresh, 1, cv2.CHAIN_APPROX_SIMPLE)
contours.sort(key = len)
numberOfSides = []
corners = []
standardDeviationsPerimeter = []
sidesDividedByPerimeter = []
standardDeviationsAngles = []
largestAngles = []
angles = []
perimeters = []
featureVectors = []

#finding all the possible circles in the image (likely many false positives)
circles = cv2.HoughCircles(grey,cv2.HOUGH_GRADIENT,1,20,
                        param1=50,param2=30,minRadius=0,maxRadius=0)

#finding sides

count = 0;
#print("New perimeter")
for contour in contours:

    #remove double recognitions due to thick lines
    if count %2 == 0:
        epsilon = 10
        x, y, w, h = cv2.boundingRect(contour)
        x-= epsilon
        y-= epsilon
        w+= 2 *epsilon
        h+= 2 * epsilon
        insideCircle = False

        #Removing false positive circles by testing each circle against
        #the bounding box of this contour
        #if we find a circle that is COMPLETELY inside the bounding box
        #we have found a circle
        for possibleCircle in range (0, len(circles[0])):
            centreX = circles[0][possibleCircle][0]
            centreY = circles[0][possibleCircle][1]
            radius = circles[0][possibleCircle][2]

            ToRight = centreX - radius >= x
            ToLeft = centreX + radius <= x + w
            ToBottom = centreY - radius >= y
            ToTop = centreY + radius <= y + h

            insideCircle = insideCircle or ToRight and ToLeft and ToBottom and ToTop

        #Finding the perimeter of the shapes   
        perim = cv2.arcLength(contour, True)
        perimeters.append(perim)

        #if we found that this contour is a circle then the number of sides is 1
        if insideCircle:
            numberOfSides.append(1)

        #use the number of corners found in the contours to determine how many
        #sides it has
        else:
            corner = cv2.approxPolyDP(contour, 0.01 * perim, True)
            corners.append(corner)
            numberOfSides.append(len(corner))
        #print(numberOfSides)
    count = count + 1

#finding angles in shape
for shape in range(0, len(corners)):
    angles.append([])
    sidesDividedByPerimeter.append([])
    for corner in range(0, len(corners[shape])):
        # 3 vertices we need to find the angle at vertice b

        ax = corners[shape][corner % len(corners[shape])][0][0]
        ay = corners[shape][corner % len(corners[shape])][0][1]

        bx = corners[shape][(corner + 1) % len(corners[shape])][0][0]
        by = corners[shape][(corner + 1) % len(corners[shape])][0][1]

        cx = corners[shape][(corner + 2) % len(corners[shape])][0][0]
        cy = corners[shape][(corner + 2) % len(corners[shape])][0][1]

        #print ("A: ", ax, ", ", ay, "\tB: ", bx, ", ", by, "\tC: ", cx, ", ", cy)
        dirBAx = ax - bx
        dirBAy = ay - by

        dirBCx = cx - bx
        dirBCy = cy - by

        #do dot product and find angle in degrees
        dot = dirBAx * dirBCx + dirBAy * dirBCy
        lengthBC = math.sqrt(dirBCx * dirBCx + dirBCy * dirBCy)
        lengthBA = math.sqrt(dirBAx * dirBAx + dirBAy * dirBAy)
        angle = math.acos(dot / (lengthBC * lengthBA))
        angle = angle * 180 / math.pi
        angles[shape].append(angle)
        sidesDividedByPerimeter[shape].append(lengthBC / perimeters[shape])
        #print(lengthBC / perimeters[shape])
        #print(angle)

#finding max of all angles in each shape
for shape in range(0, len(angles)):
    largestAngles.append(np.amax(angles[shape]))
#print(largestAngles)

#if len(approx) == 16:
#        cv2.drawContours(img, [contours[0]], 0, (0,0,255), -1)

#Calculating the standard deviation of the sides divided by the perimeter
#print("Standard Devs")
for shape in range(0, len(sidesDividedByPerimeter)):
    standarddevPerim = statistics.stdev(sidesDividedByPerimeter[shape])
    #Caluclating the standard deviation of the angles of each shape
    standarddevAngle = statistics.stdev(angles[shape])
    standardDeviationsPerimeter.append(standarddevPerim)
    standardDeviationsAngles.append(standarddevAngle)


for shape in range(0, len(sidesDividedByPerimeter)):
    featureVectors.append([])
    featureVectors[shape].append(numberOfSides[shape])
    featureVectors[shape].append(standardDeviationsPerimeter[shape])
    featureVectors[shape].append(standardDeviationsAngles[shape])
    featureVectors[shape].append(largestAngles[shape])

print(featureVectors)

And featureVector prints out this:

[[4, 0.001743713493735165, 0.6497055601752815, 90.795723552739275], 
[4, 0.0460937435599832, 0.19764217920409227, 90.204147248752378], 
[1, 0.001185534503063044, 0.3034913722821194, 60.348908179729023], 
[1, 0.015455289770298222, 0.8380914254332884, 109.02120657826231], 
[3, 0.0169961646358455, 41.36919146079211, 136.83829993466398]]

However there should be 7 shapes.

What i cant figure out is where to append blank values for the 2nd/3rd/4th feature for a circle and allow the program to continue running. It currently appears to be giving the 2nd/3rd/4th value from the next two shapes to the circles.

Aucun commentaire:

Enregistrer un commentaire