def getModelPointsAutoWhole(personId):
    image = rg.readRadioGraph(personId)
    sumScrs = 0
    avgTeeth = np.zeros((main.nbLandmarks, main.toothIds.shape[0], 2))
    corrLM = np.zeros((main.nbLandmarks, main.toothIds.shape[0], 2))
    
    for templId in range(14):
        # get the template
        templImg, templLM = mt.getTemplate(templId, main.toothIds)
        # match the template
        (x,y), scale, scr = mt.matchTemplate(image, templImg)
        # translate the template landmarks
        for i in range(main.toothIds.shape[0]):
            corrLM[:,i,:] = procru.scaleMatrixForPerson(templLM[:,i,:], scale)
            corrLM[:,i,:] = procru.translateMatrixForPerson(corrLM[:,i,:], np.array([[x],[y]]))
        # add the translated landmarks to the average tooth with weight = scr
        avgTeeth = avgTeeth + scr**main.templ_scr_loyalty*corrLM
        # update the sum of all scores
        sumScrs = sumScrs + scr**main.templ_scr_loyalty
        
    avgTeeth = avgTeeth/sumScrs

    #for i in range(8):
    #    cv2.polylines(image, np.int32([avgTeeth[:,i,:]]), True, 255)
    #main.showScaled(image, 0.6, 'automatic initialisation', True)
        
    return avgTeeth
def testMatchTemplate():
    for personId in range(14, 30):
        image = rg.readRadioGraph(personId)

        chosenScr = 0
        for templId in range(14):
            template = getTemplate(templId, np.array(range(8)))
            (x, y), scale, scr = matchTemplate(image, template[0])
            if scr > chosenScr:
                chosenScr = scr
                chosenX = x
                chosenY = y
                chosenTemplate = template
                chosenTemplId = templId

        print(personId, chosenTemplId)

        main.showScaled(template[0], 0.66, 'template', True)
        main.showScaled(templFilter(image), 0.66, 'image', True)

        combined = image.copy()
        #combined[x:x+template[0].shape[0], y:y+template[0].shape[1]] = template[0]
        cv2.circle(combined, (y, x), 3, 128, thickness=-1)
        #main.showScaled(combined, 0.66, 'combined', False)

        init_image = image.copy()
        for toothId in range(8):
            init_points = procru.translateMatrixForPerson(
                chosenTemplate[1][:, toothId, :],
                np.array([[chosenX], [chosenY]]))
            cv2.polylines(init_image, np.int32([init_points]), True, 255)
        cv2.imshow('init_image', init_image)
        main.showScaled(init_image, 0.66, 'init_image', True)
def getTemplate(personId, toothIds, Delta=15):
    # read landmarks and image
    landmarks = lm.readLandmarksOfPersonAndTeeth(personId, toothIds)
    image = rg.readRadioGraph(personId)

    # crop image to box around landmarks
    minX = np.min(landmarks[:, :, 0]) - Delta
    maxX = np.max(landmarks[:, :, 0]) + Delta
    minY = np.min(landmarks[:, :, 1]) - Delta
    maxY = np.max(landmarks[:, :, 1]) + Delta
    image = image[minY:maxY, minX:maxX]

    # translate landmarks to the coordinate system of the cropped image
    for i in range(toothIds.shape[0]):
        landmarks[:, i, :] = procru.translateMatrixForPerson(
            landmarks[:, i, :], np.array([[-minX], [-minY]]))

    return image, landmarks
def getModelPointsManually(personId, toothId):
    image = rg.readRadioGraph(personId)
    image = cv2.resize(image, (0,0), fx=main.windowscale, fy=main.windowscale)
    
    cv2.namedWindow('points')
    cv2.cv.SetMouseCallback('points', mouseCallback, image)
    
    cv2.imshow('points', image)
    
    print 'Click initial points for tooth #' + str(toothId)
    
    cv2.waitKey(0)
    
    pointsLength = len(xPoints)
    points = np.zeros((pointsLength, 2))
    for i in range(pointsLength):
        points[i,0] = xPoints[i]/main.windowscale
        points[i,1] = yPoints[i]/main.windowscale
        
    print points
    return points
