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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Visual Studio Code

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Tkinter

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1498閲覧

Pythonで特定のウィンドウをキャプチャする

Kasairyu

総合スコア12

Visual Studio Code

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Tkinter

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/10/31 04:50

前提

Pythonで特定のウィンドウをキャプチャして画像処理を施したものをtkinterのウィンドウに表示するアプリケーションを製作しています。

実現したいこと

  • 指定したウィンドウのキャプチャ
  • キャプチャした画像の処理
  • 画像をtkinterで表示

発生している問題

・ImageGrab.grab()で取得した画像に処理を加えてcv2.imshow()で表示する事はできたがディスプレイ全体のスクリーンショットしか出来ない所為で合わせ鏡の様に延々と暗くなってしまう。理想としてはchromeやZoomなど実行中のアプリケーションを指定してそのウィンドウだけをキャプチャしたい。最前面に出す必要が無ければなおよし。

・処理もWhile文で回しているだけなので使い勝手が悪い。

・生成したウィンドウサイズも変えられない。

基本のソースコード

Python

1from PIL import ImageGrab 2import numpy as np 3import cv2 4 5print("--- Running Now ---") 6 7while True: 8 # スクリーンキャプチャ 9 img = ImageGrab.grab() 10 11 # PILのimageをndarrayに変換 12 cv_img = np.array(img, dtype=np.uint8) 13 14 # 色変換 15 cv_img = cv2.cvtColor(cv_img, cv2.COLOR_RGB2BGR) 16 17 hsv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2HSV) 18 s_magnification = 4 # 彩度(Saturation)の倍率 19 v_magnification = 0.4 # 明度(Value)の倍率 20 hsv_img[:,:,(1)] = hsv_img[:,:,(1)]*s_magnification # 彩度の計算 21 hsv_img[:,:,(2)] = hsv_img[:,:,(2)]*v_magnification # 明度の計算 22 img_bgr = cv2.cvtColor(hsv_img,cv2.COLOR_HSV2BGR) # 色空間をHSVからBGRに変換 23 24 # 画面表示 25 cv2.imshow('figure',img_bgr) 26 cv2.waitKey(1)

試したこと

このサイトを参考にWhile文に頼らず実行したい時間だけキャプチャし続ける様にしたかったが、カメラ情報を無理やりキャプチャ画像に入れ替えただけな所為で失敗。表示ウィンドウのサイズに関してはこれが実現できれば達成。
指定したウィンドウのキャプチャは未だに良い方法が浮かばず。

Python

1import tkinter as tk 2from tkinter import filedialog 3from PIL import Image, ImageTk, ImageOps # 画像データ用 4from PIL import ImageGrab 5import numpy as np 6 7import cv2 8 9class Application(tk.Frame): 10 def __init__(self, master = None): 11 super().__init__(master) 12 self.pack() 13 14 self.master.title("OpenCVの動画表示") # ウィンドウタイトル 15 self.master.geometry("400x300") # ウィンドウサイズ(幅x高さ) 16 17 # Canvasの作成 18 self.canvas = tk.Canvas(self.master) 19 # Canvasにマウスイベント(左ボタンクリック)の追加 20 self.canvas.bind('<Button-1>', self.canvas_click) 21 # Canvasを配置 22 self.canvas.pack(expand = True, fill = tk.BOTH) 23 24 # カメラをオープンする 25 img = ImageGrab.grab() 26 self.capture = np.array(img, dtype=np.uint8) 27 28 self.disp_id = None 29 30 def canvas_click(self, event): 31 '''Canvasのマウスクリックイベント''' 32 33 if self.disp_id is None: 34 # 動画を表示 35 self.disp_image() 36 else: 37 # 動画を停止 38 self.after_cancel(self.disp_id) 39 self.disp_id = None 40 41 def disp_image(self): 42 '''画像をCanvasに表示する''' 43 44 # フレーム画像の取得 45 ret, frame = self.capture 46 47 # BGR→RGB変換 48 cv_img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) 49 50 hsv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2HSV) 51 s_magnification = 4 # 彩度(Saturation)の倍率 52 v_magnification = 0.4 # 明度(Value)の倍率 53 hsv_img[:,:,(1)] = hsv_img[:,:,(1)]*s_magnification # 彩度の計算 54 hsv_img[:,:,(2)] = hsv_img[:,:,(2)]*v_magnification # 明度の計算 55 img_bgr = cv2.cvtColor(hsv_img,cv2.COLOR_HSV2BGR) # 色空間をHSVからBGRに変換 56 57 # NumPyのndarrayからPillowのImageへ変換 58 pil_image = Image.fromarray(img_bgr) 59 60 # キャンバスのサイズを取得 61 canvas_width = self.canvas.winfo_width() 62 canvas_height = self.canvas.winfo_height() 63 64 # 画像のアスペクト比(縦横比)を崩さずに指定したサイズ(キャンバスのサイズ)全体に画像をリサイズする 65 pil_image = ImageOps.pad(pil_image, (canvas_width, canvas_height)) 66 67 # PIL.ImageからPhotoImageへ変換する 68 self.photo_image = ImageTk.PhotoImage(image=pil_image) 69 70 # 画像の描画 71 self.canvas.create_image( 72 canvas_width / 2, # 画像表示位置(Canvasの中心) 73 canvas_height / 2, 74 image=self.photo_image # 表示画像データ 75 ) 76 77 # disp_image()を10msec後に実行する 78 self.disp_id = self.after(10, self.disp_image) 79 80if __name__ == "__main__": 81 root = tk.Tk() 82 app = Application(master = root) 83 app.mainloop()

ValueError: too many values to unpack (expected 2)

補足情報(FW/ツールのバージョンなど)

開発にはVScodeを使用しています。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kasairyu

2022/10/31 06:14

指定したウィンドウのキャプチャは兎も角While文を使わずtkinterに写す方法だけでも解決できる方が居たらご教授ください。
guest

回答1

0

ベストアンサー

上のコードでリサイズ可能。バックエンドにもよるみたいですが、オプションが有ります

python

1cv2.namedWindow("figure", cv2.WINDOW_NORMAL) 2

tkinter のコードのエラー修正

diff

1- ret, frame = self.capture 2+ frame = self.capture

追加で注意点が幾つか

スクリーンのキャプチャーを所得してるコードは、__init__ 内で実行されている為
プログラム起動時に1度だけ実行されます。
リアルタイムに反映するにはタイマー内で所得するように変更します。

python

1# __init__ では最初に一度のみなので、disp_image へ移動 2 3 img = ImageGrab.grab() 4 self.capture = np.array(img, dtype=np.uint8)

毎回 create_image はメモリリークになるので、毎回 delete するか、
create_image の戻り値を控えておいて
itemconfigureメソッド で PhotoImage のみ差し替えるようにすると回避できます。

diff

1+ self.canvas.delete("all") 2self.canvas.create_image(...)

タイマー(GUIスレッド)内での 10ms 間隔でのキャプチャ+フィルタ処置は、
スペックによってはGUIのレスポンスが悪くなることがあります。
別スレッドでキャプチャ+画像処理を行い、
タイマー内ではPhotoImage生成とキャンバスの描画更新のみするようにすると改善できます。


ウィンドウのキャプチャ方法は、プラットフォームにより異なります。
方法によっては、背後のウィンドウは所得出来ない等、それぞれの方法に違いもあります。

投稿2022/10/31 07:36

teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kasairyu

2022/10/31 08:07

無事実装できました。改善案までご提示頂き本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問