본문 바로가기
1. Front-end/>> FFmpeg

[파이썬] 챕터6.가상 광고판 | 파이썬 추월코스, 최신 파이썬, 코딩, 기초 프로그래밍 강의

by 블록메타 2023. 1. 19.
홍정모

가상 광고판 만들기를 해 보겠습니다. 

 

재미 요소를 위해서 본인의 영상으로 따라 해보시면 좋을것 같습니다. 

 

축구 경기를 보는 영상에 합성을 하는 겁니다.  OpenCV를 이용해서 효과를 만들어 보도록 하겠습니다. 

참고로 AR에도 비슷한 원리가 적용됩니다. 

 

어떤 절차로 만들어 내는지 알아보겠습니다. 

1. 원본(source)영상과 대상(destination) 영상을 프레임 단위의 이미지 시퀀스로 저장

2. 합성된 이미지 시퀀스 생성

3. 이미지 시퀀스를 다시 동영상으로 묶기

4. 오디오 합성

 

컴퓨터 비전 분야에서는 FFMpeg 거의 필수로 사용됩니다. 

 

동영상으로 바로 작업을 하지 않고 이미지 프레임으로 바꾼 다음에 그것을 합쳐서 동영상으로 만드는 과정을 거쳐 보겠습니다. 

 

pip install ffmpeg-python 을 먼저 설치를 해 주세요.

 

FFMpeg은 최적화도 잘 되어 있고 오랜 역사를 가지고 있습니다.  여러분이 이름만 대면 알만한 소프트웨어들이 내부적으로 FFMpeg을 사용하는 경우도 아주 많습니다.  FFMpeg은 터미널에서 명령어도 사용하는 경우가 많습니다. 

 

FFMpeg을 이용해서 동영상 하나를 여러개의 시퀀스 저장하는 방법을 알아보겠습니다. 

 

별도의 폴더를 만들기 위해 mkdir 함수를 사용합니다.  images 폴더가 없다면  폴더를 만들도록 코딩하였습니다. 

동영상 파일을 읽어드리거나 이미지를 저장하거나 하는 코딩을 할때는 파일과 관련된 작업들은 예외처리를 사용해야 됩니다. 예제에서는 예외처리를 생략을 하고 진행을 하도록 하겠습니다. 

 

[보충] 체이닝(chaining)은 메써드를 연쇄적으로 호출하는 것을 의미합니다. 

 

ffmpeg.input(..).output(..).run(..) 

 

ffmpeg.input("virtual_billboard_dest.mp4")

             .output("images/dest%05d.jpg", start_number=0)

             .run(capture_stdout=True, capture_stderr=True) 

 

input은 어떤 파일로 읽어 들어야 되는지 인수로 넣어주고요.

output은 어떤 이미지 파일 형식으로 저장할 지를 지정을 해주고 있습니다. 

 

dest%05d.jpg  는  start_number는 0번부터 시작했으므로 아래와 같이 파일이 저장됩니다.  

 

dest00000.jpg

dest00001.jpg

dest00002.jpg

...

 

 

capture_stdout=True, capture_stderr=True  True로 설정하면 어떤 메시지가 나오는지를 확인할 수가 있습니다. 

 

실행을 하면 여러가지 메시지와 함께 실행되는걸 확인할 수 있습니다. 

 

images 폴더를 보시면 여러개의 프레임 단위로 저장된것을 확인할 수 있습니다. 

원본 이미지를 대상 이미지의 어디에 붙일지 픽셀 좌표를 찾습니다. 

 

대상이미지의 첫번째 이미지를 읽어서 화면에 보여주고 있구요. 

 

원본이미지를 스크린에 갔다 붙이고 싶은거죠.   좌측 상단을 클리기을 해주면  픽셀단위 좌표가 나오고 있구요   원하는 좌표를 클릭하면 좌표에 위치를 얻을 수 있는 소스 코드입니다.  클릭후 좌표를 알아내세요. 

아래와 같이 좌표를 알아냈습니다. 

 

[232,100] [606,92] [602,352] [236,316]

 

 

이제 좌표도 찾았으니 대상이미지에 원본이미지를 붙이는 작업을 해 봅시다. 

 

 

네모서리의 좌표를  원본과 대상을 array로 설정합니다. 

 

pts_src = np.array([[0.0], [853,0], [863,479], [0,479]])

pts_dst = np.array([[232,100], [606,92], [602,352], [236,316]])

 

findHomography는 원본array와 대상array를 인수로 넣어주면  결과값을 대상위치에 넣을 수 있는 행렬을 찾아줍니다. 

 

리턴 받은 h 행렬을 이용해서 warpPerspective 함수를 호출을 하면 원본 이미지가 변경된것을 볼 수 잇습니다. 

 

그 다음 단계로는 대상이미지 중에서 원본이미지를 덮어 쒸울 부분을 완전히 검은색 (0,0,0)으로 만들어줍니다. 

 

cv2.fillConvexPoly(im_dst, pts_dst.astype(int), (0,0,0), cv2.LINE_AA)

 

원본이미지를 변형시킨것과 대상이미지에 검은색부분으로 만든 이미지를 합치면  우리가 원하는 합성된 이미지를 얻을 수가 있습니다. 

 

 

 

한 프레임을 어떻게 만드는지 알아냈으니 이제 여러 프레임을 만드는 작업을 해 봅시다. 

 

여러 파일을 다루는 방법부터 알아보겠습니다. 

 

폴더안에 어떤 파일들이 들어 있는지 알기 위해서는 os.listdir 함수를 이용합니다. 

glob을 이용하시면 원하는 폴더에 조건을 걸어서 원하는 파일들의 이름을 검색할 수 있습니다.

 

 

 

여러이미지 파일의 합성을 진행해 보도록 하겠습니다. 

 

대상과 원본의 프레임수가 다릅니다. 둘 중 작은 수로 프레임수를 결정 하겠습니다. 

 

file_num = min( 원본 , 대상 ) 

 

zfill 함수를 이용을 해서   00000, 00001 이런식으로 사용할 수 있도록 합니다. 

 

합성한 이미지를 저장합니다. 

cv2.imwrite(...) 

 

images 폴더를 보시면 합성된 이미지들을 보실 수 있습니다.

 

합성된 이미지 시퀀스를 이용해서 동영상으로 만드는 작업을 해 보겠습니다. 

 

 

 

ffmpeg.input("images/comp%05d.jpg")

             .output("virtual_billboard_comp.mp4", start_number=0)

             .run(capture_stdout=True, capture_stderr=True)

 

합성이 된 동영상을 얻을 수 있습니다. 

합성된 동영상에 오디오를 추가해 봅시다.

 

먼저 대상 동영상에서 오디오 파일을 추출해 보겠습니다. 

 

import ffmpeg

 

ffmpeg.input("virtual_billboard_dest.mp4")

            .output("virtual_billboard_dest.wav").run()

 

 

이제 합성을 해 봅시다. 

 

 

 

Reference

https://www.youtube.com/watch?v=UVe_nxSv-lU

댓글