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

[v0.13]μ˜μƒμ²˜λ¦¬_2차원 νžˆμŠ€ν† κ·Έλž¨κ³Ό μ—­νˆ¬μ˜ λ³Έλ¬Έ

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

[v0.13]μ˜μƒμ²˜λ¦¬_2차원 νžˆμŠ€ν† κ·Έλž¨κ³Ό μ—­νˆ¬μ˜

μ§•μ§•μ•ŒνŒŒμΉ΄ 2022. 1. 5. 00:55
728x90
λ°˜μ‘ν˜•

220105 μž‘μ„±

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

https://bkshin.tistory.com/entry/OpenCV-11-2%EC%B0%A8%EC%9B%90-%ED%9E%88%EC%8A%A4%ED%86%A0%EA%B7%B8%EB%9E%A8%EA%B3%BC-%EC%97%AD%ED%88%AC%EC%98%81back-project?category=1148027 

 

OpenCV - 11. 2차원 νžˆμŠ€ν† κ·Έλž¨κ³Ό μ—­νˆ¬μ˜(back project)

이번 ν¬μŠ€νŒ…μ—μ„œλŠ” 2차원 νžˆμŠ€ν† κ·Έλž¨κ³Ό μ—­νˆ¬μ˜μ— λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€. 이번 ν¬μŠ€νŒ… μ—­μ‹œ '파이썬으둜 λ§Œλ“œλŠ” OpenCV ν”„λ‘œμ νŠΈ(μ΄μ„Έμš° μ €)'λ₯Ό μ •λ¦¬ν•œ κ²ƒμž„μ„ λ°νž™λ‹ˆλ‹€. μ½”λ“œ: github.com/BaekKyunShin/Op

bkshin.tistory.com

 

 

 

 

 

1. 2차원 νžˆμŠ€ν† κ·Έλž¨ (2D Histogram)

: 1차원 νžˆμŠ€ν† κ·Έλž¨μ€ 이미지 μ•ˆμ— 픽셀이 각각 λͺ‡ κ°œμΈμ§€λ₯Ό ν‘œν˜„

: 2차원 νžˆμŠ€ν† κ·Έλž¨μ€ 좕이 2개이고, 각 좕이 λ§Œλ‚˜λŠ” μ§€μ μ˜ 개수λ₯Ό ν‘œν˜„

# 2D νžˆμŠ€ν† κ·Έλž¨
import cv2
import matplotlib.pylab as plt

plt.style.use('classic')            # --β‘ μ»¬λŸ¬ μŠ€νƒ€μΌμ„ 1.x μŠ€νƒ€μΌλ‘œ μ‚¬μš©
img = cv2.imread('img/sunflower.jpg')

plt.subplot(131)
hist = cv2.calcHist([img], [0,1], None, [32,32], [0,256,0,256]) #--β‘‘
p = plt.imshow(hist)                                            #--β‘’
plt.title('Blue and Green')                                     #--β‘£
plt.colorbar(p)                                                 #--β‘€


plt.subplot(132)
hist = cv2.calcHist([img], [1,2], None, [32,32], [0,256,0,256]) #--β‘₯
p = plt.imshow(hist)
plt.title('Green and Red')
plt.colorbar(p)

plt.subplot(133)
hist = cv2.calcHist([img], [0,2], None, [32,32], [0,256,0,256]) #--⑦
p = plt.imshow(hist)
plt.title('Blue and Red')
plt.colorbar(p)

plt.show()

RGBλ₯Ό 3쌍으둜 λΆ„λ₯˜ν•΄μ„œ 2차원 νžˆμŠ€ν† κ·Έλž¨

 

 

 

 

2. μ—­νˆ¬μ˜ (Back Projection)

: 관심 μ˜μ—­μ˜ νžˆμŠ€ν† κ·Έλž¨κ³Ό μœ μ‚¬ν•œ νžˆμŠ€ν† κ·Έλž¨μ„ κ°–λŠ” μ˜μ—­μ„ μ°Ύμ•„λ‚΄λŠ” 기법

: μ—­νˆ¬μ˜μ„ ν™œμš©ν•˜λ©΄ 이미지 λ‚΄μ—μ„œ νŠΉμ • λ¬Όμ²΄λ‚˜ 배경을 뢄리

: λΆ„λ¦¬ν•˜κ³  싢은 관심 μ˜μ—­(ROI, region of interest)을 μ§€μ •ν•˜κ³  μ—­νˆ¬μ˜μ„ 적용

