Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import tensorflow as tf | |
| from PIL import Image | |
| import numpy as np | |
| import cv2 | |
| import matplotlib.pyplot as plt | |
| from imutils import perspective | |
| from scipy.spatial import distance as dist | |
| model=tf.keras.models.load_model("dental_xray_seg.h5") | |
| st.header("Segmentation of Teeth in Panoramic X-ray Image") | |
| examples=["teeth_01.png","teeth_02.png","teeth_03.png","teeth_04.png"] | |
| def load_image(image_file): | |
| img = Image.open(image_file) | |
| img_gray = img.convert('L') | |
| img_np = np.array(img_gray) | |
| return img_np | |
| def convert_one_channel(img): | |
| if len(img.shape)>2: | |
| img= cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| return img | |
| def convert_rgb(img): | |
| if len(img.shape)==2: | |
| img= cv2.cvtColor(img,cv2.COLOR_GRAY2RGB) | |
| return img | |
| def midpoint(ptA, ptB): | |
| return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5) | |
| def CCA_Analysis(orig_image,predict_image,erode_iteration,open_iteration): | |
| kernel1 =( np.ones((5,5), dtype=np.float32)) | |
| kernel_sharpening = np.array([[-1,-1,-1], | |
| [-1,9,-1], | |
| [-1,-1,-1]]) | |
| image = predict_image | |
| image2 =orig_image | |
| image=cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel1,iterations=open_iteration ) | |
| image = cv2.filter2D(image, -1, kernel_sharpening) | |
| image=cv2.erode(image,kernel1,iterations =erode_iteration) | |
| image=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) | |
| thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1] | |
| labels=cv2.connectedComponents(thresh,connectivity=8)[1] | |
| a=np.unique(labels) | |
| count2=0 | |
| for label in a: | |
| if label == 0: | |
| continue | |
| # Create a mask | |
| mask = np.zeros(thresh.shape, dtype="uint8") | |
| mask[labels == label] = 255 | |
| # Find contours and determine contour area | |
| cnts,hieararch = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
| cnts = cnts[0] | |
| c_area = cv2.contourArea(cnts) | |
| # threshhold for tooth count | |
| if c_area>2000: | |
| count2+=1 | |
| (x,y),radius = cv2.minEnclosingCircle(cnts) | |
| rect = cv2.minAreaRect(cnts) | |
| box = cv2.boxPoints(rect) | |
| box = np.array(box, dtype="int") | |
| box = perspective.order_points(box) | |
| color1 = (list(np.random.choice(range(150), size=3))) | |
| color =[int(color1[0]), int(color1[1]), int(color1[2])] | |
| cv2.drawContours(image2,[box.astype("int")],0,color,2) | |
| (tl,tr,br,bl)=box | |
| (tltrX,tltrY)=midpoint(tl,tr) | |
| (blbrX,blbrY)=midpoint(bl,br) | |
| # compute the midpoint between the top-left and top-right points, | |
| # followed by the midpoint between the top-righ and bottom-right | |
| (tlblX,tlblY)=midpoint(tl,bl) | |
| (trbrX,trbrY)=midpoint(tr,br) | |
| # draw the midpoints on the image | |
| cv2.circle(image2, (int(tltrX), int(tltrY)), 5, (255, 0, 0), -1) | |
| cv2.circle(image2, (int(blbrX), int(blbrY)), 5, (255, 0, 0), -1) | |
| cv2.circle(image2, (int(tlblX), int(tlblY)), 5, (255, 0, 0), -1) | |
| cv2.circle(image2, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1) | |
| cv2.line(image2, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),color, 2) | |
| cv2.line(image2, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),color, 2) | |
| dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY)) | |
| dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY)) | |
| pixelsPerMetric=1 | |
| dimA = dA * pixelsPerMetric | |
| dimB = dB *pixelsPerMetric | |
| cv2.putText(image2, "{:.1f}pixel".format(dimA),(int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX,0.65, color, 2) | |
| cv2.putText(image2, "{:.1f}pixel".format(dimB),(int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX,0.65, color, 2) | |
| cv2.putText(image2, "{:.1f}".format(label),(int(tltrX - 35), int(tltrY - 5)), cv2.FONT_HERSHEY_SIMPLEX,0.65, color, 2) | |
| teeth_count=count2 | |
| return image2,teeth_count | |
| def detect_decays_static_th(images, dental_masks=None, threshhold=0.9): | |
| decay_masks = [] | |
| for image, dental_mask in zip(images, dental_masks): | |
| decay_mask = np.zeros_like(dental_mask) | |
| image_masked_with_dental_mask = image * dental_mask | |
| decay_mask[image_masked_with_dental_mask > threshhold*255] = 1 | |
| decay_masks.append(decay_mask) | |
| decay_masks = np.array(decay_masks) | |
| return decay_masks | |
| st.subheader("Upload Dental Panoramic X-ray Image") | |
| image_file = st.file_uploader("Upload Images", type=["png","jpg","jpeg"]) | |
| col1, col2, col3, col4 = st.columns(4) | |
| with col1: | |
| ex=load_image(examples[0]) | |
| st.image(ex,width=200) | |
| if st.button('Example 1'): | |
| image_file=examples[0] | |
| with col2: | |
| ex1=load_image(examples[1]) | |
| st.image(ex1,width=200) | |
| if st.button('Example 2'): | |
| image_file=examples[1] | |
| with col3: | |
| ex2=load_image(examples[2]) | |
| st.image(ex2,width=200) | |
| if st.button('Example 3'): | |
| image_file=examples[2] | |
| with col4: | |
| ex2=load_image(examples[3]) | |
| st.image(ex2,width=200) | |
| if st.button('Example 4'): | |
| image_file=examples[3] | |
| if image_file is not None: | |
| image_original = Image.open(image_file) | |
| image=np.asarray(image_original) | |
| image = convert_rgb(image) | |
| st.subheader("Original Image") | |
| st.image(image,width=1100) | |
| st.text("Making A Prediction ....") | |
| img=np.asarray(image) | |
| img_cv=convert_one_channel(img) | |
| img_cv=cv2.resize(img_cv,(512,512), interpolation=cv2.INTER_LANCZOS4) | |
| img_cv=np.float32(img_cv/255) | |
| img_cv=np.reshape(img_cv,(1,512,512,1)) | |
| prediction=model.predict(img_cv) | |
| predicted=prediction[0] | |
| predicted_rgb = np.expand_dims(predicted, axis=-1) | |
| plt.imsave("predict.png",predicted_rgb) | |
| predict1 = cv2.resize(predicted, (img.shape[1], img.shape[0]), interpolation=cv2.INTER_LANCZOS4) | |
| img_dc=convert_one_channel(img) | |
| decay_mask = detect_decays_static_th(img_dc, predict1) | |
| mask = np.uint8(predict1 * 255) | |
| _, mask = cv2.threshold(mask, thresh=255/2, maxval=255, type=cv2.THRESH_BINARY) | |
| cnts, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) | |
| img = cv2.drawContours(img, cnts, -1, (0, 0, 255), 2) | |
| mask = np.uint8(decay_mask * 255) | |
| _, mask = cv2.threshold(mask, thresh=255/2, maxval=255, type=cv2.THRESH_BINARY) | |
| cnts, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) | |
| img = cv2.fillPoly(img, cnts, (255, 0, 0)) | |
| if img is not None : | |
| st.subheader("Predicted teeth shape + caries zones") | |
| st.write(img.shape) | |
| st.image(img,width=1100) | |
| image=np.asarray(image_original) | |
| image = convert_rgb(image) | |
| if image.shape[1] < 3000: | |
| image = cv2.resize(image,(3100,1150),interpolation=cv2.INTER_LANCZOS4) | |
| predicted=cv2.imread("predict.png") | |
| predicted = cv2.resize(predicted, (image.shape[1],image.shape[0]), interpolation=cv2.INTER_LANCZOS4) | |
| cca_result,teeth_count=CCA_Analysis(image,predicted,3,2) | |
| if cca_result is not None : | |
| st.subheader("Seperate predicted teeth") | |
| st.write(cca_result.shape) | |
| st.image(cca_result,width=1100) | |
| st.text("Teeth Count = " + str(teeth_count)) | |
| st.text("DONE ! ....") | |