記事ディレクトリ
1.wxpythonの概要
wxpython は、Python でフロントエンド インターフェイスを作成するための比較的シンプルなツールです。ボタン、スライダー、テキスト ブロック、その他の実用的なコンポーネントを含む基本的なインターフェイスを生成するためによく使用され、非常に使いやすいフロントエンド ツールです。
1.本文
2. テキストボックス(ステータスバー)
wx.Textctrl()
3. ボタン
wx.Button()
4. スライドボタン
2. Mediapipe と wxpython の効果的な組み合わせ
1. 運用効果
コードを実行した後の効果は次のとおりです。左側は画像の表示に使用される画像ボックス、
右側はファイルを開いて検出プロセスを実行するために使用されるステータス バーです。
ファイルを開くと、以下に示すように画像ボックスに画像が表示されます。
「キーポイントを検出」をクリックすると、人体のキーポイントを検出できます。
2. コードの説明
次に、コードの実装方法について詳しく説明します。
(1) キーポイント検出機能
前回のメディアパイプの説明では、キーポイント検出と検出動作認識の機能を実装しました。次に、それを、wxpython フロントエンド インターフェイスでのキーストローク呼び出し専用の関数にカプセル化できます。
ここでカプセル化される関数は次のとおりです。
def pre_image(image_path):
print(image_path)
#image = cv2.imread(image_path)
image = cv2.imdecode(np.fromfile(image_path, dtype=np.uint8), -1)
img = image.copy()
frame = process_frame(img)
return frame
# 先不显示
cv2.imdecode()
中国語のパスを含む画像をcv2.imread()
開くことができないため、を使用します。
process_frame()
この関数の機能は、元の画像を入力し、検出されたキーポイント画像を出力することです。この関数の概要は
次のとおりです。process_frame()
def process_frame(img):
start_time = time.time()
h, w = img.shape[0], img.shape[1] # 高和宽
# 调整字体
tl = round(0.005 * (img.shape[0] + img.shape[1]) / 2) + 1
tf = max(tl-1, 1)
# BRG-->RGB
img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 将RGB图像输入模型,获取 关键点 预测结果
results = pose.process(img_RGB)
keypoints = ['' for i in range(33)]
if results.pose_landmarks:
mp_drawing.draw_landmarks(img, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
for i in range(33):
cx = int(results.pose_landmarks.landmark[i].x * w)
cy = int(results.pose_landmarks.landmark[i].y * h)
keypoints[i] = (cx, cy) # 得到最终的33个关键点
else:
print("NO PERSON")
struction = "NO PERSON"
img = cv2.putText(img, struction, (25, 100), cv2.FONT_HERSHEY_SIMPLEX, 1.25, (255, 255, 0),
6)
end_time = time.time()
process_time = end_time - start_time # 图片关键点预测时间
fps = 1 / process_time # 帧率
colors = [[random.randint(0,255) for _ in range(3)] for _ in range(33)]
radius = [random.randint(8,15) for _ in range(33)]
for i in range(33):
cx, cy = keypoints[i]
#if i in range(33):
img = cv2.circle(img, (cx, cy), radius[i], colors[i], -1)
'''str_pose = get_pos(keypoints) #获取姿态
cv2.putText(img, "POSE-{}".format(str_pose), (12, 100), cv2.FONT_HERSHEY_TRIPLEX,
tl / 3, (255, 0, 0), thickness=tf)'''
cv2.putText(img, "FPS-{}".format(str(int(fps))), (12, 100), cv2.FONT_HERSHEY_SIMPLEX,
tl/3, (255, 255, 0),thickness=tf)
return img
この関数は実際に前の説明で登場しました。
これら 2 つの関数を使用すると、キーにバインドしてコールバックの使用を実装できます。
(2) wxpythonの具体的な操作
主要なフレームワーク部分は実際には wxpython にあり、実現したいすべての機能を接続します。
ここでは、特にフロントエンド コード呼び出しを行うために使用されるクラスを定義します。
注釈付きの wxpython コードは次のとおりです。
class mediapipeApp(wx.App):
def __init__(self):
'''UI界面的设计'''
wx.App.__init__(self)
self.frame = wx.Frame(None, title="Mediapipe_UI")
self.panel = wx.Panel(self.frame)
# -------------------------
# 新建控件位置变量
# -------------------------
VERTICAL = wx.BoxSizer(wx.VERTICAL)
HORIZONTAL = wx.BoxSizer(wx.HORIZONTAL)
# ------------------------------------
# 新建控件
# ------------------------------------
# 图片框
image = wx.EmptyImage(500,500)
self.image = wx.StaticBitmap(self.panel, wx.ID_ANY, # 设置图片控件
wx.BitmapFromImage(image))
self.opare = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "操作栏"),
wx.VERTICAL)
# 图片操作栏
self.image_op = wx.StaticBoxSizer(wx.StaticBox(self.opare.GetStaticBox(), wx.ID_ANY, "图片操作栏"),
wx.VERTICAL)
grider = wx.GridSizer(0, 2, 0, 9)
btn_open = wx.Button(self.image_op.GetStaticBox(), label="打开文件")
btn_points = wx.Button(self.image_op.GetStaticBox(), label="检测关键点")
btn_pose = wx.Button(self.image_op.GetStaticBox(), label="检测姿态")
# 状态栏,文本输入框
self.sympol = wx.StaticBoxSizer(wx.StaticBox(self.opare.GetStaticBox(), wx.ID_ANY, "状态栏"),
wx.HORIZONTAL)
self.text_ctrl = wx.TextCtrl(self.sympol.GetStaticBox(), size=(200,300))
# -----------------------------------
# 设置控件 : 按钮、文本输入框等
# -----------------------------------
btn_open.Bind(wx.EVT_BUTTON, self.openfile)
btn_points.Bind(wx.EVT_BUTTON, self.points)
# ------------------------------------
# 控件分布
# ------------------------------------
grider.Add(btn_open, 0, wx.ALL|wx.EXPAND, 5)
grider.Add(btn_points, 0, wx.ALL|wx.EXPAND, 5)
grider.Add(btn_pose, 0, wx.ALL|wx.EXPAND, 5)
self.opare.Add(self.image_op, 0, wx.ALL|wx.EXPAND, 5)
self.opare.Add(self.sympol, 0, wx.ALL|wx.EXPAND, 5)
self.image_op.Add(grider, 0, wx.ALL|wx.EXPAND, 5)
self.sympol.Add(self.text_ctrl, 0, wx.ALL|wx.EXPAND, 5)
HORIZONTAL.Add(self.image, 0, wx.ALL|wx.EXPAND, 5)
HORIZONTAL.Add(self.opare, 0, wx.ALL|wx.EXPAND, 5)
VERTICAL.Add(HORIZONTAL)
# ------------------------------------
# 最终设置
# ------------------------------------
self.panel.SetSizer(VERTICAL)
self.panel.Layout()
HORIZONTAL.Fit(self.frame)
self.frame.Show()
self.PhotoMaxSize = 500
self.filepath = ""
def points(self, event):
'''检测关键点函数'''
# 如果路径是空的,那么就在状态栏中报错
if self.filepath == "":
struction = "错误,请先导入原始图片"
self.text_ctrl.SetValue(struction)
self.text_ctrl.GetValue()
# 如果路径不为空,则执行检测操作,并把检测过后的图片显示在图片框中
else:
# 返回的image是cv2格式
image = pre_image(self.filepath)
image = cv2.resize(image, (500,500))
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
pic = wx.Bitmap.FromBuffer(image.shape[1], image.shape[0], image)
self.image.SetBitmap(pic)
self.panel.Refresh()
def openfile(self, event):
'''打开文件函数:点击打开文件后,可以打开以jpg格式的图片'''
wildcard = "JPEG files (*.jpg)|*.jpg"
dialog = wx.FileDialog(None, "choose a file",
wildcard=wildcard,
style=wx.FD_CHANGE_DIR)
if dialog.ShowModal() == wx.ID_OK:
self.text_ctrl.SetValue(dialog.GetPath())
dialog.Destroy()
self.onView()
def onView(self):
'''在状态栏中显示所需内容'''
self.filepath = self.text_ctrl.GetValue()
self.showImage(self.filepath)
def showImage(self, filepath):
'''调整图片的宽高,并在图片框中显示图片'''
img = wx.Image(filepath, wx.BITMAP_TYPE_ANY)
W = img.GetWidth()
H = img.GetHeight()
# 让显示的美观一点。
if W > H:
NewW = self.PhotoMaxSize
NewH = self.PhotoMaxSize * H / W
else:
NewH = self.PhotoMaxSize
NewW = self.PhotoMaxSize * H / W
self.W = NewW
self.H = NewH
img = img.Scale(NewW, NewH)
self.image.SetBitmap(wx.BitmapFromImage(img))
self.panel.Refresh()
コード全体の中で最も複雑な部分は、コントロールの配布設定である可能性があり、これは注意深く理解する必要があります。
要約する
wxpython
wxpython+メディアパイプ
全体的なコードは、wxpython の追加のビジュアル UI インターフェイスがあることを除いて、前述の Mediapipe と同じです。また、wxpython コードを前述の Mediapipe の章に配置しましたので、自分で読むことができます。