Files
tunmnlu/task_2/others-answer/omsa-main/ISYE-8803-OAN/hw2/q3.py
louiscklaw 9035c1312b update,
2025-02-01 02:09:32 +08:00

162 lines
6.8 KiB
Python

import pandas as pd
import matplotlib as plt
import numpy as np
import scipy.misc as spm
import scipy.ndimage as ndi
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import BSpline
from scipy.spatial.distance import cdist
from sklearn import cluster
from skimage import color,io
from skimage.filters import threshold_otsu,threshold_multiotsu,prewitt,sobel
from skimage.data import camera
from skimage.util import compare_images
import numpy as np
import matplotlib.pylab as plt
import matplotlib.pyplot as plt
from skimage import color, io
from scipy.ndimage.filters import convolve
import logging
logger = logging.getLogger(__name__)
class CannyAlgorithm:
def __init__(self):
#Input gaussian filter to smooth the input image
self.h = 1/1115* np.array([[1,4,7,10,7,4,1],
[4,12,26,33,26,12,4],
[7,26,55,71,55,26,7],
[10,33,71,91,71,33,10],
[7,26,55,71,55,26,7],
[4,12,26,33,26,12,4],
[1,4,7,10,7,4,1]])
#Load grayscale image
self.grayscale = color.rgb2gray(io.imread('./horse1-2.jpg'))*255
def gaussian_filter(self):
"""[Apply gaussian filter to image for smoothing purposes and add 0 padding to matrix]
"""
logger.info("Creating smoothed matrix from applying gaussian filter")
return np.pad(convolve(self.grayscale,self.h), ((1,1),(1,1)),'constant')
def compute_partial_derivatives(self, s_i1_j: float, s_i_j: float, s_i1_j1: float, s_i_j1:float):
"""[Compute partial derivate for pixel with respect to x]
Args:
si_j1 (float): [Pixel directly to the east in image matrix]
s_i_j (float): [Current pixel]
s_i1_j1 (float): [Pixel directly in south-east coordinate of image in relation to pixel]
s_i1_j (float): [Pixel directly south of pixel image matrix]
"""
deriv_x = 1/2*(s_i1_j-s_i_j+s_i1_j1-s_i_j1)
deriv_y = 1/2*(s_i_j1-s_i_j+s_i1_j1-s_i1_j)
return deriv_x, deriv_y
def compute_gradients(self, S: np.ndarray):
"""[Iterate through each pixel and calculate the gradient direction and magnitute]
Args:
S (np.ndarray): [Smoothed image S representing the output of the grayscale image after
gaussian filter has been applied]
"""
logger.info("Computing the gradient magnitude matrices G and theta, respectively")
#Create gradient magnitute array
G = np.zeros(S.shape)
#Create theta for gradient direction
theta = np.zeros(S.shape)
#Iterate through each pixel and calculate the magnitute and direction
for i in range(1,S.shape[0]-1):
for j in range(1,S.shape[1]-1):
s_i_j = S[i,j]
s_i1_j1 = S[i+1,j+1]
s_i1_j = S[i+1,j]
s_i_j1 = S[i,j+1]
#Compute partial derivative for wrt to x and y
x,y = self.compute_partial_derivatives(s_i1_j, s_i_j, s_i1_j1, s_i_j1)
#Compute gradient magnitude
G[i,j] = np.sqrt((x**2)+(y**2))
#Compute gradient direction
theta[i,j] = np.arctan2(x,y)
plt.imsave('q3_G.png', G, cmap=plt.cm.gray)
plt.imsave('q3_theta.png', theta, cmap=plt.cm.gray)
return G, theta
def compute_nonmaximal_suppresion(self, G: np.ndarray, theta: np.ndarray):
"""[Nonmaximal suppression method]
Args:
G (np.ndarray): [Gradient magnitude matrix]
theta (np.ndarray): [Gradient direction matrix]
"""
#Create gradient magnitute array
phi = np.zeros(theta.shape)
#Iterate through each pixel and calculate the magnitute and direction
logger.info("Computing non-max suppression phi output")
for i in range(1,theta.shape[0]-1):
for j in range(1,theta.shape[1]-1):
#Iterate through each row in theta
if (-1/8*np.pi < theta[i,j] <= 1/8*np.pi):
i_1 = (i,j-1)
i_2 = (i,j+1)
elif (1/8*np.pi < theta[i,j] <= 3/8*np.pi):
i_1 = (i+1,j-1)
i_2 = (i-1,j+1)
elif (-3/8*np.pi < theta[i,j] <= -1/8*np.pi):
i_1 = (i-1,j-1)
i_2 = (i+1,j+1)
elif ((3/8*np.pi < theta[i,j] <= 1/2*np.pi) or (-1/2*np.pi < theta[i,j] <= -3/8*np.pi)):
i_1 = (i-1,j)
i_2 = (i+1,j)
elif G[i,j] >= G[i_1] and G[i,j] >= G[i_2]:
phi[i,j]=G[i,j]
plt.imsave('q3_phi.png', phi, cmap=plt.cm.gray)
return phi
def hysterisis(self, non_max_supress: np.ndarray):
"""[Run threshold with hysterisis to mitigate streaking]
Args:
G (np.ndarray): [description]
theta (np.ndarray): [description]
"""
#Create gradient magnitute array
logger.info("Computing the hysterisis step and outputting the final edge image.")
edge_image = np.zeros(non_max_supress.shape)
tau_1, tau_2 = 3, 8
#Iterate through each pixel and calculate the magnitute and direction
for i in range(1,non_max_supress.shape[0]-1):
for j in range(1,non_max_supress.shape[1]-1):
if non_max_supress[i,j] >= tau_2 and edge_image[i,j]==0:
edge_image[i,j]=1
elif non_max_supress[i,j] >= tau_1 and edge_image[i,j]==0:
neighbors = []
neighbors.append(edge_image[i-1,j-1])
neighbors.append(edge_image[i-1,j])
neighbors.append(edge_image[i-1,j+1])
neighbors.append(edge_image[i,j+1])
neighbors.append(edge_image[i+1,j+1])
neighbors.append(edge_image[i+1,j])
neighbors.append(edge_image[i+1,j-1])
neighbors.append(edge_image[i,j-1])
if 1 in neighbors:
edge_image[i,j]=1
plt.imsave('q3_edge_image.png', edge_image, cmap=plt.cm.gray)
return edge_image
if __name__ in "__main__":
logging.basicConfig(level=logging.INFO)
canny = CannyAlgorithm()
#Apply gaussian filter to input image in order to smooth
smooth_image = canny.gaussian_filter()
#Compute gradient direction and magnitute vectors
G, theta = canny.compute_gradients(smooth_image)
#Non-max suppression
non_max_suppression = canny.compute_nonmaximal_suppresion(G, theta)
#Calculate hysterisis
edge_image = canny.hysterisis(non_max_suppression)