Reconocimiento de gestos y reconocimiento de comportamiento simple basado en mediapipe - diseño de interfaz front-end

1. Introducción a wxpython

  wxpython es una herramienta relativamente simple para crear interfaces de usuario en Python. A menudo se utiliza para generar algunas interfaces básicas, que incluyen botones, controles deslizantes, bloques de texto y otros componentes prácticos. Es una herramienta de interfaz de usuario extremadamente fácil de usar.

1. Texto

2. Cuadro de texto (barra de estado)

wx.Textctrl()

3. Botones

wx.Button()

4. Botón deslizante

2. Combinación efectiva de Mediapipe y wxpython

1. Efecto de operación

  El efecto después de ejecutar el código es el siguiente: a la izquierda está el cuadro de imagen, que se usa para mostrar imágenes;
  a la derecha está la barra de estado, que se usa para abrir archivos y realizar el proceso de detección.
Insertar descripción de la imagen aquí
  Después de abrir el archivo, la imagen se mostrará en el cuadro de imagen, como se muestra a continuación:

Insertar descripción de la imagen aquí
  Después de hacer clic en "Detectar puntos clave", podrá detectar los puntos clave del cuerpo humano.
Insertar descripción de la imagen aquí

2. Explicación del código

  A continuación, hablemos en detalle sobre cómo se implementa el código.

(1) Función de detección de puntos clave

  En la explicación anterior de mediapipe, se implementaron las funciones de detección de puntos clave y reconocimiento de comportamiento de detección. Luego podemos encapsularlo en una función específica para llamadas de pulsación de teclas en la interfaz frontal de wxpython.
  Las funciones resumidas aquí son las siguientes:

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()se utiliza porque las imágenes que contienen rutas chinas no se pueden cv2.imread()abrir.
  process_frame()La función de la función es ingresar la imagen original y generar la imagen del punto clave detectado.
De esto process_frame()se trata la función:

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

  Esta función en realidad apareció en la explicación anterior.
  Con estas dos funciones, puede vincularlas a claves para implementar el uso de devolución de llamada.

(2) Operaciones específicas de wxpython

  La parte principal del marco está en realidad en wxpython, que conecta todas las funciones que desea lograr.

Aquí defino una clase utilizada específicamente para realizar llamadas de código de front-end.
Aquí está el código wxpython anotado:

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()

  La parte más complicada de todo el código puede ser la configuración de distribución de los controles, que debe comprenderse detenidamente.

Resumir

wxpython

wxpython+Mediapipe

El código general es el mismo que el Mediapipe mencionado anteriormente, excepto que hay una interfaz de usuario visual adicional de wxpython. También coloqué el código de wxpython en el capítulo de Mediapipe mencionado anteriormente, y puede leerlo usted mismo.

Supongo que te gusta

Origin blog.csdn.net/weixin_44463519/article/details/126240816
Recomendado
Clasificación