def getModelPointsAutoParts(personId):
    debugMBB = True
    image = rg.readRadioGraph(personId)
    
    # Choice of search area around the upper resp. lower inscisors within (preprocessed) image, for finding parts (upper and lower part) in an image
    ## these coordinates are in the not-preprocessed images, format Part x {UpperLeft, LowerRight} x Dim
    partSearchAreas = np.array([[[1190,550], [1830,1120]],
                                [[1210,880], [1810,1400]]])
    ## correct for preprocessing of images
    partSearchAreas[:,:,0] = partSearchAreas[:,:,0] - np.ones_like(partSearchAreas[:,:,0])*rg.cropX[0]
    partSearchAreas[:,:,1] = partSearchAreas[:,:,1] - np.ones_like(partSearchAreas[:,:,1])*rg.cropY[0]
    
    if debugMBB:
        debugImage = image.copy()
        cv2.rectangle(debugImage, (partSearchAreas[0,0,0], partSearchAreas[0,0,1]), (partSearchAreas[0,1,0], partSearchAreas[0,1,1]), 255)
        cv2.rectangle(debugImage, (partSearchAreas[1,0,0], partSearchAreas[1,0,1]), (partSearchAreas[1,1,0], partSearchAreas[1,1,1]), 255)
        #main.showScaled(debugImage, 0.6, 'debugImage', True)
        
        
    ## get search images (image cropped to resp. search area)
    upperImage = image.copy()[partSearchAreas[0,0,1]:partSearchAreas[0,1,1], partSearchAreas[0,0,0]:partSearchAreas[0,1,0]]
    lowerImage = image.copy()[partSearchAreas[1,0,1]:partSearchAreas[1,1,1], partSearchAreas[1,0,0]:partSearchAreas[1,1,0]]
    
    sumUpScrs = 0
    sumLowScrs = 0
    avgUpTeeth = np.zeros((main.nbLandmarks, 4, 2))
    avgLowTeeth = np.zeros((main.nbLandmarks, 4, 2))
    upLMs = np.zeros((main.nbLandmarks, 4, 2))
    lowLMs = np.zeros((main.nbLandmarks, 4, 2))
    
    for templId in range(14):
        ## get templates for these parts
        upTemplImg, upTemplLMs = mt.getTemplate(templId, np.array(range(4)), Delta=0)
        lowTemplImg, lowTemplLMs = mt.getTemplate(templId, np.array(range(4,8)), Delta=0)
        ## match templates
        (upX,upY), upScale, upScore = mt.matchTemplate(upperImage, upTemplImg)
        (lowX,lowY), lowScale, lowScore = mt.matchTemplate(lowerImage, lowTemplImg)
        ## avoid deviding by zero when loyalty to best fit is high
        if upScore == 0 : upScore = 1
        if lowScore == 0 : lowScore = 1
        # translate and scale the found landmarks
        for toothIdy in range(4):
            upLMs[:,toothIdy,:] = procru.scaleMatrixForPerson(upTemplLMs[:,toothIdy,:], upScale)
            upLMs[:,toothIdy,:] = procru.translateMatrixForPerson(upLMs[:,toothIdy,:], np.array([[upX + partSearchAreas[0,0,0]],
                                                                                                 [upY + partSearchAreas[0,0,1]]]))
            lowLMs[:,toothIdy,:] = procru.scaleMatrixForPerson(lowTemplLMs[:,toothIdy,:], lowScale)
            lowLMs[:,toothIdy,:] = procru.translateMatrixForPerson(lowLMs[:,toothIdy,:], np.array([[lowX + partSearchAreas[1,0,0]],
                                                                                                   [lowY + partSearchAreas[1,0,1]]]))
        # updat the average teeth
        avgUpTeeth = avgUpTeeth + upScore**main.templ_scr_loyalty*upLMs
        avgLowTeeth = avgLowTeeth + lowScore**main.templ_scr_loyalty*lowLMs
            
        # update the sum of all scores
        sumUpScrs = sumUpScrs + upScore**main.templ_scr_loyalty
        sumLowScrs = sumLowScrs + lowScore**main.templ_scr_loyalty
    
    # merge parts into one matrix
    avgTeeth = np.zeros((main.nbLandmarks, 8, 2))
    avgTeeth[:,0:4,:] = avgUpTeeth/sumUpScrs
    avgTeeth[:,4:8,:] = avgLowTeeth/sumLowScrs
    
    return avgTeeth
