Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kidney stone prediction #229

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions Models/Kidney_Stone_Prediction/Finalcode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import cv2
import argparse
import numpy as np
import matplotlib.pyplot as plt
# %matplotlib inline

s = r'Images_Used'
image_no = '\image1.jpg'
s = s + image_no

img = cv2.imread(s,0)

def build_filters():
#returns a list of kernels in several orientations
filters = []
ksize = 31
for theta in np.arange(0, np.pi, np.pi / 32):
params = {'ksize': (ksize, ksize), 'sigma': 0.0225, 'theta': theta, 'lambd': 15.0,
'gamma': 0.01, 'psi': 0, 'ktype': cv2.CV_32F}

kern = cv2.getGaborKernel(**params)
kern /= 1.5*kern.sum()
filters.append((kern, params))
return filters


def process(img, filters):
#returns the img filtered by the filter list
accum = np.zeros_like(img)
for kern, params in filters:
fimg = cv2.filter2D(img, cv2.CV_8UC3, kern)
np.maximum(accum, fimg, accum)
return accum

def Histeq(img):
equ = cv2.equalizeHist(img)
return equ

def GaborFilter(img):
filters = build_filters()
p = process(img, filters)
return p

def Laplacian(img,par):
lap = cv2.Laplacian(img,cv2.CV_64F)
sharp = img - par*lap
sharp = np.uint8(cv2.normalize(sharp, None, 0 , 255, cv2.NORM_MINMAX))
return sharp

def Watershed(img):
ret, thresh = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# noise removal
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)

# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=3)

# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.23*dist_transform.max(),255,0)

# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)

# Marker labelling
ret, markers = cv2.connectedComponents(sure_fg)

# Add one to all labels so that sure background is not 0, but 1
markers = markers+1

# Now, mark the region of unknown with zero
markers[unknown==255] = 0

img2 = cv2.imread(s,1)
img2 = cv2.medianBlur(img2,5)
markers = cv2.watershed(img2,markers)
img2[markers == -1] = [255,0,0]

return img2

if image_no=='\image1.jpg':
img3 = Laplacian(img,0.239)

elif image_no=='\image2.jpg':
img3 = GaborFilter(img)
img3 = Histeq(img3)

elif image_no=='\image4.jpg':
img3 = GaborFilter(img)

img3 = Watershed(img)

plt.imshow(img3,'gray')
plt.title('Marked')
plt.xticks([]),plt.yticks([])
plt.show()
58 changes: 58 additions & 0 deletions Models/Kidney_Stone_Prediction/Gabor_HistEq.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#%% #this line is for VSCode editor only
import cv2
#from skimage.measure import compare_ssim
import argparse
#import imutils
import numpy as np
import matplotlib.pyplot as plt
# %matplotlib inline
#change the path as per you configuration

img = cv2.imread(r'Images_Used\image3.JPG',0)


#sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
#sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
#laplacian = cv2.Laplacian(img,cv2.CV_64F)

def build_filters():
""" returns a list of kernels in several orientations
"""
filters = []
ksize = 31
for theta in np.arange(0, np.pi, np.pi / 32):
params = {'ksize': (ksize, ksize), 'sigma': 2.5, 'theta': theta, 'lambd': 15.0,
'gamma': 0.02, 'psi': 0, 'ktype': cv2.CV_32F}

kern = cv2.getGaborKernel(**params)
kern /= 1.5*kern.sum()
filters.append((kern, params))
return filters


def process(img, filters):
""" returns the img filtered by the filter list
"""
accum = np.zeros_like(img)
for kern, params in filters:
fimg = cv2.filter2D(img, cv2.CV_8UC3, kern)
np.maximum(accum, fimg, accum)
return accum


#main
filters = build_filters()
p = process(img, filters)

equ = cv2.equalizeHist(p)

plt.figure(1)
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])

plt.subplot(122), plt.imshow(equ, cmap='gray')
plt.title('Gabor Only'),plt.xticks([]),plt.yticks([])
plt.show()

#plt.subplot(123), plt.imshow(equ, cmap='gray')
#plt.title('Histogram + Gabor'), plt.xticks([]), plt.yticks([])
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions Models/Kidney_Stone_Prediction/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Kidney Stone Detection
## Using Image Processing Techniques

The main objective of this is to detect the kidney stone from a digital ultrasound image of the kidney by performing various image processing techniques.

