I followed the Active Shape Models approach described by Tim Cootes in textbook and original paper. So far everything went well (Procrustes Analysis, Principal Component Analysis, preprocessing of images (contrast, noise)). Only the fitting procedure itself seems not to converge.
I use the statistical model of the grey-level structure approach as described in textbook (p. 13) for creating a fitting function for each of the 8 incisors, for each of the 40 landmarks (so 320 different fitting functions are created in total) per incisor by sampling 5 (=k
) points on either side along the profile normal to the boundary through each of the 40 landmarks for each of the 8 incisors. Those functions are equal to the Mahalanobis distance (textbook p. 14).
During the fitting procedure I sample 10 (=m>k
) points on either side along the profile normal to the boundary through each of the 40 landmarks of the current approximation of a tooth. That way I must evaluate 2(m-k)+1
samples with the corresponding fitting function.
Each of those samples contains the gradient value of 2k+1
points. The sample that minimizes the function is choosen and the corresponding landmark is positioned at the middle point of those 2k+1
points. This is done for each of the 40 landmarks. This results in a new (not validated yet) approximation of the tooth.
This approximation in the image coordinate frame is aligned with the model of the tooth in the image coordinate frame. Then the coefficients (bi
) of the principal component analysis are calculated and checked if |bi|<3*sqrt(eigenvalue_i)
in order not to deviate too much from the shape of the model. The coefficients (bi
) are limited if necessary and we transform back to the image coordinate frame and start some new iteration.
Shows the image of which we want to find the upper-left incisor.
Shows the gradient image with the approximation of the tooth in the image coordinate frame in iteration 19. (Red: before validation - Green: after validation) As one can see we're kind of diverged from the optimal solution.
def create_gradient(img):
temp = cv2.Scharr(img, ddepth=-1, dx=1, dy=0)
return cv2.Scharr(temp, ddepth=-1, dx=0, dy=1)
Shows the approximation of the tooth in the model coordinate frame in iteration 19. (Blue: model - Red: before validation - Green: after validation) As one can see we're still close to the shape of the model.
Shows the approximation of the tooth in the model coordinate frame for 19 iterations. (Blue: model - Red: before validation - Green: after validation) As one can see we stay close to the shape of the model during all these iterations
So we stay close to the shape (guarded by principal component analysis), but not close to the intensity behaviour (guarded by the fitting function) around the landmarks.