def getModelPointsAutoTeeth(personId):
    debugMBB = True
    image = rg.readRadioGraph(personId)
    
    # Choice of search area around the upper resp. lower inscisors within (preprocessed) image, for finding parts (upper and lower part) in an image
    ## these coordinates are in the not-preprocessed images, format Part x {UpperLeft, LowerRight} x Dim
    partSearchAreas = np.array([[[1190,550], [1830,1120]],
                                [[1210,880], [1810,1400]]])
    ## correct for preprocessing of images
    partSearchAreas[:,:,0] = partSearchAreas[:,:,0] - np.ones_like(partSearchAreas[:,:,0])*rg.cropX[0]
    partSearchAreas[:,:,1] = partSearchAreas[:,:,1] - np.ones_like(partSearchAreas[:,:,1])*rg.cropY[0]
    
    if debugMBB:
        debugImage = image.copy()
        cv2.rectangle(debugImage, (partSearchAreas[0,0,0], partSearchAreas[0,0,1]), (partSearchAreas[0,1,0], partSearchAreas[0,1,1]), 255)
        cv2.rectangle(debugImage, (partSearchAreas[1,0,0], partSearchAreas[1,0,1]), (partSearchAreas[1,1,0], partSearchAreas[1,1,1]), 255)
        #main.showScaled(debugImage, 0.6, 'debugImage', True)
    
    # 1 FIND BOUNDING BOXES OF PARTS IN SEARCH AREA
    
    if debugMBB:
        '''
        avgUpTeeth = np.zeros((main.nbLandmarks, 4, 2))
        avgLowTeeth = np.zeros((main.nbLandmarks, 4, 2))
        '''
    ## get search images (image cropped to resp. search area)
    upperImage = image.copy()[partSearchAreas[0,0,1]:partSearchAreas[0,1,1], partSearchAreas[0,0,0]:partSearchAreas[0,1,0]]
    lowerImage = image.copy()[partSearchAreas[1,0,1]:partSearchAreas[1,1,1], partSearchAreas[1,0,0]:partSearchAreas[1,1,0]]
    
    upMBBUL = np.zeros((2,))
    upMBBLR = np.zeros((2,))
    lowMBBUL = np.zeros((2,))
    lowMBBLR = np.zeros((2,))
    
    sumUpScrs = 0
    sumLowScrs = 0
    
    for templId in range(14):
        ## get templates for these parts
        upTemplImg, upTemplLMs = mt.getTemplate(templId, np.array(range(4)), Delta=0)
        lowTemplImg, lowTemplLMs = mt.getTemplate(templId, np.array(range(4,8)), Delta=0)
        ## match templates
        (upX,upY), upScale, upScore = mt.matchTemplate(upperImage, upTemplImg)
        (lowX,lowY), lowScale, lowScore = mt.matchTemplate(lowerImage, lowTemplImg)
        ## avoid deviding by zero
        if upScore == 0 : upScore = 1
        if lowScore == 0 : lowScore = 1
        ## calculate matched bounding box (MBB) corners, relative to the preprocessed image (image)
        upMBBUL = upMBBUL + (upScore**main.templ_scr_loyalty)*( np.array([upX,upY]) + partSearchAreas[0,0,:] )
        upMBBLR = upMBBLR + (upScore**main.templ_scr_loyalty)*( np.array([upX,upY]) + partSearchAreas[0,0,:]
                                                                          + np.array([upTemplImg.shape[1]*upScale,
                                                                                      upTemplImg.shape[0]*upScale])
                                                               )
        lowMBBUL = lowMBBUL + (lowScore**main.templ_scr_loyalty)*( np.array([lowX,lowY]) + partSearchAreas[1,0,:] )
        lowMBBLR = lowMBBLR + (lowScore**main.templ_scr_loyalty)*( np.array([lowX,lowY]) + partSearchAreas[1,0,:]
                                                                             + np.array([lowTemplImg.shape[1]*lowScale,
                                                                                         lowTemplImg.shape[0]*lowScale])
                                                                  )
            
        # update the sum of all scores
        sumUpScrs = sumUpScrs + upScore**main.templ_scr_loyalty
        sumLowScrs = sumLowScrs + lowScore**main.templ_scr_loyalty

    ## calculate average MBB and correct for search area
    upMBBUL = np.int32(upMBBUL/sumUpScrs)
    upMBBLR = np.int32(upMBBLR/sumUpScrs)
    lowMBBUL = np.int32(lowMBBUL/sumLowScrs)
    lowMBBLR = np.int32(lowMBBLR/sumLowScrs)
    
    #if debugMBB:
        #cv2.rectangle(debugImage, (upMBBUL[0], upMBBUL[1] ), (upMBBLR[0], upMBBLR[1] ), 255)
        #cv2.rectangle(debugImage, (lowMBBUL[0],lowMBBUL[1]), (lowMBBLR[0],lowMBBLR[1]), 255)
    
    #2 FIND LOCATION OF TEETH IN FOUND BOUNDING BOXES
    
    # Choise of search space for each inscisor
    ## the numbers in this table are the relative, horizontal borders of
    ##   the search area within the matched bounding box of the resp. part, format Tooth x {LeftBorder, RightBorder}
    searchBoxBorders = np.array([[0.0,0.3], [0.2,0.6], [0.4,0.8], [0.7,1.0],
                                 [0.0,0.3], [0.2,0.6], [0.4,0.8], [0.7,1.0]])
    '''
    searchBoxBorders = np.array([[0.0,0.25], [0.25,0.5], [0.5,0.75], [0.75,1.0],
                                 [0.0,0.25], [0.25,0.5], [0.5,0.75], [0.75,1.0]])
    '''
    ## widths of the parts
    upDeltaX = upMBBLR[0]-upMBBUL[0]
    lowDeltaX = lowMBBLR[0]-lowMBBUL[0]
    
    ## Choice of extra space to add around the searchboxes
    extraSearchSpace = 30
    
    searchBoxes = np.zeros((8,2,2)) # Tooth x {UpperLeft, LowerRight} x Dim
    ## calculate search boxes for teeth
    for toothIdx in range(4):
        searchBoxes[toothIdx,0,0] = upMBBUL[0] + upDeltaX*searchBoxBorders[toothIdx,0] - extraSearchSpace # upper part, upper left x
        searchBoxes[toothIdx,0,1] = upMBBUL[1] - extraSearchSpace # upper part, upper left y
        searchBoxes[toothIdx,1,0] = upMBBUL[0] + upDeltaX*searchBoxBorders[toothIdx,1] + extraSearchSpace # upper part, lower right x
        searchBoxes[toothIdx,1,1] = upMBBLR[1] + extraSearchSpace # upper part, lower right y
        if debugMBB : cv2.rectangle(debugImage, (np.int(searchBoxes[toothIdx,0,0]), np.int(searchBoxes[toothIdx,0,1])),
                                  (np.int(searchBoxes[toothIdx,1,0]), np.int(searchBoxes[toothIdx,1,1])), 255)
    for toothIdx in range(4,8):
        searchBoxes[toothIdx,0,0] = lowMBBUL[0] + lowDeltaX*searchBoxBorders[toothIdx,0] - extraSearchSpace # lower part, upper left x
        searchBoxes[toothIdx,0,1] = lowMBBUL[1] - extraSearchSpace # lower part, upper left y
        searchBoxes[toothIdx,1,0] = lowMBBUL[0] + lowDeltaX*searchBoxBorders[toothIdx,1] + extraSearchSpace # lower part, lower right x
        searchBoxes[toothIdx,1,1] = lowMBBLR[1] + extraSearchSpace # lower part, lower right y
        if debugMBB : cv2.rectangle(debugImage, (np.int(searchBoxes[toothIdx,0,0]), np.int(searchBoxes[toothIdx,0,1])),
                                  (np.int(searchBoxes[toothIdx,1,0]), np.int(searchBoxes[toothIdx,1,1])), 255)
    
    avgTeeth = np.zeros((main.nbLandmarks, 8, 2))
    for toothId in range(8):
        searchImage = image.copy()[searchBoxes[toothId,0,1]:searchBoxes[toothId,1,1],searchBoxes[toothId,0,0]:searchBoxes[toothId,1,0]]
        sumScrs = 0
        corrLM = np.zeros((main.nbLandmarks, 2))
        
        #main.showScaled(searchImage, 1.5, 'searchImage', True)
            
        for templId in range(14):
            templImg, templLMs = mt.getTemplate(templId, np.array([toothId]), Delta = 0)
            
            #main.showScaled(templImg, 1.5, 'template', True)
            
            (x,y), scale, scr = mt.matchTemplate(searchImage, templImg)
            # translate the template landmarks
            corrLM = procru.scaleMatrixForPerson(templLMs[:,0,:], scale)
            corrLM = procru.translateMatrixForPerson(corrLM, np.array([[searchBoxes[toothId,0,0]],[searchBoxes[toothId,0,1]]]))
            corrLM = procru.translateMatrixForPerson(corrLM, np.array([[x],[y]]))
            # add the translated landmarks to the average tooth with weight = scr
            avgTeeth[:,toothId,:] = avgTeeth[:,toothId,:] + scr**main.templ_scr_loyalty*corrLM
            # update the sum of all scores
            sumScrs = sumScrs + scr**main.templ_scr_loyalty
            
        avgTeeth[:,toothId,:] = avgTeeth[:,toothId,:]/sumScrs
      
        if debugMBB : cv2.polylines(debugImage, np.int32([avgTeeth[:,toothId,:]]), True, 255)
    #if debugMBB : main.showScaled(debugImage, 0.6, 'hierarchical initialisation', True)

    return avgTeeth
