Example #1
0
def loadBalloonsFromSVG(filename, foldername, tagName, attributeClass, verbose):
    polygons = []
    contours = []
    #w, h = imgSize
    nbContour = 0
    #nbMatch = 0
    #nbSmooth = 0
    #nbWavy = 0
    #nbZigzag = 0
    #nbNoTMatch = 0
    sumMeanHeight = 0
    #s = filepath.split(os.sep)
    #filepath = s[len(s) - 1]

    if verbose:
        img = cv2.imread('/media/Donnees/DATA/DATASET/eBDtheque_100/'+filename.split('.')[0]+'.jpg')
    
    if not filename.endswith('svg'):
        print 'ERROR in loadBalloonsFromSVG: not an SVG file (',filename,')'
        return

    w, h = toolbox_svg.getImageSizeFromSvg(foldername+filename)
    xmldoc = parse(foldername+filename)
    itemlist = xmldoc.getElementsByTagName(tagName) # find all polygon elements
    
    #contoursSVGImg = numpy.zeros([h, w], numpy.uint8)
    #defectsImg = numpy.zeros([h, w], numpy.uint8)
    itemListIterator = 0
    for item in itemlist :
        # process only polygon that are in a svg tag with class=Balloon
        if item.parentNode.attributes['class'].value == attributeClass:                
            
            points = item.attributes['points'].value
            coords = points.split(' ')

            balloonType = 'unknown'
            #if loadTypeFromText:
            #    balloonType = getTypeFromTextFile(filepath.split('.')[0]+'.txt', itemListIterator)
            #    itemListIterator += 1
            #else:
            #    for child in item.childNodes:
            #        if child.nodeType == 1:
            #            balloonType = child.attributes['shape'].value
                        
            #if balloonType == 'unknown' or balloonType == '':
            #    print 'WARNING: unknwon or empty balloon type in',filepath,
            
            
            #Convert point list into an array
            contour = toolbox_svg.svgList2NumpyArray(coords)            
                                                                          
            #Barycenter
            M = cv2.moments(contour)
            try:
                c_x = int(M['m10']/M['m00'])
                c_y = int(M['m01']/M['m00'])
            except:
                print 'ERROR: division by zero in barycenter of contour',contour,'in file',filename,'(coords=',coords,')'
                c_x = 0
                c_y = 0
            
            #Spacial position of the balloon  
            t, b, l, r = coord2box(coords, w, h)#xList, yList, w, h )   
            #coef = 100 / max((b-t),(r-l))# / 100.0
            #contourDiv = rint(contour/coef).astype(int) #divide the contour by a scalar and keep the closest integer value. Then convert as integer
            #print 'coef=',coef,'contour=',contour,'contourDiv=',contourDiv
                
            
            #Draw contour to equalize the number of points 
            newDrawing = numpy.zeros([h, w], numpy.uint8)
            cv2.drawContours(newDrawing,[contour],0,(100,50,255),0)
                    
            #Normalize and detect again contour (spatial lost)
            newContours, hierachy = cv2.findContours(newDrawing.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)              
            newContour = newContours[0]

            #Get tail direction and position fro metadata tag
            tailDirection = item.childNodes[1].attributes['tailDirection'].value
            tailTip = item.childNodes[1].attributes['tailTip'].value
            
            #if verbose:
            #    cv2.circle(img,(c_x, c_y),1,[255,0,0],2) #plot barycenter for thumbnail
            #    cv2.circle(img,tuple(newContour[0][0]),1,[0,255,0],2) #plot starting point for thumbnail
                
            if verbose:
                #Draw contour
                cv2.drawContours(img,[newContour],0,(255,0,0),1) #RGB
                #Draw position line
                if tailTip != '':
                    x1, y1 = tailTip.split(',')
                    cv2.circle(img, (int(x1), int(y1)), 5, (0,255,0), 2)

                thumbnail = img[t:b, l:r]
            else:
                thumbnail = None

            #New MyBalloon object
            myBalloon = class_balloon.MyBalloon(points, [c_x, c_y], newContour, balloonType, [t, b, l, r], thumbnail, [c_x, c_y], tailTip, tailDirection )

            #Add new contour to the contour list
            contours.append(myBalloon)          
    
            del contour
    
            #if verbose:
                #Draw contour for later use
                #cv2.drawContours(img,[newContour],0,(255,0,0),1) #RGB
       
            nbContour += 1     
            
    return contours
