6. 마스크 연산 (누끼따기)
- 마스크 연산을 지원하는 픽셀 값 복사 함수
- cv2.copyTo(img, mask)img와 mask를 넣어서 객체를 만들어줍니다.
위 이미지들을 활용하여 배경에 비행기가 copy되는 마스크연산을 해보려고 합니다.
mask는 **0인 부분은 "무시"**되고, **0이 아닌 부분은 "복사"**되는 거예요.
그림으로 비유:
마스크를 투명 종이라고 생각할 수 있어요. 종이에서 투명한 부분(=마스크가 0인 부분)은 복사되지 않고, 불투명한 부분(=마스크가 0이 아닌 부분)은 복사됩니다.
위의 마스크 사진에서는
- 검은색 부분이 0인 부분입니다.
- 즉, 이 부분은 마스크에서 복사되지 않는 영역을 나타냅니다.
- 흰색 부분이 0이 아닌 부분입니다.
- 마스크에서 복사되는 영역을 나타냅니다.
- 검은색(배경) 부분: 원본 이미지에서 이 영역은 무시되고, 복사되지 않음.
- 흰색(비행기 모양) 부분: 이 부분은 원본 이미지에서 복사되어 새로운 이미지에 복사됩니다.
따라서, 이 마스크를 사용하면 비행기 모양의 흰색 영역만 복사되고, 검은색 배경 부분은 복사되지 않게 됩니다.
import cv2
img=cv2.imread('./airplane.bmp')
mask = cv2.imread('./mask_plane.bmp')
dst = cv2.imread('./field.bmp')
temp = cv2.copyTo(img, mask)
# cv2.imshow('img', img)
# cv2.imshow('mask', mask)
cv2.imshow('temp',temp)
cv2.waitKey()
작업 과정
- 마스크 이미지에서 흰색 부분(255)**은 img에서 그 부분을 복사해서 temp에 넣습니다.
이렇게 이미지를 딸 수 있습니다.
그리고 field이미지에 비행기까지 같이넣으려면
import cv2
img=cv2.imread('./airplane.bmp')
mask = cv2.imread('./mask_plane.bmp')
dst = cv2.imread('./field.bmp')
temp = cv2.copyTo(img, mask)
cv2.copyTo(img, mask, dst)
# cv2.imshow('img', img)
# cv2.imshow('mask', mask)
cv2.imshow('temp',temp)
cv2.imshow('dst',dst)
cv2.waitKey()
cv2.copyTo(img, mask, dst) 로 한 줄 더 추가하고
여기서 dst 즉 3번째 파라미터의 기능이 연산하고 덮는 역할을 합니다.
만약 따로 마지막 연산을 하지않으려면 윗줄처럼 img, mask두개로 쓰고 변수를 하나 만들어주면 됩니다.
mask를 만들려면 같은 사진으로 ROI를 이용한거 (남이 만든거쓴다던지(?))를 이용할 수 있습니다.
응용 파이널 ... 버전
여기 영상에 뒤에있는 초록색을 따서 픽사베이에서 원하는 영상을 받아서 뒷 배경으로 인서트 하는 작업을
만들어보려고 합니다.
목표
간단하게 이 이미지를 가져왔고 백그라운드에 copyTo()를 하려고 합니다.
import cv2
#비디오 파일 열기
cap1 = cv2.VideoCapture('./woman.mp4')
cap2 = cv2.VideoCapture('./background.mp4')
#비디오 너비,높이, fps가져오기
w = round(cap1.get(cv2.CAP_PROP_FRAME_WIDTH))
h = round(cap1.get(cv2.CAP_PROP_FRAME_HEIGHT))
frame_cnt1 = round(cap1.get(cv2.CAP_PROP_FRAME_COUNT))
frame_cnt2 = round(cap2.get(cv2.CAP_PROP_FRAME_COUNT))
fps = round(cap1.get(cv2.CAP_PROP_FPS))
print(w) #1280
print(h) #720
print(frame_cnt1) #409
print(frame_cnt2) #906
print(fps) #24
#(반복문) 첫번째 영상에서 frame읽기
while True:
ret1, frame1 = cap1.read()
if not ret1:
break
ret2, frame2 = cap2.read()
if not ret2:
break
hsv = cv2.cvtColor(frame1, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, (50,150,0), (70,255,255))
#초록색배경부분을 축구장에서 따서 여성이 있는 부분에 갖다 붙이기
#여성은 그대로있고 배경만 따져옴
cv2.copyTo(frame2, mask, frame1)
cv2.imshow('frame1', frame1)
key = cv2.waitKey(10)
if key == ord(' '):
cv2.waitKey()
elif key == 27:
break
cap1.release()
cap2.release()
이렇게 합성이 되어서 깔끔하진 않지만 잘 보여지는걸 확인할 수 있습니다.
여기서 공부하고 정리한것.
1. while문이 오랜만에 나와서 개념정리
2. cv2.inRange()에서 여성의 뒷 배경인 초록색을 따려고 하는데
전 예제에서는
HSV에서의 녹색계열
#색상
50 <= H <= 80
#채도
150 <= S <= 255
#명도(밝기정보)
0 <= V <= 255
'''
dst = cv2.inRange(hsv,(50, 150, 0), (80, 255,255))
이 녹색이라고 했는데 지금 동영상의 합성한 경우는
mask = cv2.inRange(hsv, (50,150,0), (70,255,255))
이라서 왜 그런지 궁금했습니다.
이유는 아래와 같습니다.
색상 범위를 어떻게 설정할 것인지 결정하게 되는거더라구요.
mask에서 작성된 코드는 hue값이 50에서 70으로 더좁게 설정되어있어서 특정녹색계열에 초점을 맞추는것이였습니다.
지금같은경우는 강사님이 다 값을 지정해준거지만
내가 다른 영상을 합성할때에는 HSV값을 내가 알아야할것같습니다.
3.release()
영상을 사용하고 꺼주는 역할을 합니다. 물론 위에서 waitKey로 작성했잖아? 라고
생각할 수 있지만 waitKey는 키 입력할때까지 사용자가 누를때까지 대기하는역할만 한다고 생각하며 되고
release는 '파일'을 닫는 작업을 하는 함수입니다.
- **waitKey()**는: "비디오를 재생하는 동안 잠깐 멈추고 키 입력을 기다려라"라는 명령입니다.
- **release()**는: "비디오 재생이 끝났으니 이 비디오 파일과의 연결을 끊어라"라는 명령입니다.
'AI 컴퓨터 비전프로젝트' 카테고리의 다른 글
[DL] 오츠의 이진화(스레숄드값을 자동으로 잡아주기) (0) | 2024.10.03 |
---|---|
[DL]영상의 이진화(Binarization) (0) | 2024.10.02 |
[DL] cv2.inRange_hsv 색상추출 (0) | 2024.09.30 |
[DL] 정규화 (0) | 2024.09.29 |
[DL] 균등화, 평탄화단점보완 CLAHE(이미지, 영상 품질관련)(3) (0) | 2024.09.28 |