Пример #1
0
    def _drawTootSethOnImage(self, teethSet, img):
        for i in range(8):
            start = i * 40
            end = start + 40
            tooth = Tooth(teethSet.landmarks[start:end])
            img = self._drawToothOnImage(tooth, img)

        return img
Пример #2
0
    def _fitToothAtMultiResolutionLevel(self, toothIndex,
                                        downscaledRadiographs):

        # Current resolution level
        currentResolutionLevel = self.resolutionLevels - 1
        # print("Downscaled radiographs: " + str(downscaledRadiographs.shape))
        radiograph = downscaledRadiographs[currentResolutionLevel]

        # Get initial model rotations
        initialModelRotation = self.initialRotations[toothIndex]

        # Get the initial model positions
        initialModelPosition = self.initialPositions[toothIndex]
        if initialModelPosition is None:
            # Automatic model initialization not implemented
            return None

        # Get the mean model for the tooth
        statisticalToothModel = self.completeStatisticalModel.getToothModelByIndex(
            toothIndex, deepCopy=False)
        mean = Tooth(statisticalToothModel.getMeanModel())
        eigenvectors = statisticalToothModel.getEigenvectors()
        eigenvalues = statisticalToothModel.getEigenvalues()

        # Initialize Y, this has to be better
        Y = deepcopy(mean)
        Y.rotate(initialModelRotation * (math.pi / 180))
        Y.scale(500 / (2**(self.resolutionLevels - 1)))
        #Y.scale(200)
        Y.translate(initialModelPosition)

        # print("Initialized Y: " + str(Y.getLandmarks()))

        # Init algorithm
        b = 0
        X = mean

        while currentResolutionLevel >= 0:

            X, Y = self._fitSingleToothModel(
                toothIndex, currentResolutionLevel, radiograph, X, Y, b,
                eigenvalues, eigenvectors, mean,
                self.filter_settings[currentResolutionLevel])

            # print("Upscaling")

            # print("Changing resolution level")
            # print("X = " + str(X.getLandmarks()))
            # print("Y = " + str(Y.getLandmarks()))

            currentResolutionLevel -= 1
            if currentResolutionLevel >= 0:
                Y.scale(2)
                radiograph = downscaledRadiographs[currentResolutionLevel]

        return X, Y
    def loadRadiograph(self, radiographID, hasLandmarks=False):
        self.radiographID = radiographID
        self.imgPath = './data/Radiographs/%02d.tif' % (self.radiographID + 1)
        self.image = cv2.cvtColor(cv2.imread(self.imgPath), cv2.COLOR_BGR2GRAY)

        if hasLandmarks:
            for i in range(self.nb_teeth):
                landmark = self.loadLandmark('./data/Landmarks/original/' +
                                             'landmarks%d-%d.txt' %
                                             (radiographID + 1, i + 1))
                self.teeth.append(Tooth(landmark))
        self.teethSet = TeethSet(self.teeth)
Пример #4
0
    def _show_training_result(self):
        mean_tooth = Tooth(to_landmarks_format(self.pca.mean))
        test_tooth = self.data_manager.get_tooth(0, 0, True)
        test_tooth.align(mean_tooth)

        tooth_data = test_tooth.landmarks.flatten()
        projection = self.pca.project(tooth_data)
        reconstructed_data = self.pca.reconstruct(projection)

        shapes = [self.pca.mean, tooth_data, reconstructed_data]
        colors = [[255, 0, 0], [0, 255, 255], [255, 255, 0]]

        self.scene.clear()
        for i, shape in enumerate(shapes):
            tooth = Tooth(to_landmarks_format(shape))
            r, g, b = colors[i]
            tooth.outline_pen = QPen(QColor.fromRgb(r, g, b))
            tooth.outline_pen.setWidthF(0.02)
            tooth.draw(self.scene, True, False, False)

        self._focus_view()
        self.compCountLabel.setText(str(len(self.pca.eigen_values)))
Пример #5
0
    def create(data_manager, components_limit=0):
        '''
        Creates statistical model by aligning models and performing PCA
        :param data_manager: data manager providing training data
        :param components_limit: Limit how much PCA components should be found (0 == all)
        :return: resulting PCA
        '''
        teeth = data_manager.get_all_teeth(True)
        mean_shape = deepcopy(teeth[0])
        assert isinstance(mean_shape, Tooth)
        mean_shape.move_to_origin()
        mean_shape.normalize_shape()

        error = float("inf")
        while error > 0.05:
            meanAcum = np.zeros(mean_shape.landmarks.shape)
            for i in range(0, len(teeth)):
                teeth[i].align(mean_shape)
                meanAcum += teeth[i].landmarks

            new_mean_shape = Tooth(meanAcum / len(teeth))
            new_mean_shape.align(mean_shape)
            error = new_mean_shape.sum_of_squared_distances(mean_shape)

            mean_shape = new_mean_shape

        # Realign all teeth with final mean shape
        for i in range(0, len(teeth)):
            teeth[i].align(mean_shape)

        data = np.zeros((len(teeth), teeth[0].landmarks.size))
        for i, tooth in enumerate(teeth):
            data[i, :] = tooth.landmarks.flatten()

        pca = PCA()
        pca.train(deepcopy(data), components_limit)
        return pca
