DHRUV MAKWANA
DHRUV MAKWANA

Reputation: 1

Get Edges/boundary for overlapping image

I have a mask for a dental x-ray here where all teeth are overlapping with each other. I want to count the number of teeth present in the image for that I want to separate overlapping tooths so I can use contour-based approach to count the number of tooths, I tried following approach but it is giving result like this . how can I extract boundary for each tooth?

from skimage.feature import peak_local_max
from skimage.morphology import watershed
import matplotlib.pyplot as plt
from scipy import ndimage
import numpy as np
import cv2

def getImageEdge(input_image):
    img_gray = input_image
    image_black = np.zeros(shape=input_image.shape, dtype="uint8")
    thresh = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    thresh_copy = thresh.copy()
    D = ndimage.distance_transform_edt(thresh_copy)
    localMax = peak_local_max(D, indices = False, min_distance = 12, labels = thresh)
    markers = ndimage.label(localMax, structure = np.ones((3, 3)))[0]
    labels = watershed(-D, markers, mask = thresh_copy)
    for label in np.unique(labels):
        if label == 0:
            continue
        mask = np.zeros(img_gray.shape, dtype = "uint8")
        mask[labels == label] = 255
        contours, hierarchy = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        cv2.drawContours(image_black, contours, -1, (255, 255, 255), 1)
    return image_black

inputImage = cv2.imread("/content/dentalMask.bmp")
inputImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
outputImage = getImageEdge(inputImage)
plt.imshow(inputImage)
plt.show()
plt.imshow(outputImage)
plt.show()

EDITED:

Based on the answer from fmw42 I have added one more image where it is showing more overlapping and failed in simple thresholding and contour-based approach.

input output

Upvotes: 0

Views: 594

Answers (2)

user1196549
user1196549

Reputation:

Without knowledge of the exact layout of teeth in a mouth, this task is impossible. No image processing technique can help.

Because in case of touching teeth, you can't tell two touching teeth from a two-rooted tooth.

Upvotes: 0

fmw42
fmw42

Reputation: 53089

Given your example, the following works for me in Python/OpenCV by simply thresholding and getting the contours.

Input:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread("teeth.png")

# convert img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold gray image
#thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

# Get contours
cntrs = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
result = img.copy()
for c in cntrs:
    cv2.drawContours(result, [c], -1, (0,0,255), 1)

count = len(cntrs)
print("")
print("count =",count)

print("")

# write results to disk
cv2.imwrite("teeth_thresh.png", thresh)
cv2.imwrite("tide_contours.png", result)

# display it
cv2.imshow("thresh", thresh)
cv2.imshow("result", result)
cv2.waitKey(0)

Contours:

enter image description here

Resulting Count:

count = 32

Upvotes: 1

Related Questions