teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

6

追記

2021/05/12 04:47

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -117,15 +117,14 @@
117
117
  ![イメージ説明](844dd72ce6a4bdff692cee2bcd80abd5.jpeg)
118
118
 
119
119
  # 追記2
120
- - ウィンドウが720x480の時、映像が右寄りに描画
121
- - リサイズ時に消えてしまう。
122
120
 
123
- ![イージ説明](707bcb188834dae0c40687a45a089d2a.jpeg)
121
+ teamikl様からのコントの指摘をもとに変更
124
-
125
122
  ```Python
126
123
  from datetime import datetime
127
124
  from PIL import Image, ImageTk
128
125
  import cv2
126
+ import queue
127
+ import threading
129
128
  import tkinter as tk
130
129
 
131
130
  class App:
@@ -135,14 +134,19 @@
135
134
  self.width = self.vcap.get(cv2.CAP_PROP_FRAME_WIDTH)
136
135
  self.height = self.vcap.get(cv2.CAP_PROP_FRAME_HEIGHT)
137
136
 
137
+ self.data_queue = queue.Queue()
138
+
138
139
  self.win = win
139
140
  self.win.title("Camera")
141
+ self.thread = threading.Thread(target=self.get_queue)
142
+ self.thread.start()
140
143
  self.disp_center(self.win, 720, 480)
141
144
  self.win.protocol("WM_DELETE_WINDOW", self.close)
142
145
  self.create_view()
143
146
  self.bind_event()
144
147
  self.update_by_timer()
145
148
 
149
+
146
150
  def disp_center(self, win, wx=400, wy=300):
147
151
  #win.resizable(0, 0)
148
152
  dx = win.winfo_screenwidth()
@@ -151,10 +155,14 @@
151
155
  "+" + str(int(dx/2 - wx/2)) + "+" + str(int(dy/2 - wy/2))
152
156
  win.geometry(win_size)
153
157
 
158
+
154
159
  def close(self):
160
+ self.data_queue.put(["close", None])
161
+ self.thread.join()
155
162
  self.win.destroy()
156
163
  self.vcap.release()
157
164
 
165
+
158
166
  def create_view(self):
159
167
  self.win.rowconfigure(0, weight=1)
160
168
  self.win.columnconfigure(0, weight=1)
@@ -167,12 +175,14 @@
167
175
  self.canvas = tk.Canvas(self.frame)
168
176
  self.canvas.grid(row=0, column=0, sticky="nsew", padx=10, pady=10)
169
177
 
170
- _, frame = self.vcap.read()
178
+ _, frm = self.vcap.read()
171
- frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
179
+ self.frame = cv2.cvtColor(frm, cv2.COLOR_BGR2RGB)
172
- self.photo = ImageTk.PhotoImage(image = Image.fromarray(frame))
180
+ self.photo = ImageTk.PhotoImage(image = Image.fromarray(self.frame))
181
+ #self.canvas.update()
173
182
  cv_w = self.canvas.winfo_reqwidth()
174
183
  cv_h = self.canvas.winfo_reqheight()
175
- self.img_id = self.canvas.create_image(cv_w // 2, cv_h // 2, image=self.photo)
184
+ self.img_id = self.canvas.create_image(cv_w // 2, cv_h // 2, image=self.photo, anchor="center")
185
+
176
186
 
177
187
  """
178
188
  self.canvas.update()
@@ -200,35 +210,47 @@
200
210
 
201
211
 
202
212
  def pushed_button(self):
203
- _, frame = self.vcap.read()
204
- frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
213
+ self.data_queue.put(["snapshot", None])
205
- print(frame)
206
- cv2.imwrite( "Desktop/frame-" + datetime.now().strftime("%Y-%d-%m-%H-%M-%S") + ".jpg",
207
- cv2.cvtColor( frame, cv2.COLOR_BGR2RGB ) )
208
214
 
209
215
 
210
216
  def update_by_timer(self):
211
- _, frame = self.vcap.read()
217
+ _, frm = self.vcap.read()
212
- frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
218
+ self.frame = cv2.cvtColor(frm, cv2.COLOR_BGR2RGB)
213
- self.photo = ImageTk.PhotoImage(image = Image.fromarray(frame))
219
+ self.photo = ImageTk.PhotoImage(image = Image.fromarray(self.frame))
214
220
  self.canvas.itemconfig(self.img_id, image=self.photo)
215
221
  self.canvas.after(15, self.update_by_timer)
216
222
 
217
223
 
218
224
  def update_by_resize(self, e):
219
- _, frame = self.vcap.read()
220
- frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
221
- self.photo = ImageTk.PhotoImage(image = Image.fromarray(frame))
222
- self.canvas.itemconfig(self.img_id, image=self.photo)
225
+ self.canvas.itemconfig(self.img_id, image=self.photo, anchor="center")
223
- cv_w = self.canvas.winfo_reqwidth()
226
+ cv_w = self.canvas.winfo_width()
224
- cv_h = self.canvas.winfo_reqheight()
227
+ cv_h = self.canvas.winfo_height()
228
+ print(datetime.now())
229
+ print(cv_w, cv_h)
225
- self.canvas.move(self.img_id, cv_w // 2, cv_h // 2)
230
+ self.canvas.coords(self.img_id, cv_w // 2, cv_h // 2)
226
231
 
227
232
 
228
233
  def bind_event(self):
229
234
  self.canvas.bind("<Configure>", self.update_by_resize)
230
235
 
231
236
 
237
+ def get_queue(self):
238
+ while True:
239
+ msg, data = self.data_queue.get()
240
+ if msg == "snapshot":
241
+ self.snapshot()
242
+ elif msg == "close":
243
+ break
244
+ else:
245
+ print("Undefined msg")
246
+
247
+ def snapshot(self):
248
+ filename = "C:/Users/user01/Desktop/img/frame-" + datetime.now().strftime("%Y-%d-%m-%H-%M-%S_%f") + ".jpg"
249
+ cv2.imwrite( filename,
250
+ cv2.cvtColor( self.frame, cv2.COLOR_BGR2RGB ) )
251
+ print(filename)
252
+
253
+
232
254
  def main():
233
255
  win = tk.Tk()
234
256
  App(win)

5

文法修正

2021/05/12 04:47

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -117,7 +117,9 @@
117
117
  ![イメージ説明](844dd72ce6a4bdff692cee2bcd80abd5.jpeg)
118
118
 
119
119
  # 追記2
120
+ - ウィンドウが720x480の時、映像が右寄りに描画
120
- 映像が右寄りに描画、リサイズ時に消えてしまう。
121
+ - リサイズ時に消えてしまう。
122
+
121
123
  ![イメージ説明](707bcb188834dae0c40687a45a089d2a.jpeg)
122
124
 
123
125
  ```Python

