如何使用 Kivy 放大或缩小实时摄像头?
How can I use Kivy to zoom in or zoom out live camera?
我搜索了一下,找到了“scatter”,但是scatter用于图像。
我想用实时相机放大它。
有人知道我该怎么做吗?
这是我写的代码示例,但它不起作用。
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import ScreenManager , Screen
from kivy.uix.image import Image
from kivy.core.window import Window
from kivy.base import runTouchApp
from kivymd.app import MDApp
from kivy.uix.boxlayout import BoxLayout
import time
from kivy.core.window import Window
from kivy.uix.camera import Camera
from kivy.uix.scatter import Scatter
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import NumericProperty
Window.size = (1600, 850)
class MyCamera(Camera):
region_x = NumericProperty(0)
region_y = NumericProperty(0)
region_w = NumericProperty(1600)
region_h = NumericProperty(850)
def on_text(self,camera):
self.texture = texture = camera.texture
self.texture = self.texture.get_region(self.region_x, self.region_y, self.region_w, self.region_h)
self.texture_size = list(texture.size)
self.canvas.ask_update()
class MainPage(Screen):
pass
class WindowManager(ScreenManager):
pass
class CameraClick(Screen):
scale = NumericProperty(1)
def on_touch_down(self, touch):
if touch.is_mouse_scrolling:
if touch.button == 'scrolldown':
print("down")
if self.scale <10:
self.scale *= 1.1
self.ids['camera'].region_w /= 1.1
self.ids['camera'].region_h /= 1.1
self.ids['camera'].region_x = (1600-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (850-self.ids['camera'].region_h) // 2
elif touch.button == 'scrollup':
print("up")
if self.scale >1:
self.scale *= 0.8
self.ids['camera'].region_w /= 0.8
self.ids['camera'].region_h /= 0.8
if(self.ids['camera'].region_w > 1600) or (self.ids['camera'].region_h >850):
self.ids['camera'].region_w = 1600
self.ids['camera'].region_h = 850
self.ids['camera'].region_x = (1600-self.ids['camera'].region_w) //2
self.ids['camera'].region_y = (850-self.ids['camera'].region_h) //2
def capture(self):
camera = self.ids['camera']
timestr = time.strftime("%Y%m%d_%H%M%S")
camera.export_to_png("IMG_{}.png".format(timestr))
print("Captured")
Builder.load_string("""
#:import utils kivy.utils
<WindowManager>:
MainPage:
CameraClick:
<MainPage>:
name: "main page"
BoxLayout:
cols:1
orientation: "horizontal"
size: root.width , root.height
spacing: 25
padding: 530, 900 , 900 , 260
Button:
text: "take a picture"
color: (200,250,210)
font_size: 40
size_hint_x: 1
height:60
size_hint_y: None
width:500
on_release: app.root.current = "camera"
<CameraClick>:
name: "camera"
orientation: 'vertical'
MyCamera:
id: camera
play: True
allow_stretch: True
resolusion: (640,480)
BoxLayout:
orientation: 'vertical'
padding: 100 , 10 , 800 , 590
Button:
text: 'play'
size_hint_y: None
size_hint_x: None
height: '48dp'
pos:200,200
font_size:40
width: 100
height: 50
on_press: camera.play = not camera.play
BoxLayout:
orientation: 'vertical'
padding: 100 , 10 , 800 , 380
Button:
text: 'capture'
size_hint_y: None
size_hint_x: None
height: '48dp'
pos:200,200
font_size:40
width: 100
height: 50
on_press: root.capture()
BoxLayout:
orientation: 'vertical'
padding: 100 , 10 , 800 , 200
Button:
text: 'ZOOM'
size_hint_y: None
size_hint_x: None
height: '48dp'
pos:100,100
font_size:30
width: 100
height: 50
on_press: root.on_touch_down()
BoxLayout:
orientation: 'vertical'
padding: 50 , 10 , 800 , 730
Button:
text: 'HOME'
size_hint_y: None
size_hint_x: None
height: '48dp'
pos:200,200
font_size:40
width: 100
height: 50
on_release: app.root.current = "main page"
""")
class Shenacell(MDApp):
def build(self):
self.theme_cls.primary_palette = "BlueGray"
return WindowManager()
if __name__ == '__main__' :
Shenacell().run()
这是小部件的源代码 Camera。
它有方法 on_tex()
从真实相机 texture
def on_tex(self, camera):
self.texture = texture = camera.texture
self.texture_size = list(texture.size)
self.canvas.ask_update()
texture
有方法 get_region()
可以用来只获取图像的一部分 -
self.texture.get_region(x, y, width, height)
这样你就可以创建 zoom
效果 - 当你有 allow_stretch: True
.
这里是 class,它只获取了一些区域。
我假设相机提供大小为 640x480
的图像,但它需要从 Camera
.
中的变量 resolution
获取值
class MyCamera(Camera):
region_x = NumericProperty(0)
region_y = NumericProperty(0)
region_w = NumericProperty(640)
region_h = NumericProperty(480)
def on_tex(self, camera):
self.texture = texture = camera.texture
# get some region
self.texture = self.texture.get_region(self.region_x, self.region_y, self.region_w, self.region_h)
self.texture_size = list(texture.size)
self.canvas.ask_update()
现在 CameraClick
我可以更改值 region_x, region_y, region_w, region_h
以创建 zoom
效果。
class CameraClick(Screen):
scale = NumericProperty(1)
def on_touch_down(self, touch):
if touch.is_mouse_scrolling:
if touch.button == 'scrolldown':
print("down")
if self.scale < 10:
self.scale *= 1.1
# scale region size
self.ids['camera'].region_w /= 1.1
self.ids['camera'].region_h /= 1.1
# center region
self.ids['camera'].region_x = (640-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (480-self.ids['camera'].region_h) // 2
elif touch.button == 'scrollup':
print("up")
if self.scale > 1:
self.scale *= 0.8
# scale region size
self.ids['camera'].region_w /= 0.8
self.ids['camera'].region_h /= 0.8
if (self.ids['camera'].region_w > 640) or (self.ids['camera'].region_h > 480):
self.ids['camera'].region_w = 640
self.ids['camera'].region_h = 480
# center region
self.ids['camera'].region_x = (640-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (480-self.ids['camera'].region_h) // 2
很多地方需要改变
- 使用
resolution
获取真实相机尺寸而不是硬编码 640
,480
.
- 使用按钮、键盘或鼠标移动图像以查看其他区域。
如果您 运行 使用 allow_stretch: False
编码,那么它会提供更小的图像而不是调整它的大小 - 所以它需要不同的方法。它需要获取纹理、重新缩放并裁剪到预期区域。
完整的工作代码。
编辑:
我添加了Capture
。 on_touch_down
中需要super().on_touch_down(touch)
才能执行on_press
、on_release
等
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.camera import Camera
from kivy.lang import Builder
from kivy.properties import NumericProperty
import time
class MyCamera(Camera):
region_x = NumericProperty(0)
region_y = NumericProperty(0)
region_w = NumericProperty(640)
region_h = NumericProperty(480)
def on_tex(self, camera):
self.texture = texture = camera.texture
# get some region
self.texture = self.texture.get_region(self.region_x, self.region_y, self.region_w, self.region_h)
self.texture_size = list(texture.size)
self.canvas.ask_update()
class WindowManager(ScreenManager):
pass
class CameraClick(Screen):
scale = NumericProperty(1)
def on_touch_down(self, touch):
#print('[DEBUG] on_touch_down')
super().on_touch_down(touch) # run original `Screen.on_touch_down` which runs `on_press`, `on_release`
if touch.is_mouse_scrolling:
if touch.button == 'scrolldown':
print("down: (zoom in) ", self.scale)
if self.scale < 10:
self.scale *= 1.1
# scale region size
self.ids['camera'].region_w /= 1.1
self.ids['camera'].region_h /= 1.1
# center region
self.ids['camera'].region_x = (640-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (480-self.ids['camera'].region_h) // 2
elif touch.button == 'scrollup':
print(" up: (zoom out)", self.scale)
if self.scale > 1:
self.scale *= 0.8
# scale region size
self.ids['camera'].region_w /= 0.8
self.ids['camera'].region_h /= 0.8
if (self.ids['camera'].region_w > 640) or (self.ids['camera'].region_h > 480):
self.ids['camera'].region_w = 640
self.ids['camera'].region_h = 480
# center region
self.ids['camera'].region_x = (640-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (480-self.ids['camera'].region_h) // 2
def capture(self):
camera = self.ids['camera']
filename = time.strftime("IMG_%Y%m%d_%H%M%S.png")
camera.export_to_png(filename)
print("Captured:", filename)
Builder.load_string("""
<WindowManager>:
CameraClick:
<CameraClick>:
name: "camera"
orientation: 'vertical'
MyCamera:
id: camera
play: True
allow_stretch: True
Button:
text: 'Capture'
size_hint_y: None
size_hint_x: None
on_press: root.capture()
""")
class Shenacell(MDApp):
def build(self):
return WindowManager()
if __name__ == '__main__':
Shenacell().run()
也许它应该作为包装器 class 完成,它将 Camera
作为参数。
顺便说一句:
如果您需要同时显示原始图像和缩放图像,那么您可能需要我对问题
的回答中的代码
我搜索了一下,找到了“scatter”,但是scatter用于图像。 我想用实时相机放大它。
有人知道我该怎么做吗?
这是我写的代码示例,但它不起作用。
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import ScreenManager , Screen
from kivy.uix.image import Image
from kivy.core.window import Window
from kivy.base import runTouchApp
from kivymd.app import MDApp
from kivy.uix.boxlayout import BoxLayout
import time
from kivy.core.window import Window
from kivy.uix.camera import Camera
from kivy.uix.scatter import Scatter
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import NumericProperty
Window.size = (1600, 850)
class MyCamera(Camera):
region_x = NumericProperty(0)
region_y = NumericProperty(0)
region_w = NumericProperty(1600)
region_h = NumericProperty(850)
def on_text(self,camera):
self.texture = texture = camera.texture
self.texture = self.texture.get_region(self.region_x, self.region_y, self.region_w, self.region_h)
self.texture_size = list(texture.size)
self.canvas.ask_update()
class MainPage(Screen):
pass
class WindowManager(ScreenManager):
pass
class CameraClick(Screen):
scale = NumericProperty(1)
def on_touch_down(self, touch):
if touch.is_mouse_scrolling:
if touch.button == 'scrolldown':
print("down")
if self.scale <10:
self.scale *= 1.1
self.ids['camera'].region_w /= 1.1
self.ids['camera'].region_h /= 1.1
self.ids['camera'].region_x = (1600-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (850-self.ids['camera'].region_h) // 2
elif touch.button == 'scrollup':
print("up")
if self.scale >1:
self.scale *= 0.8
self.ids['camera'].region_w /= 0.8
self.ids['camera'].region_h /= 0.8
if(self.ids['camera'].region_w > 1600) or (self.ids['camera'].region_h >850):
self.ids['camera'].region_w = 1600
self.ids['camera'].region_h = 850
self.ids['camera'].region_x = (1600-self.ids['camera'].region_w) //2
self.ids['camera'].region_y = (850-self.ids['camera'].region_h) //2
def capture(self):
camera = self.ids['camera']
timestr = time.strftime("%Y%m%d_%H%M%S")
camera.export_to_png("IMG_{}.png".format(timestr))
print("Captured")
Builder.load_string("""
#:import utils kivy.utils
<WindowManager>:
MainPage:
CameraClick:
<MainPage>:
name: "main page"
BoxLayout:
cols:1
orientation: "horizontal"
size: root.width , root.height
spacing: 25
padding: 530, 900 , 900 , 260
Button:
text: "take a picture"
color: (200,250,210)
font_size: 40
size_hint_x: 1
height:60
size_hint_y: None
width:500
on_release: app.root.current = "camera"
<CameraClick>:
name: "camera"
orientation: 'vertical'
MyCamera:
id: camera
play: True
allow_stretch: True
resolusion: (640,480)
BoxLayout:
orientation: 'vertical'
padding: 100 , 10 , 800 , 590
Button:
text: 'play'
size_hint_y: None
size_hint_x: None
height: '48dp'
pos:200,200
font_size:40
width: 100
height: 50
on_press: camera.play = not camera.play
BoxLayout:
orientation: 'vertical'
padding: 100 , 10 , 800 , 380
Button:
text: 'capture'
size_hint_y: None
size_hint_x: None
height: '48dp'
pos:200,200
font_size:40
width: 100
height: 50
on_press: root.capture()
BoxLayout:
orientation: 'vertical'
padding: 100 , 10 , 800 , 200
Button:
text: 'ZOOM'
size_hint_y: None
size_hint_x: None
height: '48dp'
pos:100,100
font_size:30
width: 100
height: 50
on_press: root.on_touch_down()
BoxLayout:
orientation: 'vertical'
padding: 50 , 10 , 800 , 730
Button:
text: 'HOME'
size_hint_y: None
size_hint_x: None
height: '48dp'
pos:200,200
font_size:40
width: 100
height: 50
on_release: app.root.current = "main page"
""")
class Shenacell(MDApp):
def build(self):
self.theme_cls.primary_palette = "BlueGray"
return WindowManager()
if __name__ == '__main__' :
Shenacell().run()
这是小部件的源代码 Camera。
它有方法 on_tex()
从真实相机 texture
def on_tex(self, camera):
self.texture = texture = camera.texture
self.texture_size = list(texture.size)
self.canvas.ask_update()
texture
有方法 get_region()
可以用来只获取图像的一部分 -
self.texture.get_region(x, y, width, height)
这样你就可以创建 zoom
效果 - 当你有 allow_stretch: True
.
这里是 class,它只获取了一些区域。
我假设相机提供大小为 640x480
的图像,但它需要从 Camera
.
resolution
获取值
class MyCamera(Camera):
region_x = NumericProperty(0)
region_y = NumericProperty(0)
region_w = NumericProperty(640)
region_h = NumericProperty(480)
def on_tex(self, camera):
self.texture = texture = camera.texture
# get some region
self.texture = self.texture.get_region(self.region_x, self.region_y, self.region_w, self.region_h)
self.texture_size = list(texture.size)
self.canvas.ask_update()
现在 CameraClick
我可以更改值 region_x, region_y, region_w, region_h
以创建 zoom
效果。
class CameraClick(Screen):
scale = NumericProperty(1)
def on_touch_down(self, touch):
if touch.is_mouse_scrolling:
if touch.button == 'scrolldown':
print("down")
if self.scale < 10:
self.scale *= 1.1
# scale region size
self.ids['camera'].region_w /= 1.1
self.ids['camera'].region_h /= 1.1
# center region
self.ids['camera'].region_x = (640-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (480-self.ids['camera'].region_h) // 2
elif touch.button == 'scrollup':
print("up")
if self.scale > 1:
self.scale *= 0.8
# scale region size
self.ids['camera'].region_w /= 0.8
self.ids['camera'].region_h /= 0.8
if (self.ids['camera'].region_w > 640) or (self.ids['camera'].region_h > 480):
self.ids['camera'].region_w = 640
self.ids['camera'].region_h = 480
# center region
self.ids['camera'].region_x = (640-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (480-self.ids['camera'].region_h) // 2
很多地方需要改变
- 使用
resolution
获取真实相机尺寸而不是硬编码640
,480
. - 使用按钮、键盘或鼠标移动图像以查看其他区域。
如果您 运行 使用 allow_stretch: False
编码,那么它会提供更小的图像而不是调整它的大小 - 所以它需要不同的方法。它需要获取纹理、重新缩放并裁剪到预期区域。
完整的工作代码。
编辑:
我添加了Capture
。 on_touch_down
中需要super().on_touch_down(touch)
才能执行on_press
、on_release
等
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.camera import Camera
from kivy.lang import Builder
from kivy.properties import NumericProperty
import time
class MyCamera(Camera):
region_x = NumericProperty(0)
region_y = NumericProperty(0)
region_w = NumericProperty(640)
region_h = NumericProperty(480)
def on_tex(self, camera):
self.texture = texture = camera.texture
# get some region
self.texture = self.texture.get_region(self.region_x, self.region_y, self.region_w, self.region_h)
self.texture_size = list(texture.size)
self.canvas.ask_update()
class WindowManager(ScreenManager):
pass
class CameraClick(Screen):
scale = NumericProperty(1)
def on_touch_down(self, touch):
#print('[DEBUG] on_touch_down')
super().on_touch_down(touch) # run original `Screen.on_touch_down` which runs `on_press`, `on_release`
if touch.is_mouse_scrolling:
if touch.button == 'scrolldown':
print("down: (zoom in) ", self.scale)
if self.scale < 10:
self.scale *= 1.1
# scale region size
self.ids['camera'].region_w /= 1.1
self.ids['camera'].region_h /= 1.1
# center region
self.ids['camera'].region_x = (640-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (480-self.ids['camera'].region_h) // 2
elif touch.button == 'scrollup':
print(" up: (zoom out)", self.scale)
if self.scale > 1:
self.scale *= 0.8
# scale region size
self.ids['camera'].region_w /= 0.8
self.ids['camera'].region_h /= 0.8
if (self.ids['camera'].region_w > 640) or (self.ids['camera'].region_h > 480):
self.ids['camera'].region_w = 640
self.ids['camera'].region_h = 480
# center region
self.ids['camera'].region_x = (640-self.ids['camera'].region_w) // 2
self.ids['camera'].region_y = (480-self.ids['camera'].region_h) // 2
def capture(self):
camera = self.ids['camera']
filename = time.strftime("IMG_%Y%m%d_%H%M%S.png")
camera.export_to_png(filename)
print("Captured:", filename)
Builder.load_string("""
<WindowManager>:
CameraClick:
<CameraClick>:
name: "camera"
orientation: 'vertical'
MyCamera:
id: camera
play: True
allow_stretch: True
Button:
text: 'Capture'
size_hint_y: None
size_hint_x: None
on_press: root.capture()
""")
class Shenacell(MDApp):
def build(self):
return WindowManager()
if __name__ == '__main__':
Shenacell().run()
也许它应该作为包装器 class 完成,它将 Camera
作为参数。
顺便说一句:
如果您需要同时显示原始图像和缩放图像,那么您可能需要我对问题