😎 κ³΅λΆ€ν•˜λŠ” μ§•μ§•μ•ŒνŒŒμΉ΄λŠ” μ²˜μŒμ΄μ§€?

[v0.15]μ˜μƒμ²˜λ¦¬_이미지 이동, ν™•λŒ€/μΆ•μ†Œ, νšŒμ „ λ³Έλ¬Έ

πŸ‘©‍πŸ’» IoT (Embedded)/Image Processing

[v0.15]μ˜μƒμ²˜λ¦¬_이미지 이동, ν™•λŒ€/μΆ•μ†Œ, νšŒμ „

μ§•μ§•μ•ŒνŒŒμΉ΄ 2022. 1. 6. 01:54
728x90
λ°˜μ‘ν˜•

220106 μž‘μ„±

<λ³Έ λΈ”λ‘œκ·ΈλŠ” 귀퉁이 μ„œμž¬λ‹˜μ˜ λΈ”λ‘œκ·Έλ₯Ό μ°Έκ³ ν•΄μ„œ κ³΅λΆ€ν•˜λ©° μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€>

https://bkshin.tistory.com/entry/OpenCV-13-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%9D%B4%EB%8F%99Translation-%ED%99%95%EB%8C%80%EC%B6%95%EC%86%8CScaling-%ED%9A%8C%EC%A0%84Rotation?category=1148027 

 

OpenCV - 13. 이미지 이동(Translation), ν™•λŒ€/μΆ•μ†Œ(Scaling), νšŒμ „(Rotation)

이번 ν¬μŠ€νŒ…μ—μ„œλŠ” 이미지λ₯Ό 이동, ν™•λŒ€, μΆ•μ†Œ, νšŒμ „ν•˜λŠ” 방법에 λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€. 이번 ν¬μŠ€νŒ… μ—­μ‹œ '파이썬으둜 λ§Œλ“œλŠ” OpenCV ν”„λ‘œμ νŠΈ(μ΄μ„Έμš° μ €)'λ₯Ό μ •λ¦¬ν•œ κ²ƒμž„μ„ λ°νž™λ‹ˆλ‹€. μ½”λ“œ: github.

bkshin.tistory.com

 

 

 

 

1. 이미지 이동

: μ›λž˜ 있던 μ’Œν‘œμ— μ΄λ™μ‹œν‚€λ €λŠ” 거리만큼 λ”ν•˜κΈ°

x_new = x_old + d₁

y_new = y_old + dβ‚‚

ν–‰λ ¬μ‹μœΌλ‘œ ν‘œν˜„

x_new = 1 * x_old + 0 * y_old + d₁
y_new = 0 * x_old + 1 * y_old + dβ‚‚

 

 

λ³€ν™˜ ν–‰λ ¬

: μ΄λ―Έμ§€μ˜ μ–΄λ–€ μ’Œν‘œλ₯Ό λ‹€λ₯Έ μ’Œν‘œλ‘œ μ΄λ™μ‹œμΌœμ£ΌλŠ” ν–‰λ ¬

: μ–΄λ–€ μ’Œν‘œλ₯Ό μ„ ν˜• λ³€ν™˜(linear tranformations) ν•΄μ£ΌλŠ” ν–‰λ ¬

: μ–΄λ–€ μ’Œν‘œμ— λ³€ν™˜ 행렬을 κ³±ν•΄μ£Όλ©΄ λ‹€λ₯Έ μ’Œν‘œκ°€ κ΅¬ν•΄μ§€λŠ” ν–‰λ ¬

이미지 이동에 λŒ€ν•œ λ³€ν™˜ν–‰λ ¬

dst = cv2.warpAffine(src, matrix, dsize, dst, flags, borderMode, borderValue)
- src : 원본 이미지, numpy λ°°μ—΄
- matrix : 2 x 3 λ³€ν™˜ν–‰λ ¬, dtype=float32
- dsize : κ²°κ³Ό μ΄λ―Έμ§€μ˜ 크기, (width, height)
- flags(optional) : 보간법 μ•Œκ³ λ¦¬μ¦˜ ν”Œλž˜κ·Έ

  • cv2.INTER_LINEAR : default κ°’, μΈμ ‘ν•œ 4개 ν”½μ…€ 값에 거리 κ°€μ€‘μΉ˜ μ‚¬μš©    => 주둜 ν™•λŒ€
  • cv2.INTER_NEAREST : κ°€μž₯ κ°€κΉŒμš΄ ν”½μ…€ κ°’ μ‚¬μš©
  • cv2.INTER_AREA : ν”½μ…€ μ˜μ—­ 관계λ₯Ό μ΄μš©ν•œ μž¬μƒ˜ν”Œλ§                  => 주둜 μΆ•μ†Œ
  • cv2.INTER_CUBIC : 인정합 16개 ν”½μ…€ 값에 거리 κ°€μ€‘μΉ˜ μ‚¬μš©         => 주둜 ν™•λŒ€