: 관심 μ˜μ—­μ€ ν°μƒ‰μœΌλ‘œ, μ•„λ‹Œ 뢀뢄은 κ²€μ€μƒ‰μœΌλ‘œ μ„œλ‘œ 뢄리

 

cv2.calcBackProject(img, channel, hist, ranges, scale)
- img : μž…λ ₯ 이미지, [img]처럼 리슀트둜 κ°μ‹Έμ„œ μ‚¬μš©
- channel : μ²˜λ¦¬ν•  채널, 리슀트둜 κ°μ‹Έμ„œ μ‚¬μš©
- hist : μ—­νˆ¬μ˜μ— μ‚¬μš©ν•  νžˆμŠ€ν† κ·Έλž¨
- ranges : 각 픽셀이 κ°€μ§ˆ 수 μžˆλŠ” κ°’μ˜ λ²”μœ„
- scale : 결과에 μ μš©ν•  배율 κ³„μˆ˜

 

masking() ν•¨μˆ˜

: μŠ€λ ˆμ‹œν™€λ”©κ³Ό λ§ˆμŠ€ν‚Ήμ„ ν™œμš©ν•˜μ—¬ κ²°κ³Όλ₯Ό 좜λ ₯

: cv2.getStructuringElement()와 cv2.filter2D()λŠ” 마슀크의 ν‘œλ©΄μ„ λΆ€λ“œλŸ½κ²Œ ν•΄μ£ΌλŠ” μ—­ν• 

# 마우슀둜 μ„ νƒν•œ μ˜μ—­μ˜ 물체 λΆ„λ¦¬ν•˜κΈ°
import cv2
import numpy as np
import matplotlib.pyplot as plt

win_name = 'back_projection'
img = cv2.imread('img/alpaca1.jpeg')
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
draw = img.copy()

#--β‘€ μ—­νˆ¬μ˜λœ κ²°κ³Όλ₯Ό λ§ˆμŠ€ν‚Ήν•΄μ„œ κ²°κ³Όλ₯Ό 좜λ ₯ν•˜λŠ” κ³΅ν†΅ν•¨μˆ˜
def masking(bp, win_name):
    disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
    cv2.filter2D(bp,-1,disc,bp)
    _, mask = cv2.threshold(bp, 1, 255, cv2.THRESH_BINARY)
    result = cv2.bitwise_and(img, img, mask=mask)
    cv2.imshow(win_name, result)

#--β‘₯ 직접 κ΅¬ν˜„ν•œ μ—­νˆ¬μ˜ ν•¨μˆ˜
def backProject_manual(hist_roi):
    #--⑦ 전체 μ˜μƒμ— λŒ€ν•œ H,S νžˆμŠ€ν† κ·Έλž¨ 계산
    hist_img = cv2.calcHist([hsv_img], [0,1], None,[180,256], [0,180,0,256])
    #--⑧ μ„ νƒμ˜μ—­κ³Ό 전체 μ˜μƒμ— λŒ€ν•œ νžˆμŠ€ν† κ·Έλž¨ 그램 λΉ„μœ¨κ³„μ‚°
    hist_rate = hist_roi/ (hist_img + 1)
    #--⑨ λΉ„μœ¨μ— λ§žλŠ” ν”½μ…€ κ°’ 맀핑
    h,s,v = cv2.split(hsv_img)
    bp = hist_rate[h.ravel(), s.ravel()]
    # λΉ„μœ¨μ€ 1을 λ„˜μ–΄μ„œλŠ” μ•ˆλ˜κΈ° λ•Œλ¬Έμ— 1을 λ„˜λŠ” μˆ˜λŠ” 1을 κ°–κ²Œ 함
    bp = np.minimum(bp, 1)
    # 1차원 배열을 μ›λž˜μ˜ shape둜 λ³€ν™˜
    bp = bp.reshape(hsv_img.shape[:2])
    cv2.normalize(bp,bp, 0, 255, cv2.NORM_MINMAX)
    bp = bp.astype(np.uint8)
    #--β‘© μ—­ 투영 결과둜 λ§ˆμŠ€ν‚Ήν•΄μ„œ κ²°κ³Ό 좜λ ₯
    masking(bp,'result_manual')
 
# OpenCV API둜 κ΅¬ν˜„ν•œ ν•¨μˆ˜ ---β‘ͺ 
def backProject_cv(hist_roi):
    # μ—­νˆ¬μ˜ ν•¨μˆ˜ 호좜 ---β‘«
    bp = cv2.calcBackProject([hsv_img], [0, 1], hist_roi,  [0, 180, 0, 256], 1)
    # μ—­ 투영 결과둜 λ§ˆμŠ€ν‚Ήν•΄μ„œ κ²°κ³Ό 좜λ ₯ ---⑬ 
    masking(bp,'result_cv')