Example #2
0
def evaluateTailExtraction(f, inputSVGGroundtruth, inputSVGDetection, outputFolderPNG, verbose):
    """
        Evaluate the tail detection using recall and precision
    """

    #Load balloons detections and ground truth
    balloonsFromExtractor = loadBalloonsFromSVG(f, inputSVGDetection, 'polygon', 'Balloon', verbose)
    balloonsFromGroundtruth = loadBalloonsFromSVG(f, inputSVGGroundtruth, 'polygon', 'Balloon', verbose)

    width, height = toolbox_svg.getImageSizeFromSvg(inputSVGGroundtruth+f)
    matchList = []
    precision = 0
    recall = 0
    nbWrong = 0
    found = 0
    nb = 0
    for balloonExt in balloonsFromExtractor:
        #Ckecking
        #assert balloonExt.tailDirection != '' , 'ERROR: tail direction is not set for balloon'+str(balloonExt.BdB)+' in file '+f
        if balloonExt.tailDirection != '':
            print '\nERROR: tail direction is not set for balloon'+str(balloonExt.BdB)+' in file '+f

        #Find corresponding balloon with the biggest sharing intersection
        balloonMatchGT = getMaxMatchV2(width, height, balloonExt, balloonsFromGroundtruth, outputFolderPNG, verbose)
        
        if balloonMatchGT == None:
            if verbose:
                print '\nERROR: balloon match not found (no evaluation then) for '+str(balloonExt.BdB)+' in '+f
            continue
        pointList = balloonMatchGT.getPoints()
        if pointList in matchList:            
            if verbose:
                print 'ERROR duplicate point list (no evaluation then) in',inputSVGDetection+f,'(',pointList,')'
            continue
        matchList.append(pointList)
        
        #Position (recall)
        # try:
        if balloonMatchGT.tailCoordinates == balloonExt.tailCoordinates:
            recall += 1 #if both have the same value (none OR '' OR X,Y coordinates)
        elif balloonMatchGT.tailCoordinates == '' or balloonExt.tailCoordinates == '':
            recall += 0 #if only one is empty
        else:
            try:
                if (int(balloonMatchGT.tailCoordinates[0]) - 10 < int(balloonExt.tailCoordinates[0]) < int(balloonMatchGT.tailCoordinates[0]) + 10) and (int(balloonMatchGT.tailCoordinates[1]) - 10 < int(balloonExt.tailCoordinates[1]) < int(balloonMatchGT.tailCoordinates[1]) + 10):
                    recall += 1
                elif (int(balloonMatchGT.tailCoordinates[0]) - 20 < int(balloonExt.tailCoordinates[0]) < int(balloonMatchGT.tailCoordinates[0]) + 20) and (int(balloonMatchGT.tailCoordinates[1]) - 20 < int(balloonExt.tailCoordinates[1]) < int(balloonMatchGT.tailCoordinates[1]) + 20):
                    recall += 0.5
            except:
                recall += 0
                print 'WARNING: set recall=0 for',balloonExt.tailCoordinates,'and',balloonMatchGT.tailCoordinates,'for balloon',balloonExt.BdB,'in',f
        
        #Direction (precision)
        if balloonExt.tailDirection == balloonMatchGT.tailDirection:
            precision += 1
            found = 1
        elif balloonExt.tailDirection == 'S' and (balloonMatchGT.tailDirection == 'SE' or balloonMatchGT.tailDirection == 'SW'):
            precision += 0.5
            found = 0.5
        elif balloonExt.tailDirection == 'SE' and (balloonMatchGT.tailDirection == 'S' or balloonMatchGT.tailDirection == 'E'):
            precision += 0.5
            found = 0.5
        elif balloonExt.tailDirection == 'E' and (balloonMatchGT.tailDirection == 'SE' or balloonMatchGT.tailDirection == 'NE'):
            precision += 0.5
            found = 0.5
        elif balloonExt.tailDirection == 'NE' and (balloonMatchGT.tailDirection == 'S' or balloonMatchGT.tailDirection == 'N'):
            precision += 0.5
            found = 0.5
        elif balloonExt.tailDirection == 'N' and (balloonMatchGT.tailDirection == 'NE' or balloonMatchGT.tailDirection == 'NW'):
            precision += 0.5
            found = 0.5
        elif balloonExt.tailDirection == 'NW' and (balloonMatchGT.tailDirection == 'N' or balloonMatchGT.tailDirection == 'W'):
            precision += 0.5
            found = 0.5
        elif balloonExt.tailDirection == 'W' and (balloonMatchGT.tailDirection == 'NW' or balloonMatchGT.tailDirection == 'SW'):
            precision += 0.5
            found = 0.5
        elif balloonExt.tailDirection == 'SW' and (balloonMatchGT.tailDirection == 'W' or balloonMatchGT.tailDirection == 'S'):
            precision += 0.5
            found = 0.5    
        else:
            precision += 0#nbWrong += 1
            found = 0

        if verbose:
            if found == 1:
                print 'Matching',balloonExt.tailDirection,'for',balloonExt.BdB,'and',balloonMatchGT.BdB
            elif found == 0.5:
                print 'Found 50%',balloonExt.tailDirection,'!=',balloonMatchGT.tailDirection ,'between',balloonExt.BdB,'and', balloonMatchGT.BdB,'in',f
                plt.figure()
                plt.imshow(balloonExt.thumbnail)
                plt.show()
            else:
                print 'Found 0%',balloonExt.tailDirection,'!=',balloonMatchGT.tailDirection ,'between',balloonExt.BdB,'and', balloonMatchGT.BdB,'in',f
                plt.figure()
                plt.imshow(balloonExt.thumbnail)
                plt.show()
        
            

        nb += 1

    #Get number of balloons
    nbBalloonsFromExtractor = len(balloonsFromExtractor)
    nbBalloonsFromGroundtruth = len(balloonsFromGroundtruth)

    #IF no balloon to find and no balloon found then return max score
    if nbBalloonsFromExtractor == 0 and nbBalloonsFromGroundtruth == 0:
        return 1,1,1
    else:
        #Avoid division by zero
        if nbBalloonsFromGroundtruth == 0:
            nbBalloonsFromGroundtruth = 1
        elif nbBalloonsFromExtractor == 0:
            nbBalloonsFromExtractor = 1
        return float(recall)/nbBalloonsFromGroundtruth,float(precision)/nbBalloonsFromGroundtruth, nbBalloonsFromExtractor #return recall, precision