학교에서 졸업 프로젝트를 진행하면서 영상의 프레임을 추출해야하는 일이 생겨서 만든 프로그램이다.
이 작업 하나 때문에 프로그램 깔기도 좀 뭐하고
파이썬을 막 시작했을 때라 뭔가 만들어보면 좋을 것 같아서 만들었었다.
gui는 tkinter 라이브러리로, 동영상 프레임은 opencv 추출하도록 짰고,
exe파일화는 pyinstaller 라이브러리를 깔아서 만들었다.
지금도 그렇긴하지만 파이썬의 기초조차도 아에 모를 때라서 검색에 의존해서 마구자비로 만들었는데
꽤 최근까지도 나름 잘 썼었다.(그런데 폴더나 이름이 한글이면 관련 처리를 안해줘서 추출이 안됬던걸로 기억)
import os
desktop = os.path.join(os.path.expanduser('~'),'Desktop')
def fileload():
filename = fd.askopenfilename(initialdir=desktop, title="Select file",
filetypes=(("video files", "*.mp4"),
("all files", "*.*")))
global filedir
filedir = filename
global filedirtext
filedirtext.delete(0, 'end')
filedirtext.insert(0, filedir)
파일 불러오기 화면과 함수이다.
함수를 정의하기 전에 os 모듈을 import하고 os.path~ 명령으로 사용자의 바탕하면 경로를 찾아 저장한다.
그 후 버튼이 눌리면 fileload함수를 호출하여 파일 선택기를 바탕화면을 보여주도록 띄운다.
파일이 선택되면 filename에 파일의 경로가 저장되고 이를 전역변수인 filedir에 저장한 후
UI에서 경로를 띄워주는 filedirtext의 기존 내용을 지우고 삽입한다.
def run():
if(filedir == None or dirpath == None):
msgbox.showinfo("Error!", "입력 파일이 없습니다")
return
else:
imgwid = int(videowidth.get())
imghei = int(videoheight.get())
frame = int(spinbox.get())
print("Start Extracting...")
print(filedir)
print(dirpath)
vidcap = cv2.VideoCapture(filedir)
count = 0
while(vidcap.isOpened()):
ret, image = vidcap.read()
if(ret == FALSE): break
if(int(vidcap.get(1)) % frame == 0):
print("Saved frame number : " + str(int(vidcap.get(1))))
image = cv2.resize(image, dsize=(imgwid, imghei), fx=imgfx, fy=imgfy, interpolation=cv2.INTER_LINEAR)
cv2.imwrite(dirpath + "/frame%d.png" % count, image)
count += 1
vidcap.release()
msgbox.showinfo("Finish!", "추출이 끝났습니다.")
return
opencv를 이용해서 동영상을 불러와 프레임 단위로 추출해 저장하는 코드이다.
vidcap에 저장된 동영상을 열고 읽어서 지정한 frame 변수마다 imwrite로 프레임을 저장한다.
더보기
from tkinter import *
from tkinter import ttk
import tkinter as tk
import tkinter.filedialog as fd
import tkinter.messagebox as msgbox
import cv2
import os
filedir = None
dirpath = None
desktop = os.path.join(os.path.expanduser('~'),'Desktop')
def fileload():
filename = fd.askopenfilename(initialdir=desktop, title="Select file",
filetypes=(("video files", "*.mp4"),
("all files", "*.*")))
global filedir
filedir = filename
global filedirtext
filedirtext.delete(0, 'end')
filedirtext.insert(0, filedir)
def pathload():
pathdiry = fd.askdirectory(initialdir=desktop, title="Select file")
global dirpath
dirpath = pathdiry
global pathdirtext
pathdirtext.delete(0, 'end')
pathdirtext.insert(0, dirpath)
def choose():
global combo
global imgwid
global imghei
global imgfx
global imgfy
global videowidth
global videoheight
opnum = combo.current()
if opnum == 0:
videowidth.delete(0, 'end')
videoheight.delete(0, 'end')
videowidth.insert(0, 0)
videoheight.insert(0, 0)
videowidth.configure(state=DISABLED)
videoheight.configure(state=DISABLED)
imgwid = 0
imghei = 0
imgfx = 0.75
imgfy = 0.75
elif opnum == 1:
videowidth.delete(0, 'end')
videoheight.delete(0, 'end')
videowidth.insert(0, 0)
videoheight.insert(0, 0)
videowidth.configure(state=DISABLED)
videoheight.configure(state=DISABLED)
imgwid = 0
imghei = 0
imgfx = 0.5
imgfy = 0.5
elif opnum == 2:
videowidth.delete(0, 'end')
videoheight.delete(0, 'end')
videowidth.insert(0, 0)
videoheight.insert(0, 0)
videowidth.configure(state=DISABLED)
videoheight.configure(state=DISABLED)
imgwid = 0
imghei = 0
imgfx = 0.25
imgfy = 0.25
elif opnum == 3:
videowidth.delete(0, 'end')
videoheight.delete(0, 'end')
videowidth.insert(0, 0)
videoheight.insert(0, 0)
videowidth.configure(state=DISABLED)
videoheight.configure(state=DISABLED)
imgwid = 0
imghei = 0
imgfx = 0.1
imgfy = 0.1
elif opnum == 4:
videowidth.configure(state="normal")
videoheight.configure(state="normal")
imgfx = 0
imgfy = 0
def resizeon():
global combo
global imgwid
global imghei
global imgfx
global imgfy
if(chkValue.get() == FALSE) :
videowidth.configure(state=DISABLED)
videoheight.configure(state=DISABLED)
combo.configure(state="disabled")
videowidth.delete(0, 'end')
videoheight.delete(0, 'end')
videowidth.insert(0, 0)
videoheight.insert(0, 0)
imgfx = 1
imgfy = 1
else:
combo.configure(state="readonly")
choose()
def option(event):
choose()
def run():
if(filedir == None or dirpath == None):
msgbox.showinfo("Error!", "입력 파일이 없습니다")
return
else:
imgwid = int(videowidth.get())
imghei = int(videoheight.get())
frame = int(spinbox.get())
print("Start Extracting...")
print(filedir)
print(dirpath)
vidcap = cv2.VideoCapture(filedir)
count = 0
while(vidcap.isOpened()):
ret, image = vidcap.read()
if(ret == FALSE): break
if(int(vidcap.get(1)) % frame == 0):
print("Saved frame number : " + str(int(vidcap.get(1))))
image = cv2.resize(image, dsize=(imgwid, imghei), fx=imgfx, fy=imgfy, interpolation=cv2.INTER_LINEAR)
cv2.imwrite(dirpath + "/frame%d.png" % count, image)
count += 1
vidcap.release()
msgbox.showinfo("Finish!", "추출이 끝났습니다.")
return
# 창만들기
print("*****************Frame Extractor by LJH**********************")
root = Tk()
root.title("Frame Extrator")
root.geometry("250x350")
root.resizable(False, False)
videotext = Label(root, text="Video")
videotext.place(x=30, y=30)
filedirtext = tk.Entry(root)
# filedirtext.configure(state="readonly")
filedirtext.place(x=30, y=50, width=135, height=25)
filebtn = Button(root, text="Load", command=fileload)
filebtn.place(x=170, y=50, width=50)
foldertext = Label(root, text="저장 경로")
foldertext.place(x=30, y=90)
pathdirtext = tk.Entry(root)
# pathdirtext.configure(state=DISABLED)
pathdirtext.place(x=30, y=110, width=135, height=25)
pathbtn = Button(root, text="Load", command=pathload)
pathbtn.place(x=170, y=110, width=50)
frametext = Label(root, text="frame")
frametext.place(x=30, y=150)
var = StringVar(root)
var.set("15")
spinbox=tk.Spinbox(root, from_ = 0, to = 1000, textvariable=var)
spinbox.place(x=30, y=170, width=190, height=25)
combo = ttk.Combobox(root, width=20, textvariable=str, state='readonly')
combo['values'] = ('75%', '50%', '25%', '10%', '직접 설정')
combo.current(1)
combo.place(x=100, y=213, width=117)
combo.bind("<<ComboboxSelected>>", option)
imgwid = 0
imghei = 0
imgfx = 0.5
imgfy = 0.5
chkValue = tk.BooleanVar()
resize = tk.Checkbutton(root, text="Resize", command=resizeon, variable=chkValue)
resize.place(x=25, y=210)
resize.select()
videowidth = tk.Entry(root)
videowidth.insert(0, 0)
videowidth.configure(state=DISABLED)
videowidth.place(x=70, y=250, width=65, height=25)
x = Label(root, text="X")
x.place(x=138, y=250)
videoheight = tk.Entry(root, width=20)
videoheight.insert(0, 0)
videoheight.configure(state=DISABLED)
videoheight.place(x=155, y=250, width=65, height=25)
runbtn = Button(root, text="Run!", height=3, command=run)
runbtn.pack(side="bottom", fill="x")
root.mainloop()
'토이프로젝트 > 기타' 카테고리의 다른 글
[python] HWPtoPDF 프로그램 (0) | 2022.02.21 |
---|---|
[React] Numpad 만들기 (0) | 2022.02.21 |