Kivy按钮调用外部模块报错:NameError: name 'Aruco' is not defined
Kivy按钮调用外部模块方法报错:NameError: name 'Aruco' is not defined
我在单个文件中编写了Kivy代码,尝试将其中一个按钮与外部Python模块(Aruco.py)关联,希望点击按钮时运行该模块的detect()方法。已在main.py中导入Aruco模块,但点击按钮时触发错误:NameError: name 'Aruco' is not defined。
相关代码
main.py
import kivy from kivy.app import App from kivy.uix.widget import Widget from kivy.properties import ObjectProperty from kivy.uix.screenmanager import ScreenManager, Screen from kivy.lang.builder import Builder import sqlite3 import Aruco class MainWindow(Screen): pass class InfoWindow(Screen): pass class LocaliseWindow(Screen): pass class WindowManager(ScreenManager): pass kv = Builder.load_string(""" WindowManager: MainWindow: LocaliseWindow: InfoWindow <MainWindow>: name: "main" GridLayout: padding: 50 spacing: 20 cols:1 size: root.width, root.height Camera: id: camera play: True GridLayout: cols:2 spacing: 20 Button: text: "Localise" on_release: app.root.current = "localise" root.manager.transition.direction = "left" background_normal: "" background_color: "#05b4ff" Button: text: "Info" on_press: app.root.current = "info" root.manager.transition.direction = "left" background_normal: "" background_color: "#05b4ff" <LocaliseWIndow>: name: "localise" BoxLayout: padding: 50 spacing: 10 orientation: "vertical" Label: id: choose_destination font_size: 24 text: "Choose Destination" Button: id:Maths text: "Maths" on_press: Aruco.detect() background_normal: "" background_color: "#05b4ff" Button: id: English text: "English" on_press: app.submit() background_normal: "" background_color: "#05b4ff" Button: id: Science text: "Science" on_press: app.submit() background_normal: "" background_color: "#05b4ff" Button: id: Humanities text: "Humanities" on_press: app.submit() background_normal: "" background_color: "#05b4ff" Button: id: Office text: "Office" on_press: app.submit() background_normal: "" background_color: "#05b4ff" Button: id: Restroom text: "Restroom" on_press: app.submit() background_normal: "" background_color: "#05b4ff" Button: text: "Back" on_release: app.root.current = "main" root.manager.transition.direction = "right" <InfoWindow>: name:"info" BoxLayout: padding: 50 spacing: 10 orientation: "vertical" Label: text: "1. Press Localise" Label: text: "2. Choose Destination" Label: text: "3. Scan nearest Aruco Marker when prompted" Label: text: "4. Follow the path to destination" Button: text: "Back" on_release: app.root.current = "main" root.manager.transition.direction = "right" """) class MyApp(App): def build(self): conn = sqlite3.connect("database.db") c = conn.cursor() c.execute("""CREATE TABLE if not exists locations( place text, xcoor int, ycoor int) """) conn.commit() conn.close() return kv def submit(self): conn = sqlite3.connect("database.db") c = conn.cursor() c.execute("SELECT * FROM locations") print(c.fetchall()) conn.commit() conn.close() if __name__ == "__main__": MyApp().run()
Aruco.py
import numpy as np import time import cv2 def detect(): ARUCO_DICT = { "DICT_4X4_50": cv2.aruco.DICT_4X4_50, "DICT_4X4_100": cv2.aruco.DICT_4X4_100, "DICT_4X4_250": cv2.aruco.DICT_4X4_250, "DICT_4X4_1000": cv2.aruco.DICT_4X4_1000, "DICT_5X5_50": cv2.aruco.DICT_5X5_50, "DICT_5X5_100": cv2.aruco.DICT_5X5_100, "DICT_5X5_250": cv2.aruco.DICT_5X5_250, "DICT_5X5_1000": cv2.aruco.DICT_5X5_1000, "DICT_6X6_50": cv2.aruco.DICT_6X6_50, "DICT_6X6_100": cv2.aruco.DICT_6X6_100, "DICT_6X6_250": cv2.aruco.DICT_6X6_250, "DICT_6X6_1000": cv2.aruco.DICT_6X6_1000, "DICT_7X7_50": cv2.aruco.DICT_7X7_50, "DICT_7X7_100": cv2.aruco.DICT_7X7_100, "DICT_7X7_250": cv2.aruco.DICT_7X7_250, "DICT_7X7_1000": cv2.aruco.DICT_7X7_1000, "DICT_ARUCO_ORIGINAL": cv2.aruco.DICT_ARUCO_ORIGINAL, "DICT_APRILTAG_16h5": cv2.aruco.DICT_APRILTAG_16h5, "DICT_APRILTAG_25h9": cv2.aruco.DICT_APRILTAG_25h9, "DICT_APRILTAG_36h10": cv2.aruco.DICT_APRILTAG_36h10, "DICT_APRILTAG_36h11": cv2.aruco.DICT_APRILTAG_36h11 } def aruco_display(corners, ids, rejected, image): if len(corners) > 0: ids = ids.flatten() for (markerCorner, markerID) in zip(corners, ids): corners = markerCorner.reshape((4, 2)) (topLeft, topRight, bottomRight, bottomLeft) = corners topRight = (int(topRight[0]), int(topRight[1])) bottomRight = (int(bottomRight[0]), int(bottomRight[1])) bottomLeft = (int(bottomLeft[0]), int(bottomLeft[1])) topLeft = (int(topLeft[0]), int(topLeft[1])) cv2.line(image, topLeft, topRight, (0, 255, 0), 2) cv2.line(image, topRight, bottomRight, (0, 255, 0), 2) cv2.line(image, bottomRight, bottomLeft, (0, 255, 0), 2) cv2.line(image, bottomLeft, topLeft, (0, 255, 0), 2) cX = int((topLeft[0] + bottomRight[0]) / 2.0) cY = int((topLeft[1] + bottomRight[1]) / 2.0) cv2.circle(image, (cX, cY), 4, (0, 0, 255), -1) cv2.putText(image, str(markerID),(topLeft[0], topLeft[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) print("ArUco marker ID: {}".format(markerID)) return markerID return image aruco_type = "DICT_5X5_100" arucoDict = cv2.aruco.Dictionary_get(ARUCO_DICT[aruco_type]) arucoParams = cv2.aruco.DetectorParameters_create() capture = cv2.VideoCapture(0) capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) while capture.isOpened(): ret, img = capture.read() h, w, _ = img.shape width = 1000 height = int(width*(h/w)) img = cv2.resize(img, (width, height), interpolation=cv2.INTER_CUBIC) corners, ids, rejected = cv2.aruco.detectMarkers(img, arucoDict, parameters=arucoParams) detected_markers = aruco_display(corners, ids, rejected, img) cv2.imshow("Image", detected_markers) key = cv2.waitKey(1) & 0xFF if key == ord(" "): break cv2.destroyAllWindows() capture.release() return markerID
解决方案
1. 修复KV语言的作用域问题
KV语言无法直接访问全局导入的模块,不能直接在按钮on_press事件中写Aruco.detect(),需要通过App实例或屏幕类间接调用:
方法一:通过App类封装调用
修改MyApp类,添加调用Aruco模块的方法:
class MyApp(App): # ... 原有代码 ... def run_aruco_detect(self): Aruco.detect()
修改KV中Maths按钮的事件:
Button: id:Maths text: "Maths" on_press: app.run_aruco_detect() background_normal: "" background_color: "#05b4ff"
方法二:通过LocaliseWindow类封装调用
修改LocaliseWindow类,添加调用方法:
class LocaliseWindow(Screen): def detect_aruco(self): Aruco.detect()
修改KV中按钮事件:
Button: id:Maths text: "Maths" on_press: root.detect_aruco() background_normal: "" background_color: "#05b4ff"
2. 修复KV中的拼写错误
KV中定义的屏幕为<LocaliseWIndow>,但Python类名是LocaliseWindow(字母i和l顺序错误),会导致屏幕无法加载,修正为:
<LocaliseWindow>: name: "localise" # ... 原有内容 ...
3. 修复Aruco.py的变量作用域问题
detect()函数末尾return markerID会报错,因为markerID是aruco_display内部的局部变量,仅在检测到标记时定义。修改如下:
调整aruco_display函数返回值
def aruco_display(corners, ids, rejected, image): markerID = None if len(corners) > 0: ids = ids.flatten() for (markerCorner, markerID) in zip(corners, ids): # ... 原有绘制标记的代码 ... cv2.putText(image, str(markerID),(topLeft[0], topLeft[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) print("ArUco marker ID: {}".format(markerID)) return image, markerID
修改detect函数接收返回值
def detect(): # ... 原有代码 ... markerID = None while capture.isOpened(): # ... 原有代码 ... detected_markers, markerID = aruco_display(corners, ids, rejected, img) cv2.imshow("Image", detected_markers) # ... 原有代码 ... cv2.destroyAllWindows() capture.release() return markerID
这样可以避免cv2.imshow接收非图像类型参数导致的报错。
内容的提问来源于stack exchange,提问作者Nigel Mathews
相关产品推荐
相关产品推荐