- borderMode(optional) : μ™Έκ³½ μ˜μ—­ 보정 ν”Œλž˜κ·Έ

  • cv2.BORDER_CONSTANT : κ³ μ • 색상 κ°’
  • cv2.BORDER_REPLICATE : κ°€μž₯자리 볡제
  • cv2.BORDER_WRAP : 반볡
  • cv2.BORDER_REFLECT : λ°˜μ‚¬

- borderValue(optional) : cv2.BORDER_CONSTANT μ™Έκ³½ μ˜μ—­ 보정 ν”Œλž˜κ·ΈμΌ 경우 μ‚¬μš©ν•  색상 κ°’ (default=0)
- dst : κ²°κ³Ό 이미지

# 평행 이동
import cv2
import numpy as np

img = cv2.imread('img/whiteman.png')
rows,cols = img.shape[0:2]  # μ˜μƒμ˜ 크기

dx, dy = 100, 50            # 이동할 ν”½μ…€ 거리

# ---β‘  λ³€ν™˜ ν–‰λ ¬ 생성 
mtrx = np.float32([[1, 0, dx],
                   [0, 1, dy]])  
# ---β‘‘ λ‹¨μˆœ 이동
dst = cv2.warpAffine(img, mtrx, (cols+dx, rows+dy))   

# ---β‘’ νƒˆλ½λœ μ™Έκ³½ 픽셀을 νŒŒλž‘μƒ‰μœΌλ‘œ 보정
dst2 = cv2.warpAffine(img, mtrx, (cols+dx, rows+dy), None, \
                        cv2.INTER_LINEAR, cv2.BORDER_CONSTANT, (255,0,0) )

# ---β‘£ νƒˆλ½λœ μ™Έκ³½ 픽셀을 원본을 λ°˜μ‚¬ μ‹œμΌœμ„œ 보정
dst3 = cv2.warpAffine(img, mtrx, (cols+dx, rows+dy), None, \
                                cv2.INTER_LINEAR, cv2.BORDER_REFLECT)

cv2.imshow('original', img)
cv2.imshow('trans',dst)
cv2.imshow('BORDER_CONSTATNT', dst2)
cv2.imshow('BORDER_FEFLECT', dst3)
cv2.waitKey(0)
cv2.destroyAllWindows()

원본&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;이동&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;μ™Έκ³½ 픽셀을 νŒŒλž€μƒ‰μœΌλ‘œ&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;μ™Έκ³½ 픽셀을 λ°˜μ‚¬μ‹œμΌœμ„œ

 

 

 

 

+) μ™Έκ³½ μ˜μ—­ 보정을 보간법 νŒŒλΌλ―Έν„° λ³„λ‘œ

κ³ μ • 색상값&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;κ°€μž₯ 자리 볡제&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 반볡&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;볡제

 

 

+ λ³΄μ •λ²•μ΄λž€

Interpolation(μΈν„°ν΄λ ˆμ΄μ…˜, 보간)

: μ•Œλ €μ§„ μ§€μ μ˜ κ°’ 사이(쀑간)에 μœ„μΉ˜ν•œ 값을 μ•Œλ €μ§„ κ°’μœΌλ‘œλΆ€ν„° μΆ”μ •

: κΈ°ν•˜ν•™μ  λ³€ν™˜ ( ν™•λŒ€, νšŒμ „ λ“± )ν•  λ•Œ, μ˜μƒμ˜ μ•„λ¬΄λŸ° 정보λ₯Ό 받지 λͺ»ν•˜λŠ” pixel 생김

-> μ£Όλ³€μ˜ μ•Œκ³  μžˆλŠ” 값듀을 μ΄μš©ν•˜μ—¬ pixel 의 값을 μœ λ„ν•˜λŠ” κ³Όμ •

 

 

 

 

2. 이미지 ν™•λŒ€ 및 μΆ•μ†Œ

: 기쑴의 μ’Œν‘œμ— νŠΉμ •ν•œ 값을 κ³±ν•˜κΈ°

x_new = a₁ * x_old
y_new = aβ‚‚ * y_old

λ³€ν™˜ ν–‰λ ¬

x_new = a₁ * x_old + 0 * y_old + 0 * 1
y_new = 0 * x_old + aβ‚‚ * y_old + 0 * 1

 

