Kivy应用PC端运行正常但安卓端启动崩溃如何解决?
问题核心原因及修复方案
1 代码崩溃的直接诱因
- 硬编码了Windows系统的绝对路径,安卓设备不存在
C:\Users\这类路径结构,读取图像直接报错 - 直接调用
plt.show()尝试弹出matplotlib的GUI窗口,安卓Kivy运行环境不支持这类桌面端GUI接口,调用即崩溃 - matplotlib未指定非GUI后端,安卓环境下初始化matplotlib默认会调用不存在的GUI渲染依赖,直接崩溃
- 所有三方依赖导入写在
build方法内,一方面会拖慢应用启动速度,另一方面打包时容易出现依赖漏识别的问题
2 修复步骤
第一步:依赖导入与后端配置
将所有导入移到代码顶部,提前指定matplotlib用非GUI的Agg后端:
#-*- coding: utf-8 -*- import os import math import kivy import numpy as np import matplotlib matplotlib.use('Agg') # 必须加,禁用matplotlib的GUI后端 import matplotlib.image as mpimg from kivy.app import App from kivy.uix.label import Label from kivy.uix.boxlayout import BoxLayout from kivy.graphics.texture import Texture from kivy.uix.image import Image kivy.require('1.9.1')
第二步:修改图像路径为相对路径
把你要读取的图像和main.py放在同一目录,用脚本所在目录拼接图像路径:
# 替换原硬编码的img路径 script_dir = os.path.dirname(os.path.abspath(__file__)) img_path = os.path.join(script_dir, "CN 9_3 - cor.jpg") foto = mpimg.imread(img_path)
第三步:删除plt.imshow和plt.show()代码
如果需要在应用内显示处理后的图像,可将numpy数组转为Kivy纹理加载,示例逻辑:
# 处理完图像数组后转成Kivy纹理 buf = foto.tobytes() texture = Texture.create(size=(foto.shape[1], foto.shape[0])) texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte') img_widget = Image(texture=texture) # 最后把图像和文字标签放在BoxLayout里返回即可
第四步:优化像素处理逻辑(可选,大幅提升安卓端运行速度)
原双层循环可替换为numpy向量化操作,耗时能降低90%以上:
linhas, colunas = foto.shape[:2] y, x = np.ogrid[:linhas, :colunas] dist_from_center = (x - colunas//2)**2 + (y - linhas//2)**2 mask = dist_from_center <= (colunas//2)**2 dentro = foto[mask].tolist() # 非圆形区域灰度化 foto[~mask] = np.mean(foto[~mask], axis=1, keepdims=True) - 0.5
第五步:打包配置(如果用Buildozer打包APK)
在buildozer.spec中做以下修改:
requirements项添加python3,kivy==1.9.1,numpy,matplotlib,Pillowandroid.add_assets项添加你的图像文件:android.add_assets = CN 9_3 - cor.jpg
3 完整可运行参考代码
#-*- coding: utf-8 -*- import os import math import kivy import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.image as mpimg from kivy.app import App from kivy.uix.label import Label from kivy.uix.boxlayout import BoxLayout from kivy.graphics.texture import Texture from kivy.uix.image import Image kivy.require('1.9.1') class MeuApp(App): def build(self): # 读取图像 script_dir = os.path.dirname(os.path.abspath(__file__)) img_path = os.path.join(script_dir, "CN 9_3 - cor.jpg") foto = mpimg.imread(img_path) linhas, colunas = foto.shape[:2] # 向量化处理圆形区域 y, x = np.ogrid[:linhas, :colunas] dist_from_center = (x - colunas//2)**2 + (y - linhas//2)**2 mask = dist_from_center <= (colunas//2)**2 dentro = foto[mask] foto[~mask] = np.mean(foto[~mask], axis=1, keepdims=True) - 0.5 # 计算参数 raio = colunas // 2 area = np.pi * (raio ** 2) mean_dentro = np.mean(dentro) OD = math.log(255 / mean_dentro, 10) ODI = OD * area # 生成文字 a = "[b]Intensidade média de luz transmitida pela imagem:[/b] " + str(mean_dentro) + " \n" b = "\n [b]Área:[/b] " + str(area) + " μm \n" c = "\n [b]Densidade óptica:[/b] " + str(OD) + " \n" d = "\n [b]Densidade óptica integrada:[/b] " + str(ODI) + " \n" if ODI < 674353.78: e = "\n Essa amostra faz parte do grupo [b]POSITIVO[/b] para carcinoma \n" else: e = "\n Essa amostra faz parte do grupo [b]NEGATIVO[/b] para carcinoma \n" label = Label(text=a+b+c+d+e, markup=True, size_hint=(1, 0.4)) # 生成图像组件 buf = np.flipud(foto).tobytes() # 翻转y轴匹配Kivy纹理坐标系 texture = Texture.create(size=(colunas, linhas)) texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte') img_widget = Image(texture=texture, size_hint=(1, 0.6)) # 布局组合 layout = BoxLayout(orientation='vertical') layout.add_widget(img_widget) layout.add_widget(label) return layout if __name__ == '__main__': MeuApp().run()
内容的提问来源于stack exchange,提问作者user16752758
相关产品推荐
相关产品推荐

