質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Raspbian

Raspbianは、DebianベースのRaspberry Pi用ディストリビューション。ハードウェア浮動小数点演算を有効にすることが可能で、Webブラウズなどの速度を向上できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

解決済

Python3 Tkinter Raspberry Piでカメラからバーコードを読もうとしたときに処理速度がだいぶ遅くなった

person
person

総合スコア180

Raspbian

Raspbianは、DebianベースのRaspberry Pi用ディストリビューション。ハードウェア浮動小数点演算を有効にすることが可能で、Webブラウズなどの速度を向上できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

1回答

1評価

2クリップ

1641閲覧

投稿2021/05/18 00:53

編集2021/05/19 04:31

Python3 Tkinter カメラの映像からバーコードやQRコードを読み取りたい
にて作成したソースコードをラズパイで動かしたときに動作が重くなりました。

Windowsで確認した際はラグはなかったのですが、ラズパイで確認するとtkinterのcanvasの映像が体感的に3秒ほど遅れています。
after()の中にprint()にてタイムスタンプ表示を行うと、指定[ms]に対して少し誤差はあるものの、映像表示ほどの遅れはありません。
指定時間[ms]は10[ms]、100[ms]、1000[ms]で試験しましたが、どれも同じくらい遅いです。

canvasの描画内容をコメントアウトしてバーコードの読み取りのみに変更しても、読み取るのに要する時間(バーコードをカメラの前にもっていってから、tkinterのラベルに表示するまでの時間)が2~3秒と長いような気がします。(単にピントが合っておらず、時間がかかっているときもありますが)

画像一枚に対してのバーコード読み取りや描画処理がラズパイには負担が大きく、処理としてついていけないのでしょうか?

ソースコード

Windowsで試験した際はエラー回避のためcv2.VideoCaputure()の第2引数にcv2.CAP_DSHOWを入れてましたが、
ラズパイでやったらエラーになったので、ここでは指定しません。

Python

