๐ ๊ณต๋ถํ๋ ์ง์ง์ํ์นด๋ ์ฒ์์ด์ง?
[v0.18]์์์ฒ๋ฆฌ_ ์ค์ตํ๊ธฐ(๋ชจ์์ดํฌ ์ฒ๋ฆฌ, ๋ฆฌํดํ์ด, ์๊ณก ๊ฑฐ์ธ ์ด๋ฏธ์ง ๋คํ๊ธฐ) ๋ณธ๋ฌธ
[v0.18]์์์ฒ๋ฆฌ_ ์ค์ตํ๊ธฐ(๋ชจ์์ดํฌ ์ฒ๋ฆฌ, ๋ฆฌํดํ์ด, ์๊ณก ๊ฑฐ์ธ ์ด๋ฏธ์ง ๋คํ๊ธฐ)
์ง์ง์ํ์นด 2022. 1. 8. 00:58220108 ์์ฑ
<๋ณธ ๋ธ๋ก๊ทธ๋ ๊ทํ์ด ์์ฌ๋์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํด์ ๊ณต๋ถํ๋ฉฐ ์์ฑํ์์ต๋๋ค>
OpenCV - 16. ๋ชจ์์ดํฌ ์ฒ๋ฆฌ(Mosaic), ๋ฆฌํดํ์ด(Liquify), ์๊ณก ๊ฑฐ์ธ(Distortion Mirror)
์ด๋ฒ ํฌ์คํ ์์๋ ์ง๊ธ๊น์ง ๋ฐฐ์ ๋ ๋ด์ฉ์ ๊ธฐ๋ฐ์ผ๋ก ์ค์ต์ ํด๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฒ ํฌ์คํ ์ญ์ 'ํ์ด์ฌ์ผ๋ก ๋ง๋๋ OpenCV ํ๋ก์ ํธ(์ด์ธ์ฐ ์ )'๋ฅผ ์ ๋ฆฌํ ๊ฒ์์ ๋ฐํ๋๋ค. ์ฝ๋: github.com/BaekKyunSh
bkshin.tistory.com
1. ์ค์ต 1 : ๋ชจ์์ดํฌ ์ฒ๋ฆฌ
: ์ด๋ฏธ์ง์ ํน์ ์์ญ์ ๋ง์ฐ์ค๋ก ํด๋ฆญํ๋ฉด ๋ชจ์์ดํฌ ์ฒ๋ฆฌ
: ๋ชจ์์ดํฌ๋ฅผ ์ ์ฉํ ๊ด์ฌ ์์ญ์ ์ด๋ฏธ์ง๋ฅผ ํน์ ๋น์จ๋ก ์ถ์์ํจ ๋ค ๋ค์ ํ๋
: ํฌ๊ธฐ๊ฐ ์์ ์ด๋ฏธ์ง๋ฅผ ์ต๋ ํฝ์ ๊ฐ ์ด์์ ํฌ๊ธฐ๋ก ํ๋ํ๋ฉด ์ด๋ฏธ์ง๊ฐ ๊นจ์ง๋ ์๋ฆฌ๋ฅผ ์ ์ฉ
: ๊ด์ฌ ์์ญ์ ์ถ์ํ๋ค๊ฐ ๋ค์ ํ๋ํ๋ฉด ์๋์ ํฝ์ ๊ณผ ๋น์ทํ๊ธด ํ์ง๋ง,
๋ณด๊ฐ๋ฒ์ ์ํด์ ์ฐ์ฐํ ๊ฒฐ๊ณผ๋ผ์ ์ ๋ช ๋๊ฐ ๋จ์ด์ ธ ๋ฟ์๊ฒ ๋ณด์ (์ด๋ ๋ณด๊ฐ๋ฒ์ cv2.INTER_AREA๋ฅผ ์ฌ์ฉ)
# ๋ชจ์์ดํฌ ์ฒ๋ฆฌ
import cv2
rate = 15 # ๋ชจ์์ดํฌ์ ์ฌ์ฉํ ์ถ์ ๋น์จ (1/rate)
win_title = 'mosaic' # ์ฐฝ ์ ๋ชฉ
img = cv2.imread('img/sample.jpeg') # ์ด๋ฏธ์ง ์ฝ๊ธฐ
while True:
x,y,w,h = cv2.selectROI(win_title, img, False) # ๊ด์ฌ์์ญ ์ ํ
if w and h:
roi = img[y:y+h, x:x+w] # ๊ด์ฌ์์ญ ์ง์
roi = cv2.resize(roi, (w//rate, h//rate)) # 1/rate ๋น์จ๋ก ์ถ์
# ์๋ ํฌ๊ธฐ๋ก ํ๋
roi = cv2.resize(roi, (w,h), interpolation=cv2.INTER_AREA)
img[y:y+h, x:x+w] = roi # ์๋ณธ ์ด๋ฏธ์ง์ ์ ์ฉ
cv2.imshow(win_title, img)
else:
break
cv2.destroyAllWindows()
- rate ๊ฐ ์ปค์ง์๋ก ๋ ํฐ ๋น์จ๋ก ์ถ์ํ๋ค๊ฐ ๋ค์ ํ๋๋์ด ํฝ์ ์ด ๋ง์ด ๊นจ์ง๋ค
2. ์ค์ต 2 : ๋ฆฌํดํ์ด ๋๊ตฌ
: ๋ฆฌํดํ์ด, ์ด๋ฏธ์ง์ ์ํ๋ ๋ถ๋ถ๋ง ์๊ฒ ํ๊ฑฐ๋ ํฌ๊ฒ ํ๋ ๊ธฐ๋ฅ
: Liquify๋ '์ก์ฒด๋ก ๋ง๋ค๋ค'๋ผ๋ ๋ป์ผ๋ก ์ด๋ฏธ์ง์ ์ผ๋ถ๋ถ์ ์ก์ฒด์ฒ๋ผ ํ๋ฌผ๊ฑฐ๋ฆฌ๊ฒ ๋ฐ๊พธ๋ ํจ๊ณผ
- ์ฌ๊ฐํ ์์ญ์ 4๊ฐ์ ์ผ๊ฐํ ์์ญ์ผ๋ก ๋๋๊ธฐ
- ๋ง์ฐ์ค์ ์์น๋ฅผ ๊ฐ์ด๋ฐ ๊ต์ฐจ์ ์ผ๋ก ๋๊ธฐ
- ๋ง์ฐ์ค๋ฅผ ๋๋๊ทธํ๋ฉด ๊ต์ฐจ์ ์ ์์น๊ฐ ์ค๋ฅธ์ชฝ๊ณผ ๊ฐ์ด ๋ณํ๊ธฐ
- ๊ฐ 4๊ฐ์ ์ผ๊ฐํ์ ํฌ๊ธฐ๊ฐ ๋ฐ๋๋ค
- 4๊ฐ์ ์ผ๊ฐํ์ ๋ํด์ ๊ฐ๊ฐ ์ดํ ๋ณํ
# ํฌํ ์ต ๋ฆฌํดํ์ด ๋๊ตฌ
import cv2
import numpy as np
win_title = 'Liquify' # ์ฐฝ ์ด๋ฆ
half = 50 # ๊ด์ฌ ์์ญ ์ ๋ฐ ํฌ๊ธฐ
isDragging = False # ๋๋๊ทธ ์ฌ๋ถ ํ๋๊ทธ
# ๋ฆฌํดํ์ด ํจ์
def liquify(img, cx1,cy1, cx2,cy2) :
# ๋์ ์์ญ ์ขํ์ ํฌ๊ธฐ ์ค์
x, y, w, h = cx1-half, cy1-half, half*2, half*2
# ๊ด์ฌ ์์ญ ์ค์
roi = img[y:y+h, x:x+w].copy()
out = roi.copy()
# ๊ด์ฌ์์ญ ๊ธฐ์ค์ผ๋ก ์ขํ ์ฌ ์ค์
offset_cx1,offset_cy1 = cx1-x, cy1-y
offset_cx2,offset_cy2 = cx2-x, cy2-y
# ๋ณํ ์ด์ 4๊ฐ์ ์ผ๊ฐํ ์ขํ
tri1 = [[ (0,0), (w, 0), (offset_cx1, offset_cy1)], # ์,top
[ [0,0], [0, h], [offset_cx1, offset_cy1]], # ์ข,left
[ [w, 0], [offset_cx1, offset_cy1], [w, h]], # ์ฐ, right
[ [0, h], [offset_cx1, offset_cy1], [w, h]]] # ํ, bottom
# ๋ณํ ์ดํ 4๊ฐ์ ์ผ๊ฐํ ์ขํ
tri2 = [[ [0,0], [w,0], [offset_cx2, offset_cy2]], # ์, top
[ [0,0], [0, h], [offset_cx2, offset_cy2]], # ์ข, left
[ [w,0], [offset_cx2, offset_cy2], [w, h]], # ์ฐ, right
[ [0,h], [offset_cx2, offset_cy2], [w, h]]] # ํ, bottom
for i in range(4):
# ๊ฐ๊ฐ์ ์ผ๊ฐํ ์ขํ์ ๋ํด ์ดํ ๋ณํ ์ ์ฉ
matrix = cv2.getAffineTransform( np.float32(tri1[i]), \
np.float32(tri2[i]))
warped = cv2.warpAffine( roi.copy(), matrix, (w, h), \
None, flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_REFLECT_101)
# ์ผ๊ฐํ ๋ชจ์์ ๋ง์คํฌ ์์ฑ
mask = np.zeros((h, w), dtype = np.uint8)
cv2.fillConvexPoly(mask, np.int32(tri2[i]), (255,255,255))
# ๋ง์คํน ํ ํฉ์ฑ
warped = cv2.bitwise_and(warped, warped, mask=mask)
out = cv2.bitwise_and(out, out, mask=cv2.bitwise_not(mask))
out = out + warped
# ๊ด์ฌ ์์ญ์ ์๋ณธ ์์์ ํฉ์ฑ
img[y:y+h, x:x+w] = out
return img
# ๋ง์ฐ์ค ์ด๋ฒคํธ ํธ๋ค ํจ์
def onMouse(event,x,y,flags,param):
global cx1, cy1, isDragging, img # ์ ์ญ๋ณ์ ์ฐธ์กฐ
# ๋ง์ฐ์ค ์ค์ฌ ์ ์ ๊ธฐ์ค์ผ๋ก ๋์ ์์ญ ๋ฐ๋ผ๋ค๋๊ธฐ
if event == cv2.EVENT_MOUSEMOVE:
if not isDragging :
img_draw = img.copy()
# ๋๋๊ทธ ์์ญ ํ์
cv2.rectangle(img_draw, (x-half, y-half), \
(x+half, y+half), (0,255,0))
cv2.imshow(win_title, img_draw) # ์ฌ๊ฐํ ํ์๋ ๊ทธ๋ฆผ ํ๋ฉด ์ถ๋ ฅ
elif event == cv2.EVENT_LBUTTONDOWN :
isDragging = True # ๋๋๊ทธ ์์
cx1, cy1 = x, y # ๋๋๊ทธ ์์๋ ์๋์ ์์น ์ขํ ์ ์ฅ
elif event == cv2.EVENT_LBUTTONUP :
if isDragging:
isDragging = False # ๋๋๊ทธ ๋
# ๋๋๊ทธ ์์ ์ขํ์ ๋๋ ์ขํ๋ก ๋ฆฌํดํ์ด ์ ์ฉ ํจ์ ํธ์ถ
liquify(img, cx1, cy1, x, y)
cv2.imshow(win_title, img)
if __name__ == '__main__' :
img = cv2.imread("img/jam.jpeg")
h, w = img.shape[:2]
cv2.namedWindow(win_title)
cv2.setMouseCallback(win_title, onMouse)
cv2.imshow(win_title, img)
while True:
key = cv2.waitKey(1)
if key & 0xFF == 27:
break
cv2.destroyAllWindows()
3. ์ค์ต 3 : ์๊ณก ๊ฑฐ์ธ ์นด๋ฉ๋ผ
# ์๊ณก ๊ฑฐ์ธ ์นด๋ฉ๋ผ
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
WIDTH = 500
HEIGHT = 300
cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT)
rows, cols = HEIGHT, WIDTH
map_y, map_x = np.indices((rows, cols), dtype=np.float32)
# ๊ฑฐ์ธ ์๊ณก ํจ๊ณผ
map_mirrorh_x,map_mirrorh_y = map_x.copy(), map_y.copy()
map_mirrorv_x,map_mirrorv_y = map_x.copy(), map_y.copy()
## ์ข์ฐ ๋์นญ ๊ฑฐ์ธ ์ขํ ์ฐ์ฐ
map_mirrorh_x[: , cols//2:] = cols - map_mirrorh_x[:, cols//2:]-1
## ์ํ ๋์นญ ๊ฑฐ์ธ ์ขํ ์ฐ์ฐ
map_mirrorv_y[rows//2:, :] = rows - map_mirrorv_y[rows//2:, :]-1
# ๋ฌผ๊ฒฐ ํจ๊ณผ
map_wave_x, map_wave_y = map_x.copy(), map_y.copy()
map_wave_x = map_wave_x + 15*np.sin(map_y/20)
map_wave_y = map_wave_y + 15*np.sin(map_x/20)
# ๋ ์ฆ ํจ๊ณผ
## ๋ ์ฆ ํจ๊ณผ, ์ค์ฌ์ ์ด๋
map_lenz_x = 2*map_x/(cols-1)-1
map_lenz_y = 2*map_y/(rows-1)-1
## ๋ ์ฆ ํจ๊ณผ, ๊ทน์ขํ ๋ณํ
r, theta = cv2.cartToPolar(map_lenz_x, map_lenz_y)
r_convex = r.copy()
r_concave = r.copy()
## ๋ณผ๋ก ๋ ์ฆ ํจ๊ณผ ๋งคํ ์ขํ ์ฐ์ฐ
r_convex[r< 1] = r_convex[r<1] **2
print(r.shape, r_convex[r<1].shape)
## ์ค๋ชฉ ๋ ์ฆ ํจ๊ณผ ๋งคํ ์ขํ ์ฐ์ฐ
r_concave[r< 1] = r_concave[r<1] **0.5
## ๋ ์ฆ ํจ๊ณผ, ์ง๊ต ์ขํ ๋ณต์
map_convex_x, map_convex_y = cv2.polarToCart(r_convex, theta)
map_concave_x, map_concave_y = cv2.polarToCart(r_concave, theta)
## ๋ ์ฆ ํจ๊ณผ, ์ข์๋จ ์ขํ ๋ณต์
map_convex_x = ((map_convex_x + 1)*cols-1)/2
map_convex_y = ((map_convex_y + 1)*rows-1)/2
map_concave_x = ((map_concave_x + 1)*cols-1)/2
map_concave_y = ((map_concave_y + 1)*rows-1)/2
while True:
ret, frame = cap.read()
frame = frame[:HEIGHT, :WIDTH]
# ์ค๋นํ ๋งคํ ์ขํ๋ก ์์ ํจ๊ณผ ์ ์ฉ
mirrorh=cv2.remap(frame,map_mirrorh_x,map_mirrorh_y,cv2.INTER_LINEAR)
mirrorv=cv2.remap(frame,map_mirrorv_x,map_mirrorv_y,cv2.INTER_LINEAR)
wave = cv2.remap(frame,map_wave_x,map_wave_y,cv2.INTER_LINEAR, \
None, cv2.BORDER_REPLICATE)
convex = cv2.remap(frame,map_convex_x,map_convex_y,cv2.INTER_LINEAR)
concave = cv2.remap(frame,map_concave_x,map_concave_y,cv2.INTER_LINEAR)
# ์์ ํฉ์น๊ธฐ
r1 = np.hstack(( frame, mirrorh, mirrorv))
r2 = np.hstack(( wave, convex, concave))
merged = np.vstack((r1, r2))
cv2.imshow('distorted', merged)
if cv2.waitKey(1) & 0xFF== 27:
break
cap.release
cv2.destroyAllWindows()
์ฌ๋ฐ๋ใ
'๐ฉโ๐ป IoT (Embedded) > Image Processing' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[v0.20]์์์ฒ๋ฆฌ_๊ฒฝ๊ณ ๊ฒ์ถ (0) | 2022.01.11 |
---|---|
[v0.19]์์์ฒ๋ฆฌ_ ํํฐ์ ์ปจ๋ณผ๋ฃจ์ ์ฐ์ฐ, ๋ธ๋ฌ๋ง (0) | 2022.01.08 |
[v0.17]์์์ฒ๋ฆฌ_๋ ์ฆ ์๊ณกํ๊ธฐ (0) | 2022.01.08 |
[v0.16]์์์ฒ๋ฆฌ_์ด๋ฏธ์ง ๋คํ๊ธฐ (0) | 2022.01.07 |
[v0.15]์์์ฒ๋ฆฌ_์ด๋ฏธ์ง ์ด๋, ํ๋/์ถ์, ํ์ (0) | 2022.01.06 |