카테고리 없음

[파이썬] 가우스 에지 탐지의 라플라시안 파이썬 구현

행복을전해요 2021. 2. 6. 17:45

matlab edge ()가해야 할 일

  1. LoG 계산
  2. LoG에서 제로 크로싱 계산
  3. 로컬 LoG 차이에 대한 임계 값 계산
  4. 에지 픽셀 = 제로 크로싱 && 로컬 차이> 임계 값

scipy의 LoG 필터는 위의 1 단계 만 수행합니다. 위의 2 ~ 4 단계를 모방하기 위해 다음 스 니펫을 구현했습니다.

import scipy as sp
import numpy as np
import scipy.ndimage as nd
import matplotlib.pyplot as plt
from skimage import data    

# lena = sp.misc.lena() this function was deprecated in version 0.17
img = data.camera()  # use a standard image from skimage instead
LoG = nd.gaussian_laplace(img , 2)
thres = np.absolute(LoG).mean() * 0.75
output = sp.zeros(LoG.shape)
w = output.shape[1]
h = output.shape[0]

for y in range(1, h - 1):
    for x in range(1, w - 1):
            patch = LoG[y-1:y+2, x-1:x+2]
                    p = LoG[y, x]
                            maxP = patch.max()
                                    minP = patch.min()
                                            if (p > 0):
                                                        zeroCross = True if minP < 0 else False
                                                                else:
                                                                            zeroCross = True if maxP > 0 else False
                                                                                    if ((maxP - minP) > thres) and zeroCross:
                                                                                                output[y, x] = 1
                                                                                                
                                                                                                plt.imshow(output)
                                                                                                plt.show()
                                                                                                

물론 이것은 느리고 아마도 파이썬을 처음 접하기 때문에 관용적이지는 않지만 아이디어를 보여야합니다. 개선 방법에 대한 제안도 환영합니다.

-------------------

나는 ycyeh의 코드를 약간 가지고 놀았습니다 (제공해 주셔서 감사합니다). 내 응용 프로그램에서는 바이너리 0과 1보다 최소-최대 범위에 비례하는 출력 값을 사용하여 더 나은 결과를 얻었습니다. (그런 다음 더 이상 thresh가 필요하지 않았지만 결과에 임계 값을 쉽게 적용 할 수 있습니다.) 또한 빠른 실행을 위해 루프를 numpy 배열 작업으로 변경했습니다.

import numpy as np
import scipy.misc
import cv2  # using opencv as I am not too familiar w/ scipy yet, sorry 


def laplace_of_gaussian(gray_img, sigma=1., kappa=0.75, pad=False):
    """
        Applies Laplacian of Gaussians to grayscale image.
        
            :param gray_img: image to apply LoG to
                :param sigma:    Gauss sigma of Gaussian applied to image, <= 0. for none
                    :param kappa:    difference threshold as factor to mean of image values, <= 0 for none
                        :param pad:      flag to pad output w/ zero border, keeping input image size
                            """
                                assert len(gray_img.shape) == 2
                                    img = cv2.GaussianBlur(gray_img, (0, 0), sigma) if 0. < sigma else gray_img
                                        img = cv2.Laplacian(img, cv2.CV_64F)
                                            rows, cols = img.shape[:2]
                                                # min/max of 3x3-neighbourhoods
                                                    min_map = np.minimum.reduce(list(img[r:rows-2+r, c:cols-2+c]
                                                                                         for r in range(3) for c in range(3)))
                                                                                             max_map = np.maximum.reduce(list(img[r:rows-2+r, c:cols-2+c]
                                                                                                                                  for r in range(3) for c in range(3)))
                                                                                                                                      # bool matrix for image value positiv (w/out border pixels)
                                                                                                                                          pos_img = 0 < img[1:rows-1, 1:cols-1]
                                                                                                                                              # bool matrix for min < 0 and 0 < image pixel
                                                                                                                                                  neg_min = min_map < 0
                                                                                                                                                      neg_min[1 - pos_img] = 0
                                                                                                                                                          # bool matrix for 0 < max and image pixel < 0
                                                                                                                                                              pos_max = 0 < max_map
                                                                                                                                                                  pos_max[pos_img] = 0
                                                                                                                                                                      # sign change at pixel?
                                                                                                                                                                          zero_cross = neg_min + pos_max
                                                                                                                                                                              # values: max - min, scaled to 0--255; set to 0 for no sign change
                                                                                                                                                                                  value_scale = 255. / max(1., img.max() - img.min())
                                                                                                                                                                                      values = value_scale * (max_map - min_map)
                                                                                                                                                                                          values[1 - zero_cross] = 0.
                                                                                                                                                                                              # optional thresholding
                                                                                                                                                                                                  if 0. <= kappa:
                                                                                                                                                                                                          thresh = float(np.absolute(img).mean()) * kappa
                                                                                                                                                                                                                  values[values < thresh] = 0.
                                                                                                                                                                                                                      log_img = values.astype(np.uint8)
                                                                                                                                                                                                                          if pad:
                                                                                                                                                                                                                                  log_img = np.pad(log_img, pad_width=1, mode='constant', constant_values=0)
                                                                                                                                                                                                                                      return log_img
                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                      def _main():
                                                                                                                                                                                                                                          """Test routine"""
                                                                                                                                                                                                                                              # load grayscale image
                                                                                                                                                                                                                                                  img = scipy.misc.face()  # lena removed from newer scipy versions
                                                                                                                                                                                                                                                      img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                                                                                                                                                                                                                                                          # apply LoG
                                                                                                                                                                                                                                                              log = laplace_of_gaussian(img)
                                                                                                                                                                                                                                                                  # display
                                                                                                                                                                                                                                                                      cv2.imshow('LoG', log)
                                                                                                                                                                                                                                                                          cv2.waitKey(0)
                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                          if __name__ == '__main__':
                                                                                                                                                                                                                                                                              _main()
                                                                                                                                                                                                                                                                              


출처
https://stackoverflow.com/questions/22050199