from datetime import datetime from PIL import Image, ImageTk from pyzbar.pyzbar import decode import cv2 import queue import threading import time import tkinter as tk decode_cnt = 0 decode_span = 20 class App: def __init__(self, win): video_source = 0 self.vcap = cv2.VideoCapture(video_source) self.vcap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc("H", "2", "6", "4")) self.vcap.set(cv2.CAP_PROP_FRAME_WIDTH, 720) self.vcap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) #self.vcap.set(cv2.CAP_PROP_FPS, 30) self.fourcc = self.vcap.get(cv2.CAP_PROP_FOURCC) self.width = self.vcap.get(cv2.CAP_PROP_FRAME_WIDTH) self.height = self.vcap.get(cv2.CAP_PROP_FRAME_HEIGHT) #self.fps = self.vcap.get(cv2.CAP_PROP_FPS) print("width: {}".format(self.width)) print("height: {}".format(self.height)) self.font = cv2.FONT_HERSHEY_SIMPLEX self.label_header = "バーコード:" self.barcodeData = "" self.queue_to_subthread = queue.Queue() self.queue_to_mainthread = queue.Queue() self.win = win self.win.title("Camera") self.thread = threading.Thread(target=self.get_queue, args=(self.queue_to_mainthread,)) self.thread.start() size_str = str(int(self.width + 100)) + "x" + str(int(self.height + 100)) self.win.geometry(size_str) #self.disp_center(self.win, int(self.width) + 100, int(self.height) + 100) #self.disp_center(self.win, 720, 480) self.win.protocol("WM_DELETE_WINDOW", self.close) self.create_view() self.bind_event() #self.update_by_timer() self.canvas.after(15, self.update_by_timer) def disp_center(self, win, wx=400, wy=300): #win.resizable(0, 0) dx = win.winfo_screenwidth() dy = win.winfo_screenheight() win_size = str(wx) + "x" + str(wy) + \ "+" + str(int(dx/2 - wx/2)) + "+" + str(int(dy/2 - wy/2)) win.geometry(win_size) def close(self, e=None): self.queue_to_subthread.put(["close", None]) self.thread.join() self.win.destroy() self.vcap.release() #cv2.destroyAllWindows() def create_view(self): self.win.rowconfigure(0, weight=1) self.win.columnconfigure(0, weight=1) self.frame = tk.Frame(self.win, relief="sunken", bd=1) self.frame.grid(row=0, column=0, sticky="nsew") self.frame.rowconfigure(0, weight=1) self.frame.columnconfigure(0, weight=1) self.canvas = tk.Canvas(self.frame) self.canvas.grid(row=0, column=0, sticky="nsew", padx=10, pady=10) ret, frm = self.vcap.read() #print("ret: {}".format(ret)) #print("frm: {}".format(frm)) self.frame = cv2.cvtColor(frm, cv2.COLOR_BGR2RGB) self.photo = ImageTk.PhotoImage(image = Image.fromarray(self.frame)) self.canvas.update() cv_w = self.canvas.winfo_reqwidth() cv_h = self.canvas.winfo_reqheight() self.img_id = self.canvas.create_image(cv_w // 2, cv_h // 2, image=self.photo, anchor="center") """ self.canvas.update() cv_w = self.canvas.winfo_width() cv_h = self.canvas.winfo_height() rec_id = self.canvas.create_rectangle(0, 0, cv_w, cv_h, fill="black") # 長方形の座標取得 rec_pos = self.canvas.coords(rec_id) # テキストを描画(位置は適当) text_id = self.canvas.create_text(0, 0, text="NO SIGNAL", font=("", 20), fill="white") # テキストのサイズ取得 text_size = self.canvas.bbox(text_id) # テキストの座標移動 rc_x = rec_pos[2] / 2 rc_y = rec_pos[2] / 3 tc_y = text_size[3] / 2 self.canvas.move(text_id, rc_x - (rec_pos[0] / 2), rc_y - tc_y) """ self.label = tk.Label(self.win) self.label["text"] = self.label_header self.label.grid(row=1, column=0, sticky="", pady=10) self.button = tk.Button(self.win, text="Snapshot", command=self.pushed_button) self.button.grid(row=2, column=0, sticky="", pady=10) def pushed_button(self): self.queue_to_subthread.put(["snapshot", None]) def update_by_timer(self): global decode_cnt, decode_span ret, self.frame = self.vcap.read() #print("ret: {}".format(ret)) #print("self.frame: {}".format(self.frame)) # cv2はBGR、pillow(PIL)はRGB。色の構成順が異なる self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB) # フルカラー(色の構成順をRGBへ) #self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY) # グレースケール # 2値化(単純な閾値処理) # https://axa.biopapyrus.jp/ia/opencv/threshold.html #_, self.frame = cv2.threshold(self.frame, 120, 255, cv2.THRESH_BINARY) # 2値化 # 2値化(適応的閾値処理) # https://webcache.googleusercontent.com/search?q=cache:d8CkW7wbZ5AJ:https://algorithm.joho.info/programming/python/opencv-adaptive-thresholding-py/+&cd=2&hl=ja&ct=clnk&gl=jp #self.frame = cv2.adaptiveThreshold(self.frame, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 3) if ret and decode_cnt % decode_span == 0: self.queue_to_subthread.put(["decode", self.frame]) try: msg, d = self.queue_to_mainthread.get_nowait() #print("data: \n{}".format(d)) print(d) x,y,w,h = (0,0,0,0) if d: for barcode in d: x,y,w,h = barcode.rect self.barcodeData = barcode.data.decode("utf-8") else: self.barcodeData = "" self.label["text"] = self.label_header + self.barcodeData cv2.rectangle(self.frame,(x,y),(x+w,y+h),(0,0,255),2) frame = cv2.putText(self.frame,self.barcodeData,(x,y-10),self.font,.5,(0,0,255),2,cv2.LINE_AA) except queue.Empty: pass self.photo = ImageTk.PhotoImage(image = Image.fromarray(self.frame)) self.canvas.itemconfig(self.img_id, image=self.photo) decode_cnt += 1 self.canvas.after(15, self.update_by_timer) def update_by_resize(self, e): self.canvas.itemconfig(self.img_id, image=self.photo, anchor="center") cv_w = self.canvas.winfo_width() cv_h = self.canvas.winfo_height() self.canvas.coords(self.img_id, cv_w // 2, cv_h // 2) #pass def bind_event(self): self.win.bind("<Escape>", self.close) self.canvas.bind("<Configure>", self.update_by_resize) def get_queue(self, queue_to_mainthread): while True: msg, data = self.queue_to_subthread.get() if msg == "decode": d = decode(data) if d: queue_to_mainthread.put(["result", d]) else: queue_to_mainthread.put(["result", None]) elif msg == "snapshot": self.snapshot() elif msg == "close": break else: print("----- Undefined msg -----") break def snapshot(self): filename = "/home/pi/デスクトップ/img/frame-" + datetime.now().strftime("%Y-%m-%d-%H-%M-%S_%f") + ".jpg" cv2.imwrite(filename, cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)) print(filename) def main(): win = tk.Tk() App(win) win.mainloop() if __name__ == "__main__": main()

ラズパイのバージョン

$ lsb_release -a No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 9.13 (stretch) Release: 9.13 Codename: stretch

パッケージインストール方法等

$ sudo pip3 install opencv-python $ sudo pip3 install pyzbar $ sudo pip3 list opencv-python==4.4.0.42 pyzbar==0.1.8 (他省略)

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Raspbian

Raspbianは、DebianベースのRaspberry Pi用ディストリビューション。ハードウェア浮動小数点演算を有効にすることが可能で、Webブラウズなどの速度を向上できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。