-
Notifications
You must be signed in to change notification settings - Fork 10
/
Camera.py
230 lines (195 loc) · 7.1 KB
/
Camera.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
import cv2
import time
import os
import datetime
from threading import Thread
from queue import Queue
class Camera:
def __init__(self, mirror=False):
self.data = None
self.cam = cv2.VideoCapture(0)
self.WIDTH = 640
self.HEIGHT = 480
self.center_x = self.WIDTH / 2
self.center_y = self.HEIGHT / 2
self.touched_zoom = False
self.image_queue = Queue()
self.video_queue = Queue()
self.scale = 1
self.__setup()
self.recording = False
self.mirror = mirror
def __setup(self):
self.cam.set(cv2.CAP_PROP_FRAME_WIDTH, self.WIDTH)
self.cam.set(cv2.CAP_PROP_FRAME_HEIGHT, self.HEIGHT)
time.sleep(2)
def get_location(self, x, y):
self.center_x = x
self.center_y = y
self.touched_zoom = True
def stream(self):
# streaming thread 함수
def streaming():
# 실제 thread 되는 함수
self.ret = True
while self.ret:
self.ret, np_image = self.cam.read()
if np_image is None:
continue
if self.mirror:
# 거울 모드 시 좌우 반전
np_image = cv2.flip(np_image, 1)
if self.touched_zoom:
np_image = self.__zoom(np_image, (self.center_x, self.center_y))
else:
if not self.scale == 1:
np_image = self.__zoom(np_image)
self.data = np_image
k = cv2.waitKey(1)
if k == ord('q'):
self.release()
break
Thread(target=streaming).start()
def __zoom(self, img, center=None):
# zoom하는 실제 함수
height, width = img.shape[:2]
if center is None:
# 중심값이 초기값일 때의 계산
center_x = int(width / 2)
center_y = int(height / 2)
radius_x, radius_y = int(width / 2), int(height / 2)
else:
# 특정 위치 지정시 계산
rate = height / width
center_x, center_y = center
# 비율 범위에 맞게 중심값 계산
if center_x < width * (1-rate):
center_x = width * (1-rate)
elif center_x > width * rate:
center_x = width * rate
if center_y < height * (1-rate):
center_y = height * (1-rate)
elif center_y > height * rate:
center_y = height * rate
center_x, center_y = int(center_x), int(center_y)
left_x, right_x = center_x, int(width - center_x)
up_y, down_y = int(height - center_y), center_y
radius_x = min(left_x, right_x)
radius_y = min(up_y, down_y)
# 실제 zoom 코드
radius_x, radius_y = int(self.scale * radius_x), int(self.scale * radius_y)
# size 계산
min_x, max_x = center_x - radius_x, center_x + radius_x
min_y, max_y = center_y - radius_y, center_y + radius_y
# size에 맞춰 이미지를 자른다
cropped = img[min_y:max_y, min_x:max_x]
# 원래 사이즈로 늘려서 리턴
new_cropped = cv2.resize(cropped, (width, height))
return new_cropped
def touch_init(self):
self.center_x = self.WIDTH / 2
self.center_y = self.HEIGHT / 2
self.touched_zoom = False
self.scale = 1
def zoom_out(self):
# scale 값을 조정하여 zoom-out
if self.scale < 1:
self.scale += 0.1
if self.scale == 1:
self.center_x = self.WIDTH
self.center_y = self.HEIGHT
self.touched_zoom = False
def zoom_in(self):
# scale 값을 조정하여 zoom-in
if self.scale > 0.2:
self.scale -= 0.1
def zoom(self, num):
if num == 0:
self.zoom_in()
elif num == 1:
self.zoom_out()
elif num == 2:
self.touch_init()
def save_picture(self):
# 이미지 저장하는 함수
ret, img = self.cam.read()
if ret:
now = datetime.datetime.now()
date = now.strftime('%Y%m%d')
hour = now.strftime('%H%M%S')
user_id = '00001'
filename = './images/cvui_{}_{}_{}.png'.format(date, hour, user_id)
cv2.imwrite(filename, img)
self.image_queue.put_nowait(filename)
def record_video(self):
# 동영상 녹화 함수
fc = 20.0
record_start_time = time.time()
now = datetime.datetime.now()
date = now.strftime('%Y%m%d')
t = now.strftime('%H')
num = 1
filename = 'videos/cvui_{}_{}_{}.avi'.format(date, t, num)
while os.path.exists(filename):
num += 1
filename = 'videos/cvui_{}_{}_{}.avi'.format(date, t, num)
codec = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X')
out = cv2.VideoWriter(filename, codec, fc, (int(self.cam.get(3)), int(self.cam.get(4))))
while self.recording:
if time.time() - record_start_time >= 600:
self.record_video()
break
ret, frame = self.cam.read()
if ret:
if len(os.listdir('./videos')) >= 100:
name = self.video_queue.get()
if os.path.exists(name):
os.remove(name)
out.write(frame)
self.video_queue.put_nowait(filename)
k = cv2.waitKey(1)
if k == ord('q'):
break
def show(self):
while True:
frame = self.data
if frame is not None:
cv2.imshow('SMS', frame)
cv2.setMouseCallback('SMS', self.mouse_callback)
key = cv2.waitKey(1)
if key == ord('q'):
# q : close
self.release()
cv2.destroyAllWindows()
break
elif key == ord('z'):
# z : zoom - in
self.zoom_in()
elif key == ord('x'):
# x : zoom - out
self.zoom_out()
elif key == ord('p'):
# p : take picture and save image (image folder)
self.save_picture()
elif key == ord('v'):
# v : zoom 상태를 원상태로 복구
self.touch_init()
elif key == ord('r'):
# r : 동영상 촬영 시작 및 종료
self.recording = not self.recording
if self.recording:
t = Thread(target=cam.record_video)
t.start()
def release(self):
self.cam.release()
cv2.destroyAllWindows()
def mouse_callback(self, event, x, y, flag, param):
if event == cv2.EVENT_LBUTTONDBLCLK:
self.get_location(x, y)
self.zoom_in()
elif event == cv2.EVENT_RBUTTONDOWN:
self.zoom_out()
if __name__ == '__main__':
cam = Camera(mirror=True)
cam.stream()
cam.show()