|
from scipy import ndimage |
|
from scipy.ndimage.filters import convolve |
|
|
|
from scipy import misc |
|
import numpy as np |
|
import cv2 |
|
|
|
|
|
class cannyEdgeDetector: |
|
def __init__(self, imgs, sigma=5, kernel_size=10, weak_pixel=75, strong_pixel=255, lowthreshold=0.05, |
|
highthreshold=0.15): |
|
self.imgs = imgs |
|
self.imgs_final = [] |
|
self.img_smoothed = None |
|
self.gradientMat = None |
|
self.thetaMat = None |
|
self.nonMaxImg = None |
|
self.thresholdImg = None |
|
self.weak_pixel = weak_pixel |
|
self.strong_pixel = strong_pixel |
|
self.sigma = sigma |
|
self.kernel_size = kernel_size |
|
self.lowThreshold = lowthreshold |
|
self.highThreshold = highthreshold |
|
return |
|
|
|
def gaussian_kernel(self, size, sigma=1): |
|
size = int(size) // 2 |
|
x, y = np.mgrid[-size:size + 1, -size:size + 1] |
|
normal = 1 / (2.0 * np.pi * sigma ** 2) |
|
g = np.exp(-((x ** 2 + y ** 2) / (2.0 * sigma ** 2))) * normal |
|
return g |
|
|
|
def sobel_filters(self, img): |
|
Kx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], np.float32) |
|
Ky = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]], np.float32) |
|
|
|
Ix = ndimage.filters.convolve(img, Kx) |
|
Iy = ndimage.filters.convolve(img, Ky) |
|
|
|
G = np.hypot(Ix, Iy) |
|
G = G / G.max() * 255 |
|
theta = np.arctan2(Iy, Ix) |
|
return (G, theta, Ix, Iy) |
|
|
|
def non_max_suppression(self, img, D): |
|
M, N = img.shape |
|
Z = np.zeros((M, N), dtype=np.int32) |
|
angle = D * 180. / np.pi |
|
angle[angle < 0] += 180 |
|
|
|
for i in range(1, M - 1): |
|
for j in range(1, N - 1): |
|
try: |
|
q = 255 |
|
r = 255 |
|
|
|
|
|
if (0 <= angle[i, j] < 22.5) or (157.5 <= angle[i, j] <= 180): |
|
q = img[i, j + 1] |
|
r = img[i, j - 1] |
|
|
|
elif (22.5 <= angle[i, j] < 67.5): |
|
q = img[i + 1, j - 1] |
|
r = img[i - 1, j + 1] |
|
|
|
elif (67.5 <= angle[i, j] < 112.5): |
|
q = img[i + 1, j] |
|
r = img[i - 1, j] |
|
|
|
elif (112.5 <= angle[i, j] < 157.5): |
|
q = img[i - 1, j - 1] |
|
r = img[i + 1, j + 1] |
|
|
|
if (img[i, j] >= q) and (img[i, j] >= r): |
|
Z[i, j] = img[i, j] |
|
else: |
|
Z[i, j] = 0 |
|
|
|
|
|
except IndexError as e: |
|
pass |
|
|
|
return Z |
|
|
|
def threshold(self, img): |
|
|
|
highThreshold = img.max() * self.highThreshold; |
|
lowThreshold = highThreshold * self.lowThreshold; |
|
|
|
M, N = img.shape |
|
res = np.zeros((M, N), dtype=np.int32) |
|
|
|
weak = np.int32(self.weak_pixel) |
|
strong = np.int32(self.strong_pixel) |
|
|
|
strong_i, strong_j = np.where(img >= highThreshold) |
|
zeros_i, zeros_j = np.where(img < lowThreshold) |
|
|
|
weak_i, weak_j = np.where((img <= highThreshold) & (img >= lowThreshold)) |
|
|
|
res[strong_i, strong_j] = strong |
|
res[weak_i, weak_j] = weak |
|
|
|
return (res) |
|
|
|
def hysteresis(self, img): |
|
|
|
M, N = img.shape |
|
weak = self.weak_pixel |
|
strong = self.strong_pixel |
|
|
|
for i in range(1, M - 1): |
|
for j in range(1, N - 1): |
|
if (img[i, j] == weak): |
|
try: |
|
if ((img[i + 1, j - 1] == strong) or (img[i + 1, j] == strong) or (img[i + 1, j + 1] == strong) |
|
or (img[i, j - 1] == strong) or (img[i, j + 1] == strong) |
|
or (img[i - 1, j - 1] == strong) or (img[i - 1, j] == strong) or ( |
|
img[i - 1, j + 1] == strong)): |
|
img[i, j] = strong |
|
else: |
|
img[i, j] = 0 |
|
except IndexError as e: |
|
pass |
|
|
|
return img |
|
|
|
def detect(self): |
|
imgs_final = [] |
|
for i, img in enumerate(self.imgs): |
|
cv2.imwrite('output/0img.png', img) |
|
self.img_smoothed = convolve(img, self.gaussian_kernel(self.kernel_size, self.sigma)) |
|
self.img_smoothed = self.img_smoothed/np.max(self.img_smoothed)*255 |
|
cv2.imwrite('output/1smoothed.png', self.img_smoothed) |
|
self.gradientMat, self.thetaMat, Ix, Iy = self.sobel_filters(self.img_smoothed) |
|
cv2.imwrite('output/2Ix.png', Ix) |
|
cv2.imwrite('output/2Iy.png', Iy) |
|
cv2.imwrite('output/4deltaI.png', self.gradientMat.astype(float)) |
|
cv2.imwrite('output/5theta.png', self.thetaMat.astype(float) / np.max(self.thetaMat) * 255) |
|
self.nonMaxImg = self.non_max_suppression(self.gradientMat, self.thetaMat) |
|
cv2.imwrite('output/6nonmax.png', self.nonMaxImg) |
|
self.thresholdImg = self.threshold(self.nonMaxImg) |
|
cv2.imwrite('output/7threshold.png', self.thresholdImg) |
|
img_final = self.hysteresis(self.thresholdImg) |
|
self.imgs_final.append(img_final) |
|
|
|
return self.imgs_final |
|
|
|
if __name__ == '__main__': |
|
image_path = '/home/ho11laqe/PycharmProjects/data_raw/sar_images/test/Mapple_2011-06-02_TSX_7_1_110.png' |
|
|
|
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)[:1000,-1000:].astype(np.float32) |
|
detector = cannyEdgeDetector([img], sigma=20) |
|
edge = detector.detect() |
|
cv2.imwrite('output/8edge.png', edge[0]) |
|
|
|
|