我想使用OpenCV和Kivy创建一个APK,具有拍照并对图像应用Canny边缘检测算法的功能。代码如下:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.uix.image import Image
from kivy.properties import StringProperty
from kivy.utils import platform
from android.permissions import request_permissions, Permission
from android.storage import app_storage_path
import time
import cv2
request_permissions([
Permission.CAMERA,
Permission.WRITE_EXTERNAL_STORAGE,
Permission.READ_EXTERNAL_STORAGE
])
Builder.load_string('''
<CameraClick>:
orientation: 'vertical'
Camera:
index: 0
id: camera
resolution: (1920,1080)
play: True
allow_stretch: True
canvas.before:
PushMatrix
Rotate:
angle: -90
origin: self.center
canvas.after:
PopMatrix
Button:
text: 'Capture'
size_hint_y: None
height: '48dp'
on_press: root.capture()
<DisplayImagePopup>:
image_source: ''
BoxLayout:
orientation: 'vertical'
Image:
source: root.image_source
Button:
text: 'Process Image'
size_hint_y: None
height: 50
on_press: root.process_image()
''')
class CameraClick(BoxLayout):
def capture(self):
camera = self.ids['camera']
storage_path = app_storage_path() # Get the safe storage path for the app
timestr = time.strftime("%Y%m%d_%H%M%S")
filename = "{}/IMG_{}.png".format(storage_path, timestr)
camera.export_to_png(filename)
self.show_image(filename)
def show_image(self, filename):
popup = DisplayImagePopup(title='Captured Image', image_source=filename)
popup.open()
class DisplayImagePopup(Popup):
image_source = StringProperty('')
def process_image(self):
image = cv2.imread(self.image_source)
imgGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
imgBlur = cv2.bilateralFilter(imgGray, 10, 10, 10)
imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1)
adaptive_thresh = cv2.adaptiveThreshold(imgBlur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 15, 3)
imgCanny = cv2.Canny(adaptive_thresh, 100, 150)
processed_filename = self.image_source.replace('.png', '_processed.png')
cv2.imwrite(processed_filename, imgCanny)
self.image_source = processed_filename # Update the image displayed in the popup
class TestCamera(App):
def build(self):
return CameraClick()
if __name__ == '__main__':
TestCamera().run()
代码本身看起来没问题,但是修改它来实现Canny边缘检测后,当点击图像时,图像上会出现一个红点。代码如下:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.uix.image import Image
from kivy.graphics import Color, Ellipse
from kivy.properties import StringProperty, ListProperty
import cv2
from android.permissions import request_permissions, Permission
from android.storage import app_storage_path
import time
request_permissions([
Permission.CAMERA,
Permission.WRITE_EXTERNAL_STORAGE,
Permission.READ_EXTERNAL_STORAGE
])
Builder.load_string('''
<CameraClick>:
orientation: 'vertical'
Camera:
index: 0
id: camera
resolution: (1920,1080)
play: True
allow_stretch: True
canvas.before:
PushMatrix
Rotate:
angle: -90
origin: self.center
canvas.after:
PopMatrix
Button:
text: 'Capture'
size_hint_y: None
height: '48dp'
on_press: root.capture()
<DisplayImagePopup>:
image_source: ''
BoxLayout:
orientation: 'vertical'
InteractiveImage:
source: root.image_source
on_touch_down: root.on_image_touch(*args)
Button:
text: 'Process Image'
size_hint_y: None
height: 50
on_press: root.process_image()
''')
class CameraClick(BoxLayout):
def capture(self):
camera = self.ids['camera']
storage_path = app_storage_path()
timestr = time.strftime("%Y%m%d_%H%M%S")
filename = "{}/IMG_{}.png".format(storage_path, timestr)
camera.export_to_png(filename)
self.show_image(filename)
def show_image(self, filename):
popup = DisplayImagePopup(title='Captured Image', image_source=filename)
popup.open()
class InteractiveImage(Image):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
with self.canvas:
Color(1, 0, 0)
d = 10 # diameter of the ellipse
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
return True
return super(InteractiveImage, self).on_touch_down(touch)
class DisplayImagePopup(Popup):
image_source = StringProperty('')
def process_image(self):
image = cv2.imread(self.image_source)
imgGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
imgBlur = cv2.bilateralFilter(imgGray, 10, 10, 10)
imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1)
adaptive_thresh = cv2.adaptiveThreshold(imgBlur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 15, 3)
imgCanny = cv2.Canny(adaptive_thresh, 100, 150)
processed_filename = self.image_source.replace('.png', '_processed.png')
cv2.imwrite(processed_filename, imgCanny)
self.image_source = processed_filename # Update the image displayed in the popup
class TestCamera(App):
def build(self):
return CameraClick()
if __name__ == '__main__':
TestCamera().run()
此时,出现以下错误,即使恢复到原始代码,同样的错误仍然存在。为了使原始代码正常运行,有必要使用“buildozer android clean”进行重建。
HWCDY:/ $ run-as org.test.myapt
HWCDY:/data/data/org.test.myapt $ cd files/app/.kivy/logs/
HWCDY:/data/data/org.test.myapt/files/app/.kivy/logs $ ls
kivy_24-04-22_0.txt
HWCDY:/data/data/org.test.myapt/files/app/.kivy/logs $ cat kivy_24-04-22_0.txt
[INFO ] Logger: Record log in /data/user/0/org.test.myapt/files/app/.kivy/logs/kivy_24-04-22_0.txt
[DEBUG ] Config: Upgrading from 0 to 1
[WARNING] Config: Upgrading configuration in progress.
[WARNING] Config: Older configuration version detected (0 instead of 27)
[INFO ] Kivy: v2.2.0
[INFO ] Kivy: Installed at "/data/user/0/org.test.myapt/files/app/_python_bundle/site-packages/kivy/__init__.pyc"
[INFO ] Python: v3.10.10 (main, Apr 21 2024, 22:32:18) [Clang 14.0.6 (https://android.googlesource.com/toolchain/llvm-project 4c603efb0
[INFO ] Python: Interpreter at ""
[INFO ] Logger: Purge log fired. Processing...
[INFO ] Logger: Purge finished!
[INFO ] Factory: 190 symbols loaded
[INFO ] Image: Providers: img_tex, img_dds, img_sdl2 (img_pil, img_ffpyplayer ignored)
[INFO ] Text: Provider: sdl2
[WARNING] stderr: Traceback (most recent call last):
[WARNING] stderr: File "/home/wuqx1999/packing/.buildozer/android/app/main.py", line 8, in <module>
[WARNING] stderr: ModuleNotFoundError: No module named 'cv2'
这是为什么呢,非常感谢
我不明白为什么。我希望代码的第二个副本也能工作。 我在 GitHub 上发现有人有同样的问题,但不幸的是,也没有答案。https://github.com/liyuanrui/kivy-for-android-opencv-demo/issues/4
安装 opencv 和 opencv-python 和 opencv-contrib