4

文法修正

2021/05/12 00:22

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -117,7 +117,7 @@
117
117
  ![イメージ説明](844dd72ce6a4bdff692cee2bcd80abd5.jpeg)
118
118
 
119
119
  # 追記2
120
- 映像が寄りに描画、リサイズ時に消えてしまう。
120
+ 映像が寄りに描画、リサイズ時に消えてしまう。
121
121
  ![イメージ説明](707bcb188834dae0c40687a45a089d2a.jpeg)
122
122
 
123
123
  ```Python

3

追記

2021/05/12 00:17

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -114,4 +114,124 @@
114
114
 
115
115
  # 追記
116
116
  映像が右下寄りに描画されてしまう。
117
- ![イメージ説明](844dd72ce6a4bdff692cee2bcd80abd5.jpeg)
117
+ ![イメージ説明](844dd72ce6a4bdff692cee2bcd80abd5.jpeg)
118
+
119
+ # 追記2
120
+ 映像が左寄りに描画、リサイズ時に消えてしまう。
121
+ ![イメージ説明](707bcb188834dae0c40687a45a089d2a.jpeg)
122
+
123
+ ```Python
124
+ from datetime import datetime
125
+ from PIL import Image, ImageTk
126
+ import cv2
127
+ import tkinter as tk
128
+
129
+ class App:
130
+ def __init__(self, win):
131
+ video_source = 0
132
+ self.vcap = cv2.VideoCapture(video_source)
133
+ self.width = self.vcap.get(cv2.CAP_PROP_FRAME_WIDTH)
134
+ self.height = self.vcap.get(cv2.CAP_PROP_FRAME_HEIGHT)
135
+
136
+ self.win = win
137
+ self.win.title("Camera")
138
+ self.disp_center(self.win, 720, 480)
139
+ self.win.protocol("WM_DELETE_WINDOW", self.close)
140
+ self.create_view()
141
+ self.bind_event()
142
+ self.update_by_timer()
143
+
144
+ def disp_center(self, win, wx=400, wy=300):
145
+ #win.resizable(0, 0)
146
+ dx = win.winfo_screenwidth()
147
+ dy = win.winfo_screenheight()
148
+ win_size = str(wx) + "x" + str(wy) + \
149
+ "+" + str(int(dx/2 - wx/2)) + "+" + str(int(dy/2 - wy/2))
150
+ win.geometry(win_size)
151
+
152
+ def close(self):
153
+ self.win.destroy()
154
+ self.vcap.release()
155
+
156
+ def create_view(self):
157
+ self.win.rowconfigure(0, weight=1)
158
+ self.win.columnconfigure(0, weight=1)
159
+
160
+ self.frame = tk.Frame(self.win, relief="sunken", bd=1)
161
+ self.frame.grid(row=0, column=0, sticky="nsew")
162
+ self.frame.rowconfigure(0, weight=1)
163
+ self.frame.columnconfigure(0, weight=1)
164
+
165
+ self.canvas = tk.Canvas(self.frame)
166
+ self.canvas.grid(row=0, column=0, sticky="nsew", padx=10, pady=10)
167
+
168
+ _, frame = self.vcap.read()
169
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
170
+ self.photo = ImageTk.PhotoImage(image = Image.fromarray(frame))
171
+ cv_w = self.canvas.winfo_reqwidth()
172
+ cv_h = self.canvas.winfo_reqheight()
173
+ self.img_id = self.canvas.create_image(cv_w // 2, cv_h // 2, image=self.photo)
174
+
175
+ """
176
+ self.canvas.update()
177
+ cv_w = self.canvas.winfo_width()
178
+ cv_h = self.canvas.winfo_height()
179
+
180
+ rec_id = self.canvas.create_rectangle(0, 0, cv_w, cv_h, fill="black")
181
+
182
+
183
+ # 長方形の座標取得
184
+ rec_pos = self.canvas.coords(rec_id)
185
+ # テキストを描画(位置は適当)
186
+ text_id = self.canvas.create_text(0, 0, text="NO SIGNAL", font=("", 20), fill="white")
187
+ # テキストのサイズ取得
188
+ text_size = self.canvas.bbox(text_id)
189
+ # テキストの座標移動
190
+ rc_x = rec_pos[2] / 2
191
+ rc_y = rec_pos[2] / 3
192
+ tc_y = text_size[3] / 2
193
+ self.canvas.move(text_id, rc_x - (rec_pos[0] / 2), rc_y - tc_y)
194
+ """
195
+
196
+ self.button = tk.Button(self.win, text="Snapshot", command=self.pushed_button)
197
+ self.button.grid(row=1, column=0, sticky="", pady=10)
198
+
199
+
200
+ def pushed_button(self):
201
+ _, frame = self.vcap.read()
202
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
203
+ print(frame)
204
+ cv2.imwrite( "Desktop/frame-" + datetime.now().strftime("%Y-%d-%m-%H-%M-%S") + ".jpg",
205
+ cv2.cvtColor( frame, cv2.COLOR_BGR2RGB ) )
206
+
207
+
208
+ def update_by_timer(self):
209
+ _, frame = self.vcap.read()
210
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
211
+ self.photo = ImageTk.PhotoImage(image = Image.fromarray(frame))
212
+ self.canvas.itemconfig(self.img_id, image=self.photo)
213
+ self.canvas.after(15, self.update_by_timer)
214
+
215
+
216
+ def update_by_resize(self, e):
217
+ _, frame = self.vcap.read()
218
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
219
+ self.photo = ImageTk.PhotoImage(image = Image.fromarray(frame))
220
+ self.canvas.itemconfig(self.img_id, image=self.photo)
221
+ cv_w = self.canvas.winfo_reqwidth()
222
+ cv_h = self.canvas.winfo_reqheight()
223
+ self.canvas.move(self.img_id, cv_w // 2, cv_h // 2)
224
+
225
+
226
+ def bind_event(self):
227
+ self.canvas.bind("<Configure>", self.update_by_resize)
228
+
229
+
230
+ def main():
231
+ win = tk.Tk()
232
+ App(win)
233
+ win.mainloop()
234
+
235
+ if __name__ == "__main__":
236
+ main()
237
+ ```

2

画像追加

2021/05/12 00:11

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -110,4 +110,8 @@
110
110
 
111
111
  参考にした記事
112
112
 
113
- - [パソコンに接続したカメラの映像をGUIに表示する。](https://qiita.com/kotai2003/items/3d31528d56059c848458)
113
+ - [パソコンに接続したカメラの映像をGUIに表示する。](https://qiita.com/kotai2003/items/3d31528d56059c848458)
114
+
115
+ # 追記
116
+ 映像が右下寄りに描画されてしまう。
117
+ ![イメージ説明](844dd72ce6a4bdff692cee2bcd80abd5.jpeg)

1

文法修正

2021/05/11 07:58

投稿

person
person

スコア224

title CHANGED
@@ -1,1 +1,1 @@
1
- Python3 Tkinter カメラ映像の出力位置と接続が途切れた場合の処理について
1
+ Python3 Tkinter カメラ映像の描画位置と、カメラとの接続が途切れた場合の処理について
body CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  ソースコードを作りましたが、下記について悩んでいます。
4
4
 
5
- - 出力場所をcanvasの中央にしたいが左上に表示されてしまっている
5
+ - 描画位置をcanvasの中央にしたいが左上に表示されてしまっている
6
6
  - カメラの接続が物理的に切れた場合などの処理をどうすればいいかわからない
7
7
 
8
- 出力場所については、おそらくcreate_image()の座標設定だと思いますが、指定する座標の求め方がわかりません。
8
+ 描画位置については、おそらくcreate_image()の座標設定だと思いますが、指定する座標の求め方がわかりません。
9
- 解像度/2をすればよいのでしょうか?
9
+ カメラの解像度を求めて、解像度/2をすればよいのでしょうか?
10
10
 
11
11
  カメラの接続が物理的に切れる場合の処理は、try-exceptを使えばよいのでしょうか?
12
12
  (手元にUSBカメラがなく、内蔵カメラで試しているため切断した際の動作確認ができずどのような挙動になるかはわかりませんが、エラーは出ると思うので。)