'''
def getVerticalMiddleOfTeeth(image):
    y_min = np.argmin(np.average(image, 1))
    line = np.int32([np.array([[0,y_min],[image.shape[1]-1, y_min]])])
    
    cv2.polylines(image, line, False, 255)
    
    cv2.imshow('result', image)
    cv2.waitKey(0)

'''
MAIN PROGRAM
'''
if __name__ == '__main__':
    for personId in range(14,30):
        imageWhole = rg.readRadioGraph(personId)
        imageParts = imageWhole.copy()
        imageTeeth = imageWhole.copy()
        
        resultWhole = getModelPointsAutoWhole(personId)
        resultParts = getModelPointsAutoParts(personId)
        resultTeeth = getModelPointsAutoTeeth(personId)
        
        for toothId in range(8):
            cv2.polylines(imageWhole, np.int32([resultWhole[:,toothId,:]]), True, 255)
            cv2.polylines(imageParts, np.int32([resultParts[:,toothId,:]]), True, 255)
            cv2.polylines(imageTeeth, np.int32([resultTeeth[:,toothId,:]]), True, 255)
        '''    
        main.showScaled(imageWhole, 0.6, 'whole', False)
        main.showScaled(imageParts, 0.6, 'parts', False)
        main.showScaled(imageTeeth, 0.6, 'teeth', True)
