#main.py
import tkinter as tk
import app_main.main_ui as win
import app_main.make_widgets as mkw
import app_main.camera_service as s
def main():
img_path = 'img/a.jpg'
root = tk.Tk()
app = win.AppWindow(root, '650x700+100+100', img_path) #Frame
service = s.CameraService(app) #카메라 서비스 생성
mkw.make(app, service) #app 프레임을 받아서 거기에 위젯을 생성해 배치하고, 이벤트핸들러정의해놓는 작업
app.mainloop()
main()
#main_ui.py
import tkinter as tk
import cv2
from PIL import Image
from PIL import ImageTk
class AppWindow(tk.Frame):#Frame
def __init__(self, master=None, size=None, path=None):
super().__init__(master)
self.master = master #Tk()객체. 윈도우
self.master.geometry(size)
self.master.resizable(True, True)
self.pack()#이미지 레이블 frame
self.sub_fr = None#버튼 있는 frame
self.src = None #이미지 변수
self.frame = None #이미지 출력할 레이블
self.create_widgets(path)#기본 위젯 생성 함수
def make_img(self, path):#path 경로의 이미지를 레이블에 출력
#opencv 이미지
src = cv2.imread(path) #path 이미지를 읽어서 src에 저장
src = cv2.resize(src, (640, 400))
#이미지 color space를 rgb로 변경
img = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)
#넘파이 배열을 필로우 이미지 변환
img = Image.fromarray(img)#넘파이 배열을 이미지로 변환
#tkinter에서 사용할 수 있는 이미지로 변환
#self.src = 이미지
self.src = ImageTk.PhotoImage(image=img)#tkinter에서 인식할 수 있는 이미지로 생성
def create_widgets(self, path):#프레임에 위젯 추가
self.make_img(path)
#이미지 뿌릴 레이블 생성
self.frame = tk.Label(self.master, image=self.src)
#레이블을 프레임에 붙임
self.frame.pack()
#추가 위젯을 배치할 프레임 생성
self.sub_fr = tk.Frame(self.master)#frame
#프레임 윈도우 붙임
self.sub_fr.pack()
def change_img(self, img):#레이블의 이미지 변경
img = cv2.resize(img, (640, 400))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = Image.fromarray(img)
self.src = ImageTk.PhotoImage(image=img)
self.frame['image']=self.src
#camera_service.py
import threading
import cv2, os
def preview_th(stop, app):
cam = cv2.VideoCapture(0, cv2.CAP_DSHOW)
print(1, stop)
print(2, stop())
cam.set(3, 640)
cam.set(4, 400)
while stop():
ret, frame = cam.read()
if ret:
app.change_img(frame)
cv2.waitKey(100)
cam.release()
def img_view_th(stop, app):
flist = os.listdir('./img')
i=0
while stop():
p = './img/'+flist[i%len(flist)]
i+=1
src = cv2.imread(p)
app.change_img(src)
cv2.waitKey(1000)
def video_write_th(stop, app, fname):
cam = cv2.VideoCapture(0, cv2.CAP_DSHOW)
codec = cv2.VideoWriter_fourcc(*'mp4v') # 사용할 코덱 생성
#동영상 작성자 객체 생성
path= './video/'+fname+'.mp4'
out = cv2.VideoWriter(path, codec, 25.0, (640, 400))
while stop():
ret, frame = cam.read()
if ret:
frame = cv2.resize(frame, (640,400))
out.write(frame)
app.change_img(frame)
else:
break
cv2.waitKey(26)
cam.release()
def video_read_th(stop, app, fname):
path = './video/' + fname
cam = cv2.VideoCapture(path)
# cam.set(3, 640)
# cam.set(4, 400)
while stop():
ret, frame = cam.read()
if ret:
app.change_img(frame)
else:
break
cv2.waitKey(26)
cam.release()
class CameraService:
def __init__(self, app):
self.cam = None
self.app = app #main_ui에서 만든 ui 창. AppWindow 객체
self.flag = True #쓰레드 종료 flag
def stop(self):
self.flag = False
def preview(self):
self.flag = True
cam_th = threading.Thread(target=preview_th, args=(lambda:self.flag, self.app))
cam_th.start()
def capture(self, fname):
print('capture')
self.stop()
self.cam = cv2.VideoCapture(0)
self.cam.set(3, 640)
self.cam.set(4, 400)
ret, frame = self.cam.read()
self.app.change_img(frame)
cv2.imwrite('img/'+fname, frame)
self.cam.release()
def write_avi(self, fname):
self.flag = True
cam_th = threading.Thread(target=video_write_th, args=(lambda: self.flag, self.app, fname))
cam_th.start()
def view_img(self):
self.flag = True
cam_th = threading.Thread(target=img_view_th, args=(lambda: self.flag, self.app))
cam_th.start()
def view_video(self, fname):
self.flag = True
cam_th = threading.Thread(target=video_read_th,
args=(lambda: self.flag, self.app, fname))
cam_th.start()
#make_widgets.py
import tkinter as tk
c_serv = None #서비스 객체
def btn1_clicked():
c_serv.preview()
def btn2_clicked(app):
fname = app.ent.get()
c_serv.capture(fname)
def btn3_clicked(app):
fname= app.ent.get()
c_serv.write_avi(fname)
print('btn3 clicked')
def btn4_clicked():
c_serv.stop()
def btn5_clicked(app):
fname= app.ent.get()
c_serv.view_video(fname)
def btn6_clicked():
c_serv.view_img()
def btn7_clicked():
c_serv.stop()
def make(app, service=None):
global c_serv
c_serv = service
app.ent = tk.Entry(app.sub_fr, width=60)
app.btn1 = tk.Button(app.sub_fr, width=10, font=60, text='preview')
app.btn2 = tk.Button(app.sub_fr, width=10, font=60, text='사진저장')
app.btn3 = tk.Button(app.sub_fr, width=10, font=60, text='영상촬영')
app.btn4 = tk.Button(app.sub_fr, width=10, font=60, text='촬영종료')
app.btn5 = tk.Button(app.sub_fr, width=10, font=60, text='동영상보기')
app.btn6 = tk.Button(app.sub_fr, width=10, font=60, text='슬라이드시작')
app.btn7 = tk.Button(app.sub_fr, width=10, font=60, text='슬라이드종료')
app.ent.grid(row=0, column=0, columnspan=4)
app.btn1.grid(row=1, column=0)
app.btn2.grid(row=1, column=1)
app.btn3.grid(row=1, column=2)
app.btn4.grid(row=1, column=3)
app.btn5.grid(row=2, column=0)
app.btn6.grid(row=2, column=1)
app.btn7.grid(row=2, column=2)
app.btn1['command'] = btn1_clicked
app.btn2['command'] = lambda: btn2_clicked(app)
app.btn3['command'] = lambda: btn3_clicked(app)
app.btn4['command'] = btn4_clicked
app.btn5['command'] = lambda: btn5_clicked(app)
app.btn6['command'] = btn6_clicked
app.btn7['command'] = btn7_clicked
'OpenCV' 카테고리의 다른 글
이미지 위에 글자이미지올리기(opencv-파이썬) (0) | 2021.01.09 |
---|---|
카메라 재미있는 효과(영화 트론 스타일) (0) | 2021.01.09 |
움직임감지예제(OpenCV-파이썬) (0) | 2021.01.09 |