Пример #6
0
    def drawToothModelOnFrame(self, parent, radiograph_index, meanModels,
                              model_index, modelLocations, rotations):
        img = self.dataHandler.getRadiographs(
            deepCopy=True)[radiograph_index].getImage()
        img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

        for i in range(model_index + 1):
            model = deepcopy(meanModels[i])
            model = Tooth(model)
            rotation = rotations[i]
            theta = rotation * (math.pi / 180)
            model.rotate(theta)
            model.scale(200)
            model.translate(modelLocations[i])
            img = self._drawToothOnImage(model, img)

        return RadiographFrame(parent, img),
Пример #7
0
    def make_step(self, phase=None):
        """
        Performs one step of the active shape model search algorithm, which updates landmarks, projects obtained model
        on the PCA, limits returned eigenvalues and reconstructs the shape again. Current propoerties of this ASM
        instance are updated accordingly.
        :param phase: If None, whole algorithm is performed. If 0, only landmarks will be updated. If 1, everything
                      except landmark updates will be perfomed.
        """
        if phase is None or phase == 0:
            # 1. Sample along normals and find best new position for points by comparing with model
            resolution_level = self.multi_resolution_framework.get_level(self.current_level)
            new_tooth = resolution_level.update_tooth_landmarks(self.current_tooth)
        else:
            new_tooth = deepcopy(self.current_tooth)

        if phase is None or phase == 1:
            # 2. Find new translation, scale, rotation and eigen values
            translation, scale, rotation = new_tooth.align(self.mean_tooth)
            b = self.pca.project(new_tooth.landmarks.flatten())

            # 3. Limit the eigen values to allowed range
            max_deviations = self.pca.get_allowed_deviation()
            for i in range(0, b.shape[0]):
                b[i] = min(max(b[i], -max_deviations[i]), max_deviations[i])

            # 3b. Limit pose values
            scale = min(max(scale, 5), 80 / (2 ** self.current_level))

            # 4. Reconstruct modified shape
            new_shape = self.pca.reconstruct(b)
            new_tooth = Tooth(to_landmarks_format(new_shape))
            new_tooth.transform(translation, scale, rotation)

            self.current_params = b

        self.current_tooth = new_tooth