# ROI 선택 ---β‘ 
(x,y,w,h) = cv2.selectROI(win_name, img, False)
if w > 0 and h > 0:
    roi = draw[y:y+h, x:x+w]
    # λΉ¨κ°„ μ‚¬κ°ν˜•μœΌλ‘œ ROI μ˜μ—­ ν‘œμ‹œ
    cv2.rectangle(draw, (x, y), (x+w, y+h), (0,0,255), 2)
    #--β‘‘ μ„ νƒν•œ ROIλ₯Ό HSV 컬러 슀페이슀둜 λ³€κ²½
    hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
    #--β‘’ H,S 채널에 λŒ€ν•œ νžˆμŠ€ν† κ·Έλž¨ 계산
    hist_roi = cv2.calcHist([hsv_roi],[0, 1], None, [180, 256], [0, 180, 0, 256] )
    #--β‘£ ROI의 νžˆμŠ€ν† κ·Έλž¨μ„ 맀뉴얼 κ΅¬ν˜„ν•¨μˆ˜μ™€ OpenCV μ΄μš©ν•˜λŠ” ν•¨μˆ˜μ— 각각 전달
    backProject_manual(hist_roi)
    backProject_cv(hist_roi)
cv2.imshow(win_name, draw)
cv2.waitKey()
cv2.destroyAllWindows()

μ—­νˆ¬μ˜μœΌλ‘œ μ•ŒνŒŒμΉ΄ μΆ”μΆœν•˜κΈ°

- 마우슀둜 κ΄€μ‹¬μ˜μ—­μ„ μ„ νƒν•œ λ’€ μ—”ν„°λ₯Ό λˆ„λ₯΄λ©΄ 관심 μ˜μ—­μ— ν•΄λ‹Ήν•˜λŠ” 물체만 μΆ”μΆœ

- 관심 μ˜μ—­μ„ HSV ν˜•μ‹μœΌλ‘œ λ³€κ²½

- 전체 μ΄λ―Έμ§€μ˜ νžˆμŠ€ν† κ·Έλž¨μœΌλ‘œ λ‚˜λˆ„μ–΄ λΉ„μœ¨ κ΅¬ν•˜κΈ°

( λΉ„μœ¨ κ΅¬ν•˜κΈ° = 관심 μ˜μ—­κ³Ό λΉ„μŠ·ν•œ 색상 뢄포λ₯Ό κ°–λŠ” νžˆμŠ€ν† κ·Έλž¨μ€ 1에 κ°€κΉκ²Œ, μ•„λ‹ˆλ©΄ 0에 κ°€κΉκ²Œ )

 

- H, S 채널에 λŒ€ν•œ 2차원 νžˆμŠ€ν† κ·Έλž¨ λ§Œλ“€κΈ°

( hist_rateλŠ” νžˆμŠ€ν† κ·Έλž¨ λΉ„μœ¨μ„ κ°’μœΌλ‘œ 가짐 )

( h와 sλŠ” μ‹€μ œ μ΄λ―Έμ§€μ˜ 각 ν”½μ…€ )

( h와 sκ°€ κ΅μ°¨λ˜λŠ” μ§€μ μ˜ λΉ„μœ¨μ„ κ·Έ ν”½μ…€ κ°’μœΌλ‘œ ν•˜λŠ” 1차원 λ°°μ—΄ )

 

- νžˆμŠ€ν† κ·Έλž¨μ„ 직접 κ΅¬ν˜„ν•œ ν•¨μˆ˜μ™€ OpenCV ν•¨μˆ˜μ˜ νŒŒλΌλ―Έν„°λ‘œ 전달

- 사물을 뢄리할 수 μžˆλ‹€!

- 관심 μ˜μ—­μ˜ 색상과 λΉ„μŠ·ν•œ 물체 μΆ”μΆœ

- 관심 μ˜μ—­ μ™Έ λΆ€λΆ„μ˜ 색상이 λΉ„μŠ·ν•  경우 효과 떨어짐

 

 

 

 

 

 

 

 

 

μ™• μ‹ κΈ°ν•˜λ‹Ή

μ›ν•˜λŠ” μ˜μ—­ μΆ”μΆœ ν•˜κΈ° ><

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