cv2.warpAffine() ν•¨μˆ˜λŠ” λ³€ν™˜ 행렬이 2 x 3 행렬이 μ•„λ‹ˆλ©΄ 였λ₯˜λ₯Ό λ‚Έλ‹€

=> 2 x 3 ν–‰λ ¬λ‘œ ν‘œν˜„ν•˜κΈ° !

# 행렬을 μ΄μš©ν•œ 이미지 ν™•λŒ€ 및 μΆ•μ†Œ
import cv2
import numpy as np

img = cv2.imread('img/jam.jpeg')
height, width = img.shape[:2]

# --β‘  0.5λ°° μΆ•μ†Œ λ³€ν™˜ ν–‰λ ¬
m_small = np.float32([[0.5, 0, 0],
                       [0, 0.5,0]])  
# --β‘‘ 2λ°° ν™•λŒ€ λ³€ν™˜ ν–‰λ ¬
m_big = np.float32([[2, 0, 0],
                     [0, 2, 0]])  

# --β‘’ 보간법 적용 없이 ν™•λŒ€ μΆ•μ†Œ
dst1 = cv2.warpAffine(img, m_small, (int(height*0.5), int(width*0.5)))
dst2 = cv2.warpAffine(img, m_big, (int(height*2), int(width*2)))

# --β‘£ 보간법 μ μš©ν•œ ν™•λŒ€ μΆ•μ†Œ
dst3 = cv2.warpAffine(img, m_small, (int(height*0.5), int(width*0.5)), \
                        None, cv2.INTER_AREA)
dst4 = cv2.warpAffine(img, m_big, (int(height*2), int(width*2)), \
                        None, cv2.INTER_CUBIC)

# κ²°κ³Ό 좜λ ₯
cv2.imshow("original", img)
cv2.imshow("small", dst1)
cv2.imshow("big", dst2)
cv2.imshow("small INTER_AREA", dst3)
cv2.imshow("big INTER_CUBIC", dst4)
cv2.waitKey(0)
cv2.destroyAllWindows()

μΆ•μ†Œ ( 보간법 X, 보간법 O )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ν™•λŒ€ ( 보간법 X, 보간법 O )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;

- 보간법 유무의 차이가... 눈으둜 봀을 λ•Œ λ”±νžˆ 차이점이 μ•ˆλŠκ»΄μ§„λ‹€!

 

 

 

 

+) cv2.resize() 둜 ν™•λŒ€ 및 μΆ•μ†Œ

cv2.resize(src, dsize, dst, fx, fy, interpolation)
- src : μž…λ ₯ 원본 이미지
-  dsize : 좜λ ₯ μ˜μƒ 크기 (ν™•λŒ€/μΆ•μ†Œ λͺ©ν‘œ 크기, (width, height)ν˜•μ‹), μƒλž΅ν•˜λ©΄ fx, fy λ°°μœ¨μ„ 적용
-  fx, fy : λ³€κ²½ν•  크기 배율, dsizeκ°€ 주어지면 dsizeλ₯Ό μ μš©ν•¨
-  interpolation : 보간법 μ•Œκ³ λ¦¬μ¦˜ 선택 ν”Œλž˜κ·Έ (cv2.warpAffine()κ³Ό 동일)
-  dst : κ²°κ³Ό 이미지

# cv2.reize()둜 이미지 ν™•λŒ€ 및 μΆ•μ†Œ
import cv2
import numpy as np

img = cv2.imread('img/hobbang.jpeg')
height, width = img.shape[:2]

#--β‘  크기 μ§€μ •μœΌλ‘œ μΆ•μ†Œ
dst1 = cv2.resize(img, (int(width*0.5), int(height*0.5)), \
                         interpolation=cv2.INTER_AREA)

#--β‘‘ 배율 μ§€μ •μœΌλ‘œ ν™•λŒ€
dst2 = cv2.resize(img, None,  None, 2, 2, cv2.INTER_CUBIC)
#--β‘’ κ²°κ³Ό 좜λ ₯
cv2.imshow("original", img)
cv2.imshow("small", dst1)
cv2.imshow("big", dst2)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.resize μ‚¬μš©ν•΄μ„œ ν™•λŒ€ 및 μΆ•μ†Œ

- small 은 μ›ν•˜λŠ” 결과의 크기λ₯Ό ν”½μ…€ κ°’μœΌλ‘œ 직접 지정

- big 은 μ›ν•˜λŠ” λ°°μœ¨μ„ μ§€μ •ν•΄μ„œ 이미지 μŠ€μΌ€μΌλ§

 

 

 

 

 

 

3. 이미지 νšŒμ „

이미지 νšŒμ „μ˜ λ³€ν™˜ ν–‰λ ¬ &lt;좜처: https://slidesplayer.org/slide/14096571/&gt;

