728x90
영상 필터링
블러링 : 평균값 필터
가우시안 필터
Gaussian filtering
가우시안 필터 적용 결과
샤프닝 필터 구현
샤프닝 필터
양방향 필터
OpenCV Bitwise
기하학적 변환
Affine transform
- 𝐿𝑖𝑛𝑒𝑎𝑟 𝑡𝑟𝑎𝑛𝑠𝑓𝑜𝑟𝑚
- 휘어짐이 없고 평행한 선들은 평행을 유지하는 변환
- 이동, 회전, 스케일 및 이들의 조합에 의한 변환
- 𝑥' = 𝑎0𝑥 + 𝑎1𝑦 + 𝑎2, 𝑦' = 𝑏0𝑥 + 𝑏1𝑦 + 𝑏2
- ℎ𝑜𝑚𝑜𝑔𝑒𝑛𝑒𝑜𝑢𝑠 𝑐𝑜𝑜𝑟𝑑𝑖𝑛𝑎𝑡𝑒 𝑠𝑦𝑠𝑡𝑒𝑚 사용
위치 이동
회전 이동
영상 확대
전단 변환 (Shearing)
Warping
- Nonlinear transform (rubber sheet transform)
- pixel별로 이동 정도를 다르게 할 수 있어서 고무판 위에 그려진 영상을 임의대로 구부리는 것과 같은 효과를 낼 수 있음
- 고차항을 사용하여 일반화된 다항식으로 표현
Interpolation 이란?
- 결과 픽셀에 정확하게 대응되는 입력 픽셀이 없는 경우 주변 픽셀들을 고려하여 새로운 값을 생성하는 방법
Interpolation 종류
- 최근접 이웃 보간법(Nearest neighbor interpolation)
- 이웃 평균 보간법(Neighbor averaging interpolation)
- 양선형 보간법(Bilinear interpolation)
- 고차 보간법 (Higher order interpolation)
Nearest neighbor interpolation
- 계산한 위치에서 가장 가까운 원시 픽셀을 선택하는 방법
- 처리 속도는 빠르지만 결과 영상의 질이 좋지 않음
- (e.g.) I(10,11) -> d(9.8,9.2) ~~ d(10,9)=55
Neighbor averaging interpolation
- 이웃들의 평균 계산 (2차원의 경우 4개 이웃 사용)
- 최근접 이웃 보간법에 비해 계산량은 많지만 조금 더 만족스러운 결과 제공
- (e.g.) I(10,11) -> d(9.8,9.2) = (50+44+55+48)/4 ~~ 49
Bilinear interpolation
- 새로운 픽셀을 생성하기 위해 네 개의 가장 가까운 픽셀들에 가중치를 곱한 값들의 합을 사용
- 조금 더 자연스러운 영상을 산출
OpenCV를 이용한 기하학적 변환
import numpy as np import cv2 import sys import matplotlib.pyplot as plt from pathlib import Path |
영상 필터링 (Filtering)
2D Convolution
# cv2.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) -> dst # src: 입력영상 # ddepth: 출력영상의 타입 (cv2.CV_8U, cv2.CV_32F, cv2.CV_64F), # -1 => 입력영상과 같은 타입 # kernel: filter 행렬, 실수형 # anchor: (-1, -1) 필터의 중앙점 # delta: 더할 값 # borderType: 가장자리 픽셀확장 방식 # dst: 출력영상 # blur(src, ksize[, dst[, anchor[, borderType]]]) -> dst # src: 입력영상 # ksize: mean filter kernel size |
folder = "fig" |
## 영역처리, 영상 필터링, Convolution # src = cv2.imread("./fig/blue_eyes.png", cv2.IMREAD_REDUCED_COLOR_2) src = cv2.imread(Path(folder, "blue_eyes.png"), cv2.IMREAD_REDUCED_COLOR_2) kernel_3 = np.ones((3, 3), dtype = np.float64)/9. dst_kernel = cv2.filter2D(src, -1, kernel_3) dst_blur = cv2.blur(src, (3, 3)) cv2.imshow('src', src) cv2.imshow('dst_kernel', dst_kernel) cv2.imshow("dst_blur", dst_blur) cv2.waitKey() cv2.destroyAllWindows() |
src = cv2.imread(Path(folder, "blue_eyes.png"), cv2.IMREAD_REDUCED_COLOR_2) cv2.imshow("src", src) for ksize in (3, 5, 7, 9, 12, 15, 23): dst = cv2.blur(src, (ksize, ksize)) text = '{} x {}'.format(ksize, ksize) cv2.putText(dst, text, (20, 30), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA) cv2.imshow('mean filter', dst) cv2.waitKey() cv2.destroyAllWindows() |
가우시안 필터
# GaussianBlur(src, (ksize), sigmaX[, dst[, sigmaY[, borderType]]]) -> dst # src: 입력영상 # ksize: mean filter kernel size, (0, 0) 자동으로 결정 # sigmaX: gaussian x 방향의 sigma # sigmaY: gaussian y 방향의 sigma |
## 가우시안 필터 src = cv2.imread(Path(folder, "blue_eyes.png"), cv2.IMREAD_COLOR) dst_Gaussian1 = cv2.GaussianBlur(src, (0, 0), 1) dst_mean = cv2.blur(src, (5,5)) # dst_Gaussian2 = cv2.GaussianBlur(src, (0, 0), 2) # dst_Gaussian3 = cv2.GaussianBlur(src, (0, 0), 3) cv2.imshow('src', src) cv2.imshow("Gaussian1", dst_Gaussian1) cv2.imshow("dst_mean", dst_mean) # cv2.imshow("Gaussian2", dst_Gaussian2) # cv2.imshow("Gaussian3", dst_Gaussian3) cv2.waitKey() cv2.destroyAllWindows() |
사프닝 필터링
## Sharpening filter src = cv2.imread(Path(folder, "blue_eyes.png"), cv2.IMREAD_REDUCED_COLOR_2) blr = cv2.GaussianBlur(src, (0, 0), 1) blr2 = cv2.GaussianBlur(src, (0, 0), 2) blr3 = cv2.GaussianBlur(src, (0, 0), 3) dst = cv2.addWeighted(src, 2, blr, -1, 0.0) dst2 = cv2.addWeighted(src, 2, blr2, -1, 0.0) dst3 = cv2.addWeighted(src, 2, blr3, -1, 0.0) cv2.imshow('src', src) cv2.imshow("blr", blr) cv2.imshow("sharpening1", dst) cv2.imshow("sharpening2", dst2) cv2.imshow("sharpening3", dst3) cv2.waitKey() cv2.destroyAllWindows() # [[ 0. -1. 0.] # [-1. 5. -1.] # [ 0. -1. 0.]] # [[-0.2 -0.8 -0.2] # [-0.8 5. -0.8] # [-0.2 -0.8 -0.2]] # src = cv2.imread('blue_eyes.png', cv2.IMREAD_REDUCED_COLOR_2) # kernel = np.ones((3, 3), dtype = np.float64)*-1 # kernel[1,1] = 9 # #print(kernel) # dst = cv2.filter2D(src, -1, kernel) # cv2_imshow(src) # cv2_imshow(dst) |
## sharpen filter src = cv2.imread(Path(folder, "blue_eyes.png")) kernel_3 = np.ones((3, 3), dtype = np.float64)*-.5 kernel_3[1, 1] = 5 dst_kernel = cv2.filter2D(src, -1, kernel_3) cv2.imshow('src', src) cv2.imshow('dst_kernel', dst_kernel) plt.imshow(kernel_3, cmap="seismic") plt.colorbar() plt.show() # cv2.imshow("dst_blur", dst_blur) cv2.waitKey() cv2.destroyAllWindows() print(kernel_3) |
중앙값 필터링
## median filter src = cv2.imread(Path(folder, "blue_eyes.png"), cv2.IMREAD_GRAYSCALE) salt_noise = np.random.choice((0, 255), src.shape, p = (0.99, 0.01)).astype(np.uint8) pepper_noise = np.random.choice((0, 255), src.shape, p = (0.99, 0.01)).astype(np.uint8) dst = cv2.add(src, salt_noise) dst = cv2.subtract(dst, pepper_noise) dst_median = cv2.medianBlur(dst, 3) # dst_Gaussian = cv2.GaussianBlur(dst, (0, 0), 1) cv2.imshow("src", src) # cv2.imshow("salt_noise", salt_noise) # cv2.imshow("pepper_noise", pepper_noise) cv2.imshow("dst", dst) cv2.imshow("dst_median", dst_median) # cv2.imshow("dst_Gaussian", dst_Gaussian) while True: if cv2.waitKey() == ord("q"): break cv2.destroyAllWindows() |
양방향 필터 (Bilateral filter)
# bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]]) -> dst # src: 입력영상 # d: -1로 설정 # sigmaColor: 색공간의 표준편차 # sigmaSpace: 좌표공간의표준편차 # dst: # borderType: 가장자리 픽셀확장 방식 |
카툰 필터
## bitwise operator src1 = np.zeros((256, 256), np.uint8) cv2.rectangle(src1, (10, 10), (127, 245), 255, -1) src2 = np.zeros((256, 256), np.uint8) cv2.circle(src2, (127, 127), 100, 128, -1) dst1 = cv2.bitwise_and(src1, src2) dst2 = cv2.bitwise_or(src1, src2) dst3 = cv2.bitwise_xor(src1, src2) dst4 = cv2.bitwise_not(src2) cv2.imshow("src1", src1) cv2.imshow('src2', src2) cv2.imshow("AND", dst1) cv2.imshow("OR", dst2) cv2.imshow("XOR", dst3) cv2.imshow("NOT", dst4) cv2.waitKey() cv2.destroyAllWindows() |
## Cartoon 필터 time = cv2.TickMeter() # src = cv2.imread("./fig/son.jpg") src = cv2.imread(Path(folder, "son.jpg")) time.start() ### 연산 구간 for i in range(100): blr = cv2.GaussianBlur(src, (0, 0), 2) edge = 255 - cv2.Canny(src, 100, 200) edge = cv2.cvtColor(edge, cv2.COLOR_GRAY2BGR) dst = cv2.bitwise_and(blr, edge) ### time.stop() cv2.imshow("son", src) cv2.imshow("blr", blr) cv2.imshow("edge", edge) cv2.imshow("dst", dst) print(time.getTimeMilli(), "ms") time.reset() cv2.waitKey() cv2.destroyAllWindows() |
260.1467 ms
기하학적 변환 (Geometric transform)
영상 이동 (Translation)
# warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst # src: 입력영상 # M: affine transform matrix (size: 2 x 3) # dsize: 출력영상 크기, (0, 0) = 입력영상크기로 출력 # borderValue: 값이 없는 영역을 채우는 값, default = 0 |
## 영상 이동 (Translation) # src = cv2.imread("./fig/dog.bmp") src = cv2.imread(Path(folder, "dog.bmp")) ## affine matrix affine = np.array([[1, 0, 50], [0, 1, 200]], np.float32) print("affine matrix: \n", affine) # print(affine.dtype) dst = cv2.warpAffine(src, affine, (0, 0), borderMode = cv2.BORDER_CONSTANT, borderValue=(255, 255, 255)) # dst = cv2.warpAffine(src, affine, (0, 0)) cv2.imshow("src", src) cv2.imshow("dst", dst) cv2.waitKey() cv2.destroyAllWindows() |
affine matrix:
[[ 1. 0. 50.]
[ 0. 1. 200.]]
영상 회전 (Rotation)
# warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst # src: 입력영상 # M: affine transform matrix (size: 2 x 3) # dsize: 출력영상 크기, (0, 0) = 입력영상크기로 출력 # borderValue: 값이 없는 영역을 채우는 값, default = 0 # getRotationMatrix2D(center, angle, scale) -> retval # center: 영상의 center # angle: 회전각도 # scale: 확대율 |
## 회전 변환 (Rotation) src = cv2.imread(Path(folder, "dog.bmp")) cp = (src.shape[1]/2, src.shape[0]/2) affine = cv2.getRotationMatrix2D(cp, 30, 1.) dst = cv2.warpAffine(src, affine, (0, 0)) cv2.imshow("src", src) cv2.imshow("dst", dst) cv2.waitKey() cv2.destroyAllWindows() |
영상 확대 (Scaling)
## 영상 확대 (Scaling) # src = cv2.imread("./fig/rose.jpg") src = cv2.imread(Path(folder, "rose.jpg")) print("src shape : ", src.shape) dst1 = cv2.resize(src, (1900, 1300), interpolation=cv2.INTER_NEAREST) dst2 = cv2.resize(src, (1900, 1300), interpolation=cv2.INTER_LINEAR) dst3 = cv2.resize(src, (1900, 1300), interpolation=cv2.INTER_CUBIC) cv2.imshow("src", src) cv2.imshow('INTER_NEAREST', dst1[800:1600, 800:1200]) cv2.imshow('INTER_LINEAR', dst2[800:1600, 800:1200]) cv2.imshow('INTER_CUBIC', dst3[800:1600, 800:1200]) cv2.waitKey() cv2.destroyAllWindows() |
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[3], line 3
1 ## 영상 확대 (Scaling)
2 # src = cv2.imread("./fig/rose.jpg")
----> 3 src = cv2.imread(Path(folder, "rose.jpg"))
5 print("src shape : ", src.shape)
7 dst1 = cv2.resize(src, (1900, 1300), interpolation=cv2.INTER_NEAREST)
NameError: name 'folder' is not defined
영상 전단 (Shearing)
## Shearing src = cv2.imread(Path(folder, "dog.bmp")) affine = np.array([[1, 0.2, 0], [0.2, 1, 0 ]], np.float32) dst = cv2.warpAffine(src, affine, (0, 0)) cv2.imshow("src", src) cv2.imshow("dst", dst) cv2.waitKey() cv2.destroyAllWindows() |
비선형 변환 (Perspective transform)
# getPerspectiveTransform(src, dst[, solveMethod]) -> retval # src: 입력영상의 4개 좌표점, numpy array shape(4,2) # dst: 출력영상의 4개 좌표점, numpy array shape(4,2) |
## Non linear warping # src = cv2.imread("./fig/checkerboard.png") src = cv2.imread(Path(folder, "checkerboard.png")) h, w = src.shape[:2] srcPoint = np.array([[218, 48], [691, 47], [830, 518], [67, 527]], np.float32) dstPoint = np.array([[0, 0], [w-1, 0], [w-1, h-1], [0, h-1]], np.float32) pers = cv2.getPerspectiveTransform(srcPoint, dstPoint) # array([[ 2.13264257e+00, 6.72294421e-01, -4.97186212e+02], # [ 4.08735101e-03, 1.93331703e+00, -9.36902599e+01], # [-1.86504523e-05, 1.36282733e-03, 1.00000000e+00]]) dst = cv2.warpPerspective(src, pers, (w, h)) # a, b, c, d = cv2.selectROI(src) # print(a, b, c, d) print("width = ", w, "height = ", h) cv2.imshow("src", src) cv2.imshow("dst", dst) cv2.waitKey() cv2.destroyAllWindows() |
width = 960 height = 540
비선형 리매핑
# remap(src, map1, map2, interpolation[, dst[, borderMode[, borderValue]]]) -> dst |
## remapping # src = cv2.imread("./fig/bamboo.jpg") src = cv2.imread(Path(folder, "bamboo.jpg")) h, w = src.shape[:2] map2, map1 = np.indices((h, w), np.float32) # print(map1) print("") print(map2) map1 = map1 + 10*np.sin(map2/32) dst = cv2.remap(src, map1, map2, cv2.INTER_CUBIC) cv2.imshow('src', src) cv2.imshow('dst', dst) cv2.waitKey() cv2.destroyAllWindows() |
[[ 0. 0. 0. ... 0. 0. 0.]
[ 1. 1. 1. ... 1. 1. 1.]
[ 2. 2. 2. ... 2. 2. 2.]
...
[597. 597. 597. ... 597. 597. 597.]
[598. 598. 598. ... 598. 598. 598.]
[599. 599. 599. ... 599. 599. 599.]]
728x90
'AI 개론' 카테고리의 다른 글
AI 개론 _ OpenCV를 이용한 컴퓨터 비전3 + OpenCV를 이용한 객체 검출, 동영상 처리 실습 (0) | 2025.04.09 |
---|---|
AI 개론 _ OpenCV를 이용한 컴퓨터 비전 + opencv를 이용한 영상 정규화 실습 (0) | 2025.04.09 |