### WORK PERFORMED
The data were collected from various sources some were online, whose link is given below and also from some close contacts. After collecting the data, we proceeded towards our working.
The first step was to get a clear and better quality of the data so we worked on the IMAGE ENHANCEMENT:
1. The first one we applied was Frequency Domain + Gaussian Filter. Here we had to divide the image into two plains real plain and complex plain and then apply the Gaussian Filter in both.
2. The second attempt was with Gaussian Blur + Laplacian Filter. We had to apply Gaussian Blur to make Laplacian filter less sensitive to noise.
3. On further studies, we found in some research papers (link given below) that Ultrasounds give speckle noise. So, our third attempt was to replace Gaussian Blur with Median Blur as the latter is more effective for low-level noises like speckle noise, salt-and-pepper noise etc. followed by Laplacian filter.
4. In the application of the Gabor filter, the restored image is enriched with optimal resolution in both spatial and frequency domains (as stated in one of the research papers, whose link is given below). 2-D Gabor filter is easier to tune the direction and radial frequency bandwidth, and easier to tune centre frequency, so they can simultaneously get the best resolution in the spatial domain and frequency domain.

Now we moved to our next step HISTOGRAM EQUALIZATION.
It is a technique for adjusting image intensities to enhance contrast. This process leads to an increase in contrast of the shadow of the stone and the stone itself. Thus, it became more visible.

After this, we proceeded towards IMAGE SEGMENTATION.
It partitions an image into distinct regions containing each pixel with similar attributes. To be meaningful and useful for image analysis and interpretation, the regions should strongly relate to depicted objects or features of interest. Meaningful segmentation is the first step from low-level image processing transforming a greyscale or colour image into one or more other images to high-level image description in terms of features, objects, and scenes. Hereby performing this, we needed to partition our stone from the rest of the image. The type of Image Segmentation used here is Watersheds. Here we divide the image into peaks (high intensity) and valleys (low intensity). We fill the valleys (points of minima or background) with water of different colours (labels). As the water rises, depending on the peaks(gradients) nearby, water from different valleys, obviously with different colours will start to merge. To avoid this, we need to build barriers in the area where the water is mixing. Also, we continue the process of filling water until all the peaks are under water. The barriers, thus, created are the result of image segmentation. Now, the shadow gets separated from the stone giving a clear image of the stone.

The last step being MARKING.
It provides you with a way to identify or label a spot within the processing pipeline. Adding a marker into the pipeline will allow you to refer to the image currently being processed at that point. It can also be used to specify a location in the pipeline for other modules.



