blitting opencv图片上的Kivy分割错误
Kivy segmentation fault on blitting opencv picture
我正在尝试将通过某些 aliexpress EasyCap 捕获的外部摄像头视频投射到我的 kivy 应用程序。我遇到的一个问题是在尝试
时因分段错误而崩溃
texture = Texture.create(size=(frame.shape[0], frame.shape[1]))
我发现问题出在 kivy's side 上。它有时无法创建 NPOT 纹理。因此,我将其更改为 POT 形状并将可能的内容复制到另一个 numpy 数组。
flipped = cv2.flip(frame, 0)
buf = np.zeros((512, 512, 3), dtype=np.uint8)
for i in range(min(frame.shape[0], 512)):
for j in range(min(frame.shape[1], 512)):
buf[i, j] = flipped[i, j]
buf = buf.tostring()
texture = Texture.create(size=(512, 512))
texture.blit_buffer(buf, colorfmt="bgr", bufferfmt="ubyte")
self.texture = texture
但它仍然因以下行中相同的旧分段错误而崩溃:
texture.blit_buffer(buf, colorfmt="bgr", bufferfmt="ubyte")
如果相关,cv2.imshow("image", buf) 在 buf.tostring() 之前正确显示图像。
原代码如下:
from kivy.app import App
from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.graphics.texture import Texture
import cv2
import threading
from time import sleep
import numpy as np
class KivyCamera(Image):
def __init__(self, **kwargs):
super(KivyCamera, self).__init__(**kwargs)
self.fps = 30
self.capture = cv2.VideoCature(0)
threading.Thread(target=self.update).start()
def update(self):
while True:
ret, frame = self.capture.read()
if ret:
buf = cv2.flip(frame, 0).tostring()
texture = Texture.create(size=(frame.shape[0], frame.shape[1])
texture.blit_buffer(buf, colorfmt="bgr", bufferfmt="ubyte")
self.texture = texture
sleep(1.0 / self.fps)
class CamApp(App):
def build(self):
return KivyCamera()
if __name__ == "__main__":
CamApp().run()
没有很好的记录,但我相信 Texture
操作(特别是 blit_buffer()
)必须在主线程上完成。您的 update()
方法在另一个线程中被 运行,因此使用 Clock.schedule_once()
调用一个方法,该方法在主线程。
您的代码有几个问题:
- GUI 更新应始终在主线程中完成,如 John Anderson 所示。因此,应该通过
Clock
计划调用 update()
函数,而不是单独的线程。
- 把
Texture.create
语句中的size
元组取反,加上colorfmt="bgr"
。应该是:texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt="bgr")
.
- 没有定义布局。
BoxLayout
等布局应添加为 Image
小部件的占位符。
以下是您的代码的修改后的工作版本:
from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.graphics.texture import Texture
import cv2
class KivyCamera(BoxLayout):
def __init__(self, **kwargs):
super(KivyCamera, self).__init__(**kwargs)
self.img1=Image()
self.add_widget(self.img1)
self.capture = cv2.VideoCapture(0)
Clock.schedule_interval(self.update, 1.0/33.0)
def update(self, *args):
ret, frame = self.capture.read()
if ret:
buf = cv2.flip(frame, 0).tostring()
texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt="bgr")
texture.blit_buffer(buf, colorfmt="bgr", bufferfmt="ubyte")
self.img1.texture = texture
class CamApp(App):
def build(self):
return KivyCamera()
if __name__ == "__main__":
CamApp().run()
删除了 while
循环,Clock.schedule_interval
与 1 / 33.
个步骤一起使用。
希望对您有所帮助。
我正在尝试将通过某些 aliexpress EasyCap 捕获的外部摄像头视频投射到我的 kivy 应用程序。我遇到的一个问题是在尝试
时因分段错误而崩溃texture = Texture.create(size=(frame.shape[0], frame.shape[1]))
我发现问题出在 kivy's side 上。它有时无法创建 NPOT 纹理。因此,我将其更改为 POT 形状并将可能的内容复制到另一个 numpy 数组。
flipped = cv2.flip(frame, 0)
buf = np.zeros((512, 512, 3), dtype=np.uint8)
for i in range(min(frame.shape[0], 512)):
for j in range(min(frame.shape[1], 512)):
buf[i, j] = flipped[i, j]
buf = buf.tostring()
texture = Texture.create(size=(512, 512))
texture.blit_buffer(buf, colorfmt="bgr", bufferfmt="ubyte")
self.texture = texture
但它仍然因以下行中相同的旧分段错误而崩溃:
texture.blit_buffer(buf, colorfmt="bgr", bufferfmt="ubyte")
如果相关,cv2.imshow("image", buf) 在 buf.tostring() 之前正确显示图像。
原代码如下:
from kivy.app import App
from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.graphics.texture import Texture
import cv2
import threading
from time import sleep
import numpy as np
class KivyCamera(Image):
def __init__(self, **kwargs):
super(KivyCamera, self).__init__(**kwargs)
self.fps = 30
self.capture = cv2.VideoCature(0)
threading.Thread(target=self.update).start()
def update(self):
while True:
ret, frame = self.capture.read()
if ret:
buf = cv2.flip(frame, 0).tostring()
texture = Texture.create(size=(frame.shape[0], frame.shape[1])
texture.blit_buffer(buf, colorfmt="bgr", bufferfmt="ubyte")
self.texture = texture
sleep(1.0 / self.fps)
class CamApp(App):
def build(self):
return KivyCamera()
if __name__ == "__main__":
CamApp().run()
没有很好的记录,但我相信 Texture
操作(特别是 blit_buffer()
)必须在主线程上完成。您的 update()
方法在另一个线程中被 运行,因此使用 Clock.schedule_once()
调用一个方法,该方法在主线程。
您的代码有几个问题:
- GUI 更新应始终在主线程中完成,如 John Anderson 所示。因此,应该通过
Clock
计划调用update()
函数,而不是单独的线程。 - 把
Texture.create
语句中的size
元组取反,加上colorfmt="bgr"
。应该是:texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt="bgr")
. - 没有定义布局。
BoxLayout
等布局应添加为Image
小部件的占位符。
以下是您的代码的修改后的工作版本:
from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.graphics.texture import Texture
import cv2
class KivyCamera(BoxLayout):
def __init__(self, **kwargs):
super(KivyCamera, self).__init__(**kwargs)
self.img1=Image()
self.add_widget(self.img1)
self.capture = cv2.VideoCapture(0)
Clock.schedule_interval(self.update, 1.0/33.0)
def update(self, *args):
ret, frame = self.capture.read()
if ret:
buf = cv2.flip(frame, 0).tostring()
texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt="bgr")
texture.blit_buffer(buf, colorfmt="bgr", bufferfmt="ubyte")
self.img1.texture = texture
class CamApp(App):
def build(self):
return KivyCamera()
if __name__ == "__main__":
CamApp().run()
删除了 while
循环,Clock.schedule_interval
与 1 / 33.
个步骤一起使用。
希望对您有所帮助。