ToF 카메라는 보이는 그대로의 영상을 만드는 것이 아니라, 카메라로부터의 거리 정보를 담은 영상을 만든다. 기본 원리는 빛을 물체에 비춰 반사되어 돌아오는 데 걸리는 시간을 측정하고 이로부터 카메라와 물체 사이의 거리를 계산하는 것이다. ToF 카메라는 이렇게 계산한 거리 정보를 모아 디지털 영상을 만든다.ToF 카메라는 빛을 내는 광원과 빛을 감지하는 감지기(센서: sensor)가 한 쌍으로 작동한다. 사람 눈에 보이지 않는 빛인 적외선을 광원으로 많이 사용한다. 카메라의 광원을 떠난 빛은 물체에 부딪혀 반사되어 카메라로 다시 돌아온다. 빛이 날아간 거리는 카메라와 물체 사이의 거리를 왕복한 거리다. 비행시간(ToF: Time of Flight)은 왕복 거리를 날아가는 비행시간이다. 따라서 카메라와 물체 사이의 실제 거리는 ‘비행시간’으로 계산한 거리를 반으로 나눠서 계산한다.
arducam의 경우 tof 카메라로 depth map을 생성하면, 각 픽셀에 해당하는 행렬의 원소는 각지점까지의 거리를 mm단위로 포함하고 있음
youtube 영상
아두캠 TOF 페이지 -> 하단의 product page -> Documentation의 Getting Started with Arducam ToF Camera
아두캠
Ros에서 실행시
Ros
#pull repository
git clone https://github.com/ArduCAM/Arducam_tof_camera.git
cd Arducam_tof_camera
#*Installation (Driver, Dependencies, SDK, OpenCV)*
./Install_dependencies.sh
#compile and run
/compile.sh
#--------------여기서 부터는 point cloud----------
#installing PCL
sudo apt-get update
sudo apt install libpcl-dev
#compile
cd Arducam_tof_camera/pcl_preview
mkdir build && cd build
cmake ..
make
#run example
./preview_pointcloud
------------------- 위의 세팅과 동일 ------------------
# Pull the repository.
git clone https://github.com/ArduCAM/Arducam_tof_camera.git
cd Arducam_tof_camera
# Installation (Driver, Dependencies, SDK, OpenCV)
./Insall_dependencies.sh
------------------------------------------------------
# Step 4. Installing ROS2
curl -s https://raw.githubusercontent.com/v1ster/rpi-bullseye-ros2/main/install.bash | bash
#Modify enviroment viriables
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
echo "export ROS_DOMAIN_ID=7" >> ~/.bashrc
source ~/.bashrc
sudo apt install python3-colcon-common-extension
## Compile & run ROS2 on your Raspberry Pi
#compile
cd Arducam_tof_camera/ros2_publisher
colcon build --merge-install
#run
. install/setup.bash
ros2 run arducam tof_pointcl
rviz2
사용 용어
nested for loop : 중복 반복문
Contiguous chunks : 데이터 구조 또는 메모리의 일부로서, 연속적으로 저장되어 있는 데이터 요소를 가리킵니다. 연속적으로 저장되어 있으면 주소 공간에서 인접한 위치에 있는 데이터 요소들을 의미합니다. 메모리 레이아웃 및 데이터 구조의 효율성과 관련이 있으며, 데이터 처리 및 액세스에 있어서 중요한 역할을 합니다.
aggregation : 객체 지향 프로그래밍에서 객체 내에 다른 객체를 포함시키는 방법을 가리킵니다. 이를 통해 관련 데이터와 동작을 논리적으로 그룹화하고 관리할 수 있습니다. 예를 들어, 자동차 객체에 엔진, 바퀴, 창문과 같은 하위 객체를 집계할 수 있습니다.
tuple : 프로그래밍에서 사용되는 데이터 구조로, 여러 개의 요소를 포함하는 순서가 있는(ordered) 데이터 형식입니다.
C ordered arrays : 다차원 배열의 데이터 저장 순서를 나타내는 용어입니다. C 언어에서 다차원 배열의 기본적인 저장 순서를 설명하는 것으로, 이 순서를 따르면 배열의 요소가 메모리에 연속적으로 저장됩니다.다차원 배열의 데이터 접근 및 처리를 간단하게 만들며, 메모리 캐싱 등의 이점을 가질 수 있습니다.
channel : 이미지 처리에서 각 컬러 또는 정보의 구성 요소를 나타내며, 이러한 채널을 조합하여 전체 이미지를 생성하거나 처리합니다. 이러한 컬러 채널은 이미지의 각 픽셀에 대한 정보를 저장하는 데 사용됩니다. 빨강 채널은 이미지의 빨간색 성분을, 녹색 채널은 녹색 성분을, 파랑 채널은 파란색 성분을 나타냅니다.
numpy이용
링크 내용 요약
1) stride 이용시
shape=(3,2,2,2) 의미 - 첫 번째 원소 : 행의 수, 두 번째 원소 : 열의 수, 세 번째 원소 : 각 행의 원소의 수, 네 번째 원소 : 각 열의 원소의 수
strides = (8,2,4,1)의 의미 - 첫 번째 원소 : 각 열의 stride 수(하나의 열은 8개를 뛰어 넘어야 함), 두 번째 원소 : 각 행의 stride 수 하나의 행은 2개의 원소씩, 세 번째 원소 : 기존의 행을 유지하기 위한 stride(기존의 행에서는 4개의 stride 이동시 열변경), 네 번째 원소 : 픽셀 수준의 공간 관계 유지를 위해 일정
단일 채널의 경우
2) swapaxes 이용시
reshape의 결과 strides = (8,4,2,1) 이 되어 swapaxes(1,2)를 하면 np.lib.stride_tricks.as_strided함수 사용결과와 동일
여러 채널의 경우
pip install opencv-python
# cv2, numpy library 이용
import cv2
import numpy as np
# 이미지를 읽어옵니다.
image = cv2.imread('your_image.jpg')
# 이미지의 행과 열 수를 얻습니다.
rows, cols, _ = image.shape
# 이미지를 1행 3열로 분할합니다.
num_rows = 1
num_cols = 3
block_width = cols // num_cols
block_height = rows // num_rows
# 이미지를 그리드로 나누어 각 부분을 얻습니다.
blocks = []
for r in range(num_rows):
for c in range(num_cols):
x1 = c * block_width
y1 = r * block_height
x2 = (c + 1) * block_width
y2 = (r + 1) * block_height
block = image[y1:y2, x1:x2]
blocks.append(block)
# 'blocks' 리스트에는 이미지의 각 부분이 저장됩니다.
# 각 부분에 대해 원하는 작업을 수행할 수 있습니다.
OpenCV는 Open Source Computer Vision의 약자로 영상 처리에 사용할 수 있는 오픈 소스 라이브러리 입니다. 컴퓨터가 사람의 눈처럼 인식할 수 있게 처리해주는 역할을 하기도 하며, 우리가 많이 사용하는 카메라 어플에서도 OpenCV가 사용하기도 한다. (추가로 자율주행자동차에서 자동차의 눈이 되주는 것이 카메라와 OpenCV가 합작해서 해낸 일이다.)
gaussian filter, meian filter python 예제
OpenCV
기본 사용법
1.image read 함수
참고영상
BGR형태로 이미지 read
** 참고 : matplot library는 RGB로 read
2. image show 함수
3. image write 함수
4. pycharm 사용시에만
5. 화면 닫기
openCV 설치
python -m pip install opencv-python
anaconda에설치
1) 아나콘다 홈페이지에서 아나콘다 설치
bash ~/Downloads/Anaconda3-2023.07-2-Linux-x86_64.sh
source ~/.bashrc
# conda 환경 생성
conda create -n opencv python=3.8 numpy matplotlib opencv
conda activate opencv-env
#install opencv
conda install -c conda-forge opencv
#check
python
import cv2 as cv
cv.__version__
python 설치
링크텍스트
Median filtering은 window(filter)가 이미지를 지나가면서, Median값(중간값)을 새로운 픽셀 값을 return하여, 수정된 이미지를 갖습니다. Median filtering은 이미지의 노이즈를 없애는데 사용됩니다.
ㅈ
이미지 처리 및 조작을 위해 Python에서 사용하려면 Pillow 라이브러리를 설치하고 가져와야 합니다. 아래는 Pillow 라이브러리를 사용하여 이미지를 불러오는 방법입니다.
-pillow library 설치
pip install Pillow
## 라이브러리 사용
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
def media_filter(img, filter_size(3, 3), stride=1):
img_shape = np.shape(img)
result_shape = tuple( np.int64
(np.array(imag_shape)-np.array(filter_size)/stride+1
))
result = np.zeros(result_shape)
for h in range(0, result_shape[0], stride):
for w in range(0, result_shape[2], stride):
tmp = img[h:h+filter_size[0],w:w+filter_size[1]]
tmp = np.sort(tmp.ravel())
result[h,w] = tmp[int(filter_size[0]*filter_size[1]/2)]
return result
입력으로 image와 filter size와 stride(filter가 한 번에 몇 pixel 움직이는지)를 주면
result를 return합니다.
필터 사이즈가 커질수록 노이즈는 많이 없앨 수 있었지만, 그림이 blur되는 단점이 있음을 알 수 있습니다
장점 - 잡음 제거에 매우 효과적이고, average filter 대비 edge sharpness 보존
단점 - uniform영역의 경우 점, 선 등의 디테일한 요소가 사라져 블러처리됨.
Gaussian smoothing operator는 가우시안 분포를 기반으로 주변 픽셀의 가중 평균을 수행합니다. 이 연산자는 가우시안 노이즈를 제거하는 데 사용되며, 초점이 흐린 렌즈의 현실적인 모델입니다. σ값은 표준편차를 나타내며, 흐림의 양을 정의합니다. gaussian filter는 low pass filter로 고주파를 제거함. 반경 슬라이더는 템플릿의 크기를 제어하는 데 사용됩니다. 시그마의 큰 값은 큰 템플릿 크기에만 큰 흐림을 제공합니다 슬라이더를 사용하여 노이즈를 추가할 수 있습니다. 가우시안 필터는 스텝 함수 입력에 대한 오버슛 없이 빠른 rise, decline time을 최소화하는 특성을 가지고 있습니다. 이러한 행동은 가우시안 필터가 최소 그룹 딜레이를 가지고 있기 때문입니다.
wikipedia
수식 참조
gaussian filter
채널 (Channel) : 이미지의 각 채널은 이미지의 색상 또는 정보의 차원을 나타낸다. 컬러 이미지의 경우, 일반적으로 Red (빨강), Green (초록), Blue (파랑) 채널이 있으며, 각 채널은 해당 색상 정보를 포함합니다. 그레이스케일 이미지는 단일 채널을 가지며 각 픽셀은 흑백 레벨 정보를 나타냅니다. 채널은 이미지의 각 요소에 대한 정보를 제공하며, 컬러 조정 및 이미지 처리 작업에서 중요한 역할을 합니다.
커널 (Kernel) : 커널은 이미지 처리에서 사용되는 필터 또는 마스크로, 이미지에 적용되어 특정 연산을 수행하는 작은 행렬입니다. 이미지의 각 픽셀에 대해 커널이 이동하면서 연산을 수행하고, 이를 통해 이미지를 변경하거나 특정 특징을 강조할 수 있습니다. 일반적인 이미지 처리 작업에는 블러링, 경계 감지, 엣지 검출 및 특징 추출과 같은 작업에서 커널이 사용됩니다. 예를 들어, 이미지의 가우시안 블러링을 수행하기 위해 가우시안 필터 커널을 사용할 수 있습니다.
채널과 커널은 이미지 처리와 컴퓨터 비전 분야에서 중요한 개념으로, 이미지의 정보를 추출하고 변경하는 데 사용됩니다.
mean filter의 단점 : 필터링 대상 위치에서 가까이 있는 픽셀과 멀리 있는 픽셀이 모두 같은 가
중치를 사용하여 평균을 계산하여, 멀리 있는 픽셀의 영향을 많이 받을 수 있음.
Gaussian filter 쓰는 이유 : 중앙값만 도드라지게 보고 주변은 잘안보이게 하는 마스킹의 형태로
스무스하게 만들어줍니다.
가우시안 필터는 선형 필터로 일반적으로 이미지를 흐리게 하거나 노이즈를 줄이는 데 사용 됩니다. mean filter와 gaussian filter 두 가지를 사용 해서 흐리게하고 뺄 경우 가장자리 감지에 사용할 수 있습니다. 엣지 검출은 가우스 필터 만으로는 가장자리가 흐려지게 되고 대비가 줄어들기에 힘들다.
median filter의 경우 edge 검출은 우수하나 gaussian보다 느림.
mean filter와 gaussian filter의 장, 단점
##library
import scipy
import cv2
import numpy as np
import matplotlib.pyplot as plt
import math
##1D Gaussian filter
def genGausKernel1D(width, sigma):
arr = np.arange((width//2)*(-1), (width//2)+1)
#중심에서부터의 거리를 계산함,
arr = np.array([float(x) for x in arr])
#float 처리를 해주지 않으면 값이 달라질 수 있어서 처리해주었다
kernel_1d= np.exp((-arr*arr)/(2*sigma**2))
#위에서 봤던 수식을 그대로 적용했다. 달라진 점은, 앞에 상수로 나눠주는 부분을 생략한건데
#어차피 나중에 커널 전체 값의 합을 1로 만들기 위해서 커널 전체의 합으로 나눠주기 때문에
#상수부분이 필요 없다고 생각해서 나누지 않았다
kernel_1d /= kernel_1d.sum()
#kernel은 모든 element의 합이 1이어야하기 때문에 전체 수의 합으로 나눠준다.
#비율이 중요하다는 뜻으로 해석했다.
return np.array([kernel_1d])
##CV 이용시 한번에 가능
kernel_1d = cv2.getGaussianKernel(5, 3)
# getGaussiankernel(width, sigma)의 형태임
2D gaussian filter의 경우 point-spread 형식의 그래프라고 하는데, 맨 윗 점에서 퍼지는 모양으로 존재한다는 뜻이다. convolution으로 얻을 수 있고, array에 값으로 저장되기 때문에 추가적인 처리가 필요하다.
## library , matplotlib는 visualization에 사용
import scipy
import cv2
import numpy as np
import matplotlib.pyplot as plt
import math
### 2D gaussian filter
def genGaussianKernel(width, sigma):
array = np.arange((width//2)*(-1), (width//2)+1)
#중심에서부터의 거리 계산
arr = np.zeros((width, width))
#x^2+y^2 부분을 미리 계산해둘 매트릭스 initialize
for x in range(width):
for y in range(width):
arr[x,y] = array[x]**2+array[y]**2
#중심에서부터의 거리를 제곱합으로 계산
kernel_2d = np.zeros((width, width))
#커널의 값을 저장할 매트릭스 생성
for x in range(width):
for y in range(width):
kernel_2d[x,y] = np.exp(-arr[x,y]/(2*sigma**2))
#수식에 맞게 값 저장(역시나 상수 부분은 생략)
kernel_2d /= kernel_2d.sum()
#전체 값의 합으로 나누어 필터 전체의 합이 1이 되도록 함
return kernel_2d
### 이미지 로딩
lena = cv2.imread('SourceImages/lena.bmp', 0)
# 0 represents gray-scale
#(1 for unchanged, -1 for color - default)
lena_noise = cv2.imread('SourceImages/lena_noise.bmp', 0)
##위 함수를 이용 두개의 필터(커널) 생성
kernel_1 = genGaussianKernel(5,1) # 5 by 5 kernel with sigma of 1
kernel_2 = genGaussianKernel(11,3) # 11 by 11 kernel with sigma of 3
##두 필터로 이미지 변환
res_lena_kernel1 = cv2.filter2D(lena, -1, kernel_1)
# cv2.filter2D(src, ddepth, kernel)
# src : input
# ddepth = -1 : return type same as the source
# kernel (= mask)
res_lena_kernel2 = cv2.filter2D(lena, -1, kernel_2)
res_lena_noise_kernel1 = cv2.filter2D(lena_noise, -1, kernel_1)
res_lena_noise_kernel2 = cv2.filter2D(lena_noise, -1, kernel_2)
python 예제 - OpenCV
morphology
다양한 filter 예제
모폴로지(morphology)란 '형태학'이라는 뜻입니다. 이는 영상 분야에서 노이즈 제거, 구멍 채우기, 끊어진 선 이어 붙이기 등에 쓰이는 형태학적 연산을 말합니다. 모폴로지 연산은 검은색과 흰색으로만 구성되어 있는 바이너리(binary) 이미지에 적용할 수 있습니다. 모폴로지 연산으로는 침식, 팽창, 열림, 닫힘이 있다.
침식(erosion)이란 말 그대로 형태를 깎아 내는 것입니다. 따라서 침식 연산은 이미지를 깎아 내는 연산을 뜻합니다. 침식 연산을 위해서는 구조화 요소 커널(structuring element kernel)이라는 0과 1로 구성된 커널이 필요합니다. 구조화 요소 커널은 1이 채워진 모양에 따라 사각형, 타원형, 십자형 등으로 사용할 수 있습니다.
침식 연산은 구조화 요소 커널을 입력 이미지에 적용해서 1로 채워진 영역을 온전히 올려 놓을 수 없으면 해당 픽셀을 0으로 변경합니다. 아래는 십자형 구조화 요소 커널로 침식 연산을 하는 과정을 보여줍니다.
erosion의 코드 구조
python 예제
# 침식 연산 (morph_erode.py)
import cv2
import numpy as np
img = cv2.imread('../img/morph_dot.png')
# 구조화 요소 커널, 사각형 (3x3) 생성 ---①
k = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
# 침식 연산 적용 ---②
erosion = cv2.erode(img, k)
# 결과 출력
merged = np.hstack((img, erosion))
cv2.imshow('Erode', merged)
cv2.waitKey(0)
cv2.destroyAllWindows()
erosion의 경우, 노이즈 제거 효과도 있고, 원래는 떨어져 있는 물체인데 겹쳐 있는 것을 서로 떼어내는 데도 효과적입니다.
팽창(dilatation)은 침식과 반대로 물체의 주변을 확장하는 연산입니다. 연산 방법도 반대입니다. 침식 연산은 구조화 요소 커널이 입력 영상에서 1로 채워진 영역과 완전히 겹치지 않으면 0으로 변경했습니다. 그러나 팽창 연산은 이와 반대로 완전히 겹치지 않으면 1로 변경합니다.
팽창을 위한 함수는 아래와 같습니다.
dst = cv2.dilate(src, kernel, dst, anchor, iterations, bordeType, borderValue)
모든 파라미터는 cv2.erode()와 동일합니다.
src : 입력 영상
kernel : 구조 요소. getStructuringElement() 함수에 의해 생성 가능. 만약 None을 지정하면 3x3 사각형 구성 요소를 사용.
dst : 출력 영상. src와 동일한 크기와 타입.
anchor : 고정점 위치. 기본값 (-1, -1)을 사용하면 중앙점을 사용.
iterations : 반복 횟수. 기본값은 1.
borderType : 가장자리 픽셀 확장 방식. 기본값은 cv2.BORDER_CONSTANT.
borderValue : cv2.BORDER_CONSTANT인 경우, 확장된 가장자리 픽셀을 채울 값.
python 코드 예시
# 팽창 연산 (morph_dilate.py)
import cv2
import numpy as np
img = cv2.imread('../img/morph_hole.png')
# 구조화 요소 커널, 사각형 (3x3) 생성 ---①
k = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
# 팽창 연산 적용 ---②
dst = cv2.dilate(img, k)
# 결과 출력
merged = np.hstack((img, dst))
cv2.imshow('Dilation', merged)
cv2.waitKey(0)
cv2.destroyAllWindows()
침식은 어두운 부분의 노이즈를 제거하는 효과가 있고 팽창은 밝은 부분의 노이즈를 제거하는 효과가 있다는 것을 살펴봤습니다. 노이즈 제거 효과는 좋으나 원래 모양이 홀쭉해지거나 뚱뚱해지는 변형이 일어납니다. 하지만 침식과 팽창의 연산을 조합하면 원래의 모양을 유지하면서 노이즈를 제거하는 효과를 거둘 수 있습니다.
열림 = 침식 + 팽창
닫힘 = 팽창 + 침식
OpenCV는 열림, 닫힘, 그레디언트, 탑햇, 블랙햇 연산을 위해서 아래의 함수를 제공합니다.
dst = cv2.morphologyEx(src, op, kernel, dst, anchor, iteration, borderType, borderValue)
src: 입력 영상
op: 모폴로지 연산 종류 (cv2.MORPH_OPEN: 열림 연산, cv2.MORPH_COLSE: 닫힘 연산, cv2.MORPH_GRADIENT: 그레디언트 연산, cv2.MORPH_TOPHAT: 탑햇 연산, cv2.MORPH_BLACKHAT: 블랙햇 연산)
kernel: 구조화 요소 커널
dst(optional): 결과 영상
anchor(optional): 커널의 기준점
iteration(optional): 연산 반복 횟수
borderType(optional): 외곽 영역 보정 방법
borderValue(optional): 외곽 영역 보정 값
python 코드 예시
# 열림과 닫힘 연산으로 노이즈 제거 (morph_open_close.py)
import cv2
import numpy as np
img1 = cv2.imread('../img/morph_dot.png', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('../img/morph_hole.png', cv2.IMREAD_GRAYSCALE)
# 구조화 요소 커널, 사각형 (5x5) 생성 ---①
k = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
# 열림 연산 적용 ---②
opening = cv2.morphologyEx(img1, cv2.MORPH_OPEN, k)
# 닫힘 연산 적용 ---③
closing = cv2.morphologyEx(img2, cv2.MORPH_CLOSE, k)
# 결과 출력
merged1 = np.hstack((img1, opening))
merged2 = np.hstack((img2, closing))
merged3 = np.vstack((merged1, merged2))
cv2.imshow('opening, closing', merged3)
cv2.waitKey(0)
cv2.destroyAllWindows()
팽창 연산을 적용한 이미지에서 침식 연산을 적용한 이미지를 빼면 경계 픽셀만 얻게 되는데, 이는 앞서 살펴본 경계 검출과 비슷합니다. 이런 연산을 그레디언트(gradient) 연산이라고 합니다.
그레디언트 = 팽창 - 침식
python 코드 예시
# 모폴로지 그레이언트 (morph_gradient.py)
import cv2
import numpy as np
img = cv2.imread('../img/morphological.png')
# 구조화 요소 커널, 사각형 (3x3) 생성 ---①
k = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
# 열림 연산 적용 ---②
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, k)
# 결과 출력
merged = np.hstack((img, gradient))
cv2.imshow('gradient', merged)
cv2.waitKey(0)
cv2.destroyAllWindows()
또한, 원본에서 열림 연산 적용 결과를 빼면 값이 크게 튀는 밝은 영역을 강조할 수 있고, 닫힘 연산 적용 결과에서 원본을 빼면 어두운 부분을 강조할 수 있습니다. 이것을 각각 탑햇(top hat)과 블랙햇(black hat) 연산이라고 합니다.
탑햇 = 원본 - 열림
블랙햇 = 닫힘 - 원본
탑햇은 달의 밝은 부분을 강조하고, 블랙햇은 달의 어두운 부분을 강조합니다.
python 코드 예시
# 모폴로지 탑햇, 블랙햇 연산 (morph_hat.py)
import cv2
import numpy as np
img = cv2.imread('../img/moon_gray.jpg')
# 구조화 요소 커널, 사각형 (5x5) 생성 ---①
k = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
# 탑햇 연산 적용 ---②
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, k)
# 블랫햇 연산 적용 ---③
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, k)
# 결과 출력
merged = np.hstack((img, tophat, blackhat))
cv2.imshow('tophat blackhat', merged)
cv2.waitKey(0)
cv2.destroyAllWindows()
바이레터럴 필터는 이미지에 대한 비선형적이면서 엣지를 보존하며, 노이즈를 감소시키는 스무딩 필터입니다. 각 픽셀의 강도를 해당 픽셀 주변의 강도 값들의 가중 평균으로 대체합니다. 이 가중치는 가우시안 분포를 기반으로 할 수 있습니다. 중요한 것은 가중치가 픽셀 간의 유클리드 거리뿐만 아니라(예: 색상 강도, 깊이 거리 등)에 따라 달라진다는 것입니다. 이것은 날카로운 엣지를 보존합니다.
그러나 연산시간이 오래걸림.
양방향 필터 - Bilateral filter
가우시안 필터를 양쪽 방향으로 두번 한다고해서 이름이 붙여졌습니다.
평균 값 필터 또는 가우시안 필터는 에지 부근에서도 픽셀 값을 평탄하게 만드는 단점이 있습니다.
양방향 필터는 에지가 아닌 부분에서만 블러링을 합니다.
평탄한 부분은 가우시안 필터르 이용하고, 엣지 부분이면 가우시안의 일부분만 가져와 필터링을 합니다.
따라서 에지를 보존할 수 있습니다.
양방향 필터는 에지가 아닌 부분에서만 블러링을 합니다.
평탄한 부분은 가우시안 필터르 이용하고, 엣지 부분이면 가우시안의 일부분만 가져와 필터링을 합니다.
따라서 에지를 보존할 수 있습니다.
양방향 필터는 기준 픽셀과 이웃 픽셀과의 거리, 그리고 픽셀 값의 차이를 함께 고려하여 블러링 정도를 조절합니다.
bilateral
#rpi.gpio 설치
pip install RPi.GPIO