| WaterShed | Read Write | Med Lap |
| ------------- | ------------- | ------------- |
| ![WaterShed](https://user-images.githubusercontent.com/67019423/119897060-85a55200-bf5d-11eb-8b91-b45b39f530c9.PNG) | ![read_write](https://user-images.githubusercontent.com/67019423/119897084-8ccc6000-bf5d-11eb-8ece-ac0646e23d77.PNG) | ![med_lap](https://user-images.githubusercontent.com/67019423/119897117-9655c800-bf5d-11eb-80b6-d0a085089d52.PNG) |

| Gaussian | Gabor HistEq | Final Image |
| ------------- | ------------- | ------------- |
| ![gaussian](https://user-images.githubusercontent.com/67019423/119897180-a9689800-bf5d-11eb-9885-671785171637.PNG) | ![Gabor_HistEq](https://user-images.githubusercontent.com/67019423/119897224-b8e7e100-bf5d-11eb-9cd9-a2b6955077d9.PNG) | ![Finalcode](https://user-images.githubusercontent.com/67019423/119897256-c43b0c80-bf5d-11eb-8ac2-df3291acda56.PNG) |

### RESULTS
Total of 4 approaches have been performed to enhance the quality of the image, namely: Gabor Filter, Median blur + Laplacian Filter, Gaussian blur + Laplacian Filter, Gaussian Filtering in Frequency domain. Out of the 4, we have noticed that Gabor Filter was effective on a larger number of images though not all. Nextly Median blur + Laplacian Filter and Gaussian blur + Laplacian Filter worked perfectly with other of the few images which are lesser compared to Gabor Filter. Lastly, Gaussian Filtering in Frequency domain, which didn’t work as expected and hence this technique was not employed to enhance any of the other images. We also could generalize the effectiveness of the techniques due to lack of data samples.
Resulting images of ultrasound are given below:

| Original image | Image with detection |
| ------------- | ------------- |
| ![image](https://user-images.githubusercontent.com/67019423/119896533-c6e93200-bf5c-11eb-973f-79330915b0d9.png) | ![image](https://user-images.githubusercontent.com/67019423/119896558-d0729a00-bf5c-11eb-8bb6-94f75137f1f9.png) |
| ![image](https://user-images.githubusercontent.com/67019423/119896609-df594c80-bf5c-11eb-943d-90cbe5856fb7.png) | ![image](https://user-images.githubusercontent.com/67019423/119896625-e7b18780-bf5c-11eb-91dd-f2b8941c6556.png) |
63 changes: 63 additions & 0 deletions Models/Kidney_Stone_Prediction/WaterShed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#%% #this line is for VSCode editor only
import cv2
#from skimage.measure import compare_ssim
import argparse
#import imutils
import numpy as np
import matplotlib.pyplot as plt
# %matplotlib inline

img = cv2.imread(r'images\image2.JPG',0)

ret, thresh = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

plt.subplot(121),plt.imshow(thresh,'gray')
plt.title('Thresh_Binary_INV+cv2.Thresh_OTSU')
plt.xticks([]),plt.yticks([])

# noise removal
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)

# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=3)

# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.1*dist_transform.max(),255,0)

# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)

plt.subplot(121),plt.imshow(sure_fg,'gray')
plt.title('Sure')
plt.xticks([]),plt.yticks([])

plt.subplot(122),plt.imshow(unknown,'gray')
plt.title('Unknown')
plt.xticks([]),plt.yticks([])

# Marker labelling
ret, markers = cv2.connectedComponents(sure_fg)

# Add one to all labels so that sure background is not 0, but 1
markers = markers+1

# Now, mark the region of unknown with zero
markers[unknown==255] = 0


plt.subplot(121),plt.imshow(markers,'gray')
plt.title('Marked')
plt.xticks([]),plt.yticks([])

img = cv2.imread(r'images\image2.JPG',1)
img = cv2.medianBlur(img,5)
markers = cv2.watershed(img,markers)
img[markers == -1] = [255,0,0]

plt.imshow(img,'gray')
plt.title('Marked')
plt.xticks([]),plt.yticks([])
plt.show()
35 changes: 35 additions & 0 deletions Models/Kidney_Stone_Prediction/gaussian.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import sys
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

ddepth = cv.CV_16S
kernel_size = 3
# [variables]
# [load]
src = cv.imread(r'Images_Used\image2.JPG', cv.IMREAD_COLOR) # Load an image
# Check if image is loaded fine
# [load]
# [reduce_noise]
# Remove noise by blurring with a Gaussian filter
src = cv.GaussianBlur(src, (3, 3), 0)
# [reduce_noise]
# [convert_to_gray]
# Convert the image to grayscale
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# [convert_to_gray]
# Create Window
# [laplacian]
# Apply Laplace function
dst = cv.Laplacian(src_gray, ddepth, kernel_size)
# [laplacian]
# [convert]
# converting back to uint8
abs_dst = cv.convertScaleAbs(dst)
# [convert]
# [display]
plt.subplot(121),plt.imshow(src, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(abs_dst, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
Binary file added Models/Kidney_Stone_Prediction/images/image1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Models/Kidney_Stone_Prediction/images/image2.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Models/Kidney_Stone_Prediction/images/image3.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Models/Kidney_Stone_Prediction/images/image4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Models/Kidney_Stone_Prediction/images/image5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions Models/Kidney_Stone_Prediction/med_lap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import cv2
import argparse
import imutils
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread(r'Images_Used\image2.JPG', 0)

# **** check by changing the value 5 to any other odd number ****
dst = cv2.medianBlur(img, 5)

# Calculate the Laplacian
lap = cv2.Laplacian(dst,cv2.CV_64F)

# Calculate the sharpened image
# *****check this line if it is necessary******
sharp = dst - 0.3*lap

sharp = np.uint8(cv2.normalize(sharp, None, 0 , 255, cv2.NORM_MINMAX))
equ = cv2.equalizeHist(sharp)

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(equ, cmap = 'gray')
plt.title('Output Image'), plt.xticks([]), plt.yticks([])
plt.show()
16 changes: 16 additions & 0 deletions Models/Kidney_Stone_Prediction/read_write.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#%% #this line is for VSCode editor only
import cv2
#from skimage.measure import compare_ssim
import argparse
import imutils
import numpy as np
import matplotlib.pyplot as plt
#change the path as per you configuration
img = cv2.imread(r'Images_Used\image1.jpg',1)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
#sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
#laplacian = cv2.Laplacian(img,cv2.CV_64F)

plt.subplot(111), plt.imshow(sobely, cmap='gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.show()