Пример #8
0
 def createMeanModelFrame(self, parent, meanModel, col, row):
     height = 360
     width = 320
     img = np.zeros((height, width, 3), np.uint8)
     meanTooth = Tooth(deepcopy(meanModel))
     meanTooth.scale(height)
     meanTooth.translate([width / 2, height / 2])
     img = self._drawToothOnImage(meanTooth, img)
     frame = MeanModelFrame(parent, img, row, col)
     return frame
    def step(self, Y, X, eigenvectors, mean):

        # Fit Y to X
        Y_new = self.procrustes.allignDataToModel(Y, X)

        # Project Y into X space and get new b
        b = self.pca.project(Y_new.getLandmarks().flatten(), eigenvectors,
                             mean.getLandmarks().flatten())
        # print("b = " + str(b))

        # Generate new model points X
        X_new = self.pca.reconstruct(b, eigenvectors,
                                     mean.getLandmarks().flatten())

        X_new = X_new.reshape((X_new.shape[0] // 2, 2))

        return Tooth(X_new), b
Пример #10
0
    def _fitSingleToothModel(self, toothIndex, currentResolutionLevel,
                             radiograph, X, Y, b, eigenvalues, eigenvectors,
                             mean, filter_settings):

        scale = 500 / ((2 * currentResolutionLevel) + 1)

        Y_copy = deepcopy(Y)
        i = 0
        while i < 100:

            X, b_new = self._modelFittingStep(Y, X, eigenvalues, eigenvectors,
                                              mean, scale)
            # print("X Step: " + str(X.getLandmarks()))

            # Calculate new Y from the current X
            # I might need to first allign model X to Y, as X could still be at the origin and with no scale and rotation
            temp = self.procrustes.allignModelToData(deepcopy(Y_copy),
                                                     deepcopy(X))[1]
            # print("Temp step: " + str(temp.getLandmarks()))

            Y, p = self._getNewYEstimateAtCurrentResolutionLevel(
                temp, radiograph, toothIndex, currentResolutionLevel,
                filter_settings)
            Y = Tooth(Y)
            Y_copy = deepcopy(Y)

            # if ((np.isclose(b, b_new).all() and i>3) or (i>=(12/(currentResolutionLevel+1)) and currentResolutionLevel > 0)):
            #     print("Breaking after " + str(i) + " iterations")
            #     break
            # else:
            #     b = b_new
            #     i += 1

            if (p >= 0.9 and i > 2) or i >= 5:
                print("Breaking after " + str(i) + " iterations")
                break
            else:
                b = b_new
                i += 1

        return X, Y
Пример #11
0
    def _modelFittingStep(self, Y, X, eigenvalues, eigenvectors, mean, scale):

        # Fit Y to X
        Y_new = self.procrustes.allignDataToModel(Y, X)

        # Project Y into X space and get new b
        b = self.pca.project(Y_new.getLandmarks().flatten(), eigenvectors,
                             mean.getLandmarks().flatten())
        # print("b = " + str(b))

        # Enforce constraint |b_i| < 3*lambda_i
        for i in range(len(b)):
            if abs(b[i]) > 2 * eigenvalues[i] * scale:
                b[i] = 2 * eigenvalues[i] * scale
                # print("eigenvalue: " + str(eigenvalues[i]))

        # Generate new model points X
        X_new = self.pca.reconstruct(b, eigenvectors,
                                     mean.getLandmarks().flatten())

        X_new = X_new.reshape((X_new.shape[0] // 2, 2))

        return Tooth(X_new), b
    def fitModel(self, target_tooth, model):

        self.procrustes = Procrustes()
        self.pca = PCA()
        eigenvectors = model.getEigenvectors()
        Y = target_tooth
        mean = Tooth(model.getMeanModel())

        # Init
        b = 0
        X = mean

        i = 0
        while i < 20:
            i += 1

            X, b_new = self.step(Y, X, eigenvectors, mean)

            if np.allclose(b, b_new):
                break
            else:
                b = b_new

        return X
Пример #13
0
    def createMeanModelPresentationImages(self, statisticalModel):
        toothModels = statisticalModel.getAllToothModels(deepCopy=True)

        pca = PCA()

        for i in range(8):
            height = 3840
            width = 2160
            img = np.zeros((height, width, 3), np.uint8)
            meanModel = toothModels[i].getMeanModel(deepCopy=True)
            flatModel = meanModel.flatten()
            eigenvalues = toothModels[i].getEigenvalues(deepCopy=True)
            eigenvectors = toothModels[i].getEigenvectors(deepCopy=True)

            meanTooth = Tooth(deepcopy(meanModel))
            meanTooth.scale(height)
            meanTooth.translate([width / 2, height / 2])

            for j in range(len(eigenvalues)):

                img_2 = deepcopy(img)

                maxChangeVector = np.zeros(np.array(eigenvalues).shape)
                maxChangeVector[j] = 100 * eigenvalues[j] * (5 * j + 1)
                maxChange = pca.reconstruct(maxChangeVector, eigenvectors,
                                            deepcopy(flatModel))
                maxChange = maxChange.reshape((maxChange.shape[0] // 2, 2))
                maxChangeTooth = Tooth(maxChange)
                maxChangeTooth.scale(height)
                maxChangeTooth.translate([width / 2, height / 2])

                minChangeVector = np.zeros(np.array(eigenvalues).shape)
                minChangeVector[j] = -100 * (eigenvalues[j]) * (5 * j + 1)
                minChange = pca.reconstruct(minChangeVector, eigenvectors,
                                            deepcopy(flatModel))
                minChange = minChange.reshape((minChange.shape[0] // 2, 2))
                minChangeTooth = Tooth(minChange)
                minChangeTooth.scale(height)
                minChangeTooth.translate([width / 2, height / 2])

                # img_2 = self._drawToothContourOnImage(meanTooth, img_2, lineColor=(255,255,255))
                img_2 = self._drawToothContourOnImage(maxChangeTooth,
                                                      img_2,
                                                      lineColor=(255, 255,
                                                                 255))
                img_2 = self._drawToothContourOnImage(minChangeTooth,
                                                      img_2,
                                                      lineColor=(255, 255,
                                                                 255))

                height = img_2.shape[0]
                width = img_2.shape[1]
                img_2 = cv2.resize(img_2,
                                   (int(width * 0.1), int(height * 0.1)),
                                   interpolation=cv2.INTER_AREA)

                # img_2 = Filter.process_image(img_2)

                filename = "Results/mean_model_modes_adjusted/tooth_{0}_mode_{1}.jpg".format(
                    i, j)
                cv2.imwrite(filename, img_2)

                cv2.imshow("Mean Model", img_2)