示例#8
0
def findSegments():
    # load training radiographs
    images = rg.readRadiographs(trainingPersonIds)
    if debugFB: print 'DB: Training radiographs loaded'

    for personToFitId in personToFitIds:
        # load radiograph to determine segments for
        imageToFit = rg.readRadioGraph(personToFitId)
        if debugFB:
            print 'DB: Radiograph to fit (#' + str(personToFitId +
                                                   1) + ') loaded'

        contourImage = imageToFit.copy()
        segmentsImage = np.zeros_like(np.array(imageToFit))

        if autoInitPoints:
            init_points = ip.getModelPointsAutoWhole(personToFitId)

        for i in range(toothIds.shape[0]):
            toothId = toothIds[i]

            # Read data (images and landmarks)
            landmarks = lm.readLandmarksOfTooth(toothId, trainingPersonIds)
            if debugFB:
                print '   DB: Landmarks loaded for tooth #' + str(toothId + 1)

            # Initialization of mean vector (xStriped), covariance matrix, x-vector, x-striped-vector (mean), eigenvectors (P) and eigenvalues.
            processedLandmarks = procrustes.procrustesMatrix(landmarks, 100)
            if debugFB:
                print '   DB: Procrustes ready for tooth #' + str(toothId + 1)
            pcMean, pcEigv = cv2.PCACompute(
                np.transpose(stackPoints(processedLandmarks)))
            if debugFB: print '   DB: PCA ready for tooth #' + str(toothId + 1)
            xStacked = xStriped = np.transpose(pcMean)

            covar, _ = cv2.calcCovarMatrix(
                stackPoints(processedLandmarks), cv2.cv.CV_COVAR_SCRAMBLED
                | cv2.cv.CV_COVAR_SCALE | cv2.cv.CV_COVAR_COLS)
            eigval = np.sort(np.linalg.eigvals(covar), kind='mergesort')[::-1]

            # Number of modes
            coverage = 0
            nbModes = 0
            eigval_total = np.sum(eigval)
            for value in eigval:
                coverage += value / eigval_total
                nbModes += 1
                if coverage >= 0.99:
                    break

            P = np.transpose(pcEigv[:nbModes])  # normalized
            eigval = eigval[:nbModes]

            # Initialization of the initial points
            if autoInitPoints: X = init_points[:, toothId, :]
            else: X = ip.getModelPointsManually(personToFitId, toothId)

            # Draw the initial points
            initialImage = imageToFit.copy()
            cv2.polylines(initialImage, np.int32([X]), True, 255, thickness=2)
            #showScaled(initialImage, windowscale, 'initial', False)

            # Initialize the model
            directions = profile.getDirections(landmarks)
            model = profile.getModel(images, landmarks, directions, nModel)

            ## Protocol 1: step 1 (initialize shape parameters)
            b = np.zeros((nbModes, 1))
            prev_b = b

            stop = False
            it = 1
            while (not stop):
                # Protocol 2: step 1 (examine region around each point to find best nearby match)
                Y = profile.getNewModelPoints(imageToFit, X, model, nSample)

                # Protocol 2: step 3 = protocol 1

                ## Protocol 1: step 2 (generate model point positions)
                xStacked = xStriped + np.dot(P, b)

                ## Protocol 1: step 3 & 4 (project Y into the model coordinate frame)
                y, translation = procrustes.procrustesTranslateMatrixForPerson(
                    Y)
                scale, rotation = procrustes.alignShapes(
                    unstackPointsForPerson(xStacked), y)
                translation = -translation

                y = procrustes.rotateMatrixForPerson(y, -rotation)
                y = procrustes.scaleMatrixForPerson(y, 1 / scale)

                ## Protocol 1: step 5 --> NOT NEEDED??
                #yStacked = stackPointsForPerson(y)
                #yStacked = yStacked/np.dot(np.transpose(yStacked), xStriped)
                #y = unstackPointsForPerson(yStacked)

                ## Protocol 1: step 6 (update model parameters)
                b = np.dot(np.transpose(P),
                           (stackPointsForPerson(y) - xStriped))

                # Protocol 2: step 3 (apply constraints to b)
                #mahalonobis = np.sqrt(np.sum(b**2)/np.sum(eigval))
                #if mahalonobis > 3.0:
                #   b = b*(3.0/mahalonobis)

                for i in range(b.shape[0]):
                    if np.abs(b[i, 0]) > 3 * np.sqrt(eigval[i]):
                        b[i, 0] = np.sign(b[i, 0]) * 3 * np.sqrt(eigval[i])

                # Calculate difference with previous result
                # and stop iterating after a certain threshold
                differences = prev_b - b
                prev_b = b

                stop = True
                for diff in differences:
                    if np.abs(diff) > 0.01:
                        stop = False

                it += 1

            if debugFB:
                print '   DB: Tooth #' + str(
                    toothId + 1) + ' finished in ' + str(it) + ' iterations.'

            # Draw the model on the radiograph
            x = unstackPointsForPerson(xStriped + np.dot(P, b))
            X = procrustes.rotateMatrixForPerson(x, rotation)
            X = procrustes.scaleMatrixForPerson(X, scale)
            X = procrustes.translateMatrixForPerson(X, translation)

            cv2.polylines(contourImage, np.int32([X]), True, 255, thickness=2)
            #showScaled(contourImage, windowscale, 'contours', True)

            cv2.fillPoly(segmentsImage, np.int32([[X]]), 128)
            #showScaled(segmentsImage, windowscale, 'segments', True)

        #cv2.imwrite('C:/Users/samue_000/Desktop/' + str(personToFitId+1) + 'i.jpg', initialImage)
        #cv2.imwrite('C:/Users/samue_000/Desktop/' + str(personToFitId+1) + 'c.jpg', contourImage)
        #cv2.imwrite('C:/Users/samue_000/Desktop/' + str(personToFitId+1) + 's.jpg', segmentsImage)
        showScaled(contourImage, windowscale, 'contours', True)

        print 'DB: Radiograph #' + str(personToFitId + 1) + ' is segmented.'