# λ³€ν™˜ν–‰λ ¬μ„ μ΄μš©ν•œ 이미지 νšŒμ „
import cv2
import numpy as np

img = cv2.imread('img/hobbang.jpeg')
rows,cols = img.shape[0:2]

# ---β‘  λΌλ””μ•ˆ 각도 계산(60진법을 ν˜Έλ„λ²•μœΌλ‘œ λ³€κ²½)
d45 = 45.0 * np.pi / 180    # 45도
d90 = 90.0 * np.pi / 180    # 90도

# ---β‘‘ νšŒμ „μ„ μœ„ν•œ λ³€ν™˜ ν–‰λ ¬ 생성
m45 = np.float32( [[ np.cos(d45), -1* np.sin(d45), rows//2],
                    [np.sin(d45), np.cos(d45), -1*cols//4]])
m90 = np.float32( [[ np.cos(d90), -1* np.sin(d90), rows],
                    [np.sin(d90), np.cos(d90), 0]])

# ---β‘’ νšŒμ „ λ³€ν™˜ ν–‰λ ¬ 적용
r45 = cv2.warpAffine(img,m45,(cols,rows))
r90 = cv2.warpAffine(img,m90,(rows,cols))

# ---β‘£ κ²°κ³Ό 좜λ ₯
cv2.imshow("origin", img)
cv2.imshow("45", r45)
cv2.imshow("90", r90)
cv2.waitKey(0)
cv2.destroyAllWindows()

원본&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ν˜Έλ„λ²•μœΌλ‘œ 45도&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; λ³€ν™˜ν–‰λ ¬λ‘œ 90도

- 1 λΌλ””μ•ˆ(radian) = (180/π)도

- 1도 = (π/180) λΌλ””μ•ˆ

- λ³€ν™˜ν–‰λ ¬λ‘œ 직접 κ΅¬ν˜„ν•˜λŠ” 건 볡작 -> μ΄λ™μ‹œν‚¬ μ’Œν‘œμ˜ ν¬κΈ°κΉŒμ§€ 고렀해야됨

 

 

 

 

+) cv2.getRotationMatrix2D

: κ°„λ‹¨ν•˜κ²Œ λ³€ν™˜ν–‰λ ¬ γ„±

mtrx = cv2.getRotationMatrix2D(center, angle, scale)

- center: νšŒμ „μΆ• 쀑심 μ’Œν‘œ

- (x, y)angle : νšŒμ „ν•  각도, 60진법

- scale : ν™•λŒ€ 및 μΆ•μ†Œ λΉ„μœ¨

# OpenCv둜 νšŒμ „ λ³€ν™˜ν–‰λ ¬ κ΅¬ν•˜κΈ°
import cv2

img = cv2.imread('img/hobbang.jpeg')
rows,cols = img.shape[0:2]

#---β‘  νšŒμ „μ„ μœ„ν•œ λ³€ν™˜ ν–‰λ ¬ κ΅¬ν•˜κΈ°
# νšŒμ „μΆ•:쀑앙, 각도:45, 배율:0.5
m45 = cv2.getRotationMatrix2D((cols/2,rows/2),45,0.5) 
# νšŒμ „μΆ•:쀑앙, 각도:90, 배율:1.5
m90 = cv2.getRotationMatrix2D((cols/2,rows/2),90,1.5) 

#---β‘‘ λ³€ν™˜ ν–‰λ ¬ 적용
img45 = cv2.warpAffine(img, m45,(cols, rows))
img90 = cv2.warpAffine(img, m90,(cols, rows))

#---β‘’ κ²°κ³Ό 좜λ ₯
cv2.imshow('origin',img)
cv2.imshow("45", img45)
cv2.imshow("90", img90)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.getRotationMatrix2D μ‚¬μš©&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; μΆ•μ†Œ 45도&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ν™•λŒ€ 90도&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;

- cv2.getRotationMatrix2D μ‚¬μš©ν•˜λ‹ˆκΉŒ κ°„νŽΈν•˜κ²Œ μΆ•μ†Œλ‚˜, ν™•λŒ€ + νšŒμ „μ΄ κ°€λŠ₯ν•˜λ‹€!

 

 

 

 

 

 

 

μˆ˜μ—…μ‹œκ°„μ— 배운 것듀이닀..

ν›„ λ³΅μŠ΅ν•˜κ³ 

μ œλŒ€λ‘œ μˆ™μ§€ν•˜κ²Œλ˜λŠ” λŠλ‚Œ..

이제 μ•Œλ©΄ μ–΄λ–‘ν•΄ !!! γ…œγ…œ

728x90
λ°˜μ‘ν˜•
Comments