def testMatchTemplateFilter():
    for personId in range(14, 30):
        # WITHOUT FILTER
        image = rg.readRadioGraph(personId)

        sumScrs = 0
        avgTeeth = np.zeros((main.nbLandmarks, main.toothIds.shape[0], 2))
        corrLM = np.zeros((main.nbLandmarks, main.toothIds.shape[0], 2))

        for templId in range(14):
            # get the template
            templImg, templLM = getTemplate(templId, np.array(range(8)))
            # match the template
            (x, y), scale, scr = matchTemplate(image, templImg)
            # translate the template landmarks
            for i in range(main.toothIds.shape[0]):
                toothIdx = main.toothIds[i]
                corrLM[:, toothIdx, :] = procru.scaleMatrixForPerson(
                    templLM[:, toothIdx, :], scale)
                corrLM[:, toothIdx, :] = procru.translateMatrixForPerson(
                    corrLM[:, toothIdx, :], np.array([[x], [y]]))
            # add the translated landmarks to the average tooth with weight = scr
            avgTeeth = avgTeeth + scr**main.templ_scr_loyalty * corrLM
            # update the sum of all scores
            sumScrs = sumScrs + scr**main.templ_scr_loyalty

        avgTeeth = avgTeeth / sumScrs

        init_image = image.copy()
        for toothId in range(8):
            cv2.polylines(init_image, np.int32([avgTeeth[:, toothId, :]]),
                          True, 255)
        main.showScaled(init_image, 0.66, 'without filter', True)

        # WITH FILTER
        image = rg.readRadioGraph(personId)

        sumScrs = 0
        avgTeeth = np.zeros((main.nbLandmarks, main.toothIds.shape[0], 2))
        corrLM = np.zeros((main.nbLandmarks, main.toothIds.shape[0], 2))

        for templId in range(14):
            # get the template
            templImg, templLM = getTemplate(templId, np.array(range(8)))
            # match the template
            (x, y), scale, scr = matchTemplate(templFilter(image),
                                               templFilter(templImg))
            # translate the template landmarks
            for i in range(main.toothIds.shape[0]):
                toothIdx = main.toothIds[i]
                corrLM[:, toothIdx, :] = procru.scaleMatrixForPerson(
                    templLM[:, toothIdx, :], scale)
                corrLM[:, toothIdx, :] = procru.translateMatrixForPerson(
                    corrLM[:, toothIdx, :], np.array([[x], [y]]))
            # add the translated landmarks to the average tooth with weight = scr
            avgTeeth = avgTeeth + scr**main.templ_scr_loyalty * corrLM
            # update the sum of all scores
            sumScrs = sumScrs + scr**main.templ_scr_loyalty

        avgTeeth = avgTeeth / sumScrs

        init_image = image.copy()
        for toothId in range(8):
            cv2.polylines(init_image, np.int32([avgTeeth[:, toothId, :]]),
                          True, 255)
        main.showScaled(init_image, 0.66, 'with filter', True)