在 Kivy 布局上显示 OpenCV 图像结果和绘图

Posted

技术标签:

【中文标题】在 Kivy 布局上显示 OpenCV 图像结果和绘图【英文标题】:Displaying an OpenCV Imageresult and Plots on Kivy Layouts 【发布时间】:2021-12-03 20:17:52 【问题描述】:

我是 OpenCV 的初学者,是一个试图创建 android 应用程序的 kivy。

我的应用应该显示通过一些 OpenCV 命令的图像。

目前我无法在我的 Kivy 布局中显示这些图像。

我知道您可以通过以下方式在 Kivy 上显示图像:

    Image:

                source: 'Images/Cats.jpg'

但是当我得到一个像这个阈值图像这样的“编辑”图像时,我需要另一种方法:

threshold, thresh_inverse = cv.threshold(gray, 150, 255, cv.THRESH_BINARY_INV)
cv.imshow('Easy Threshold INV', thresh_inverse)

与我想在 Kivy 布局中显示的直方图相同。

img = cv.imread('C:\\Users\\julia\\Desktop\\Images_HHN\\Cats3.jpg')
cv.imshow('Bsp. HHN', img)
blank = np.zeros(img.shape[:2],dtype='uint8')
Circle = cv.circle(blank, (img.shape[1] // 2, img.shape[0] // 2), 100, 255, -1)
cv.imshow('Circle', Circle)
mask= cv.bitwise_and(img,img, mask= Circle )
cv.imshow('MaskPic', mask)

plt.xlim([0, 256])
plt.show()
colors = ('b', 'g', 'r')
plt.figure()
plt.title('Color Histogramm')
plt.xlabel('Bins')
plt.ylabel('n pixels')


for i, col in enumerate(colors):
    hist = cv.calcHist([img], [i], None, [256], [0,256 ])
    plt.plot(hist,color=col)
    plt.xlim([0,256])


plt.show()

如果有人可以给我提示以在我的 Kivy 布局 id 上显示它们,非常感谢。

感谢您的帮助!

【问题讨论】:

文件 .kv 仅加载一次 - 在开始时。稍后您必须使用 Python 代码更改 Kivy 中的image.source。使用 plt.show() 对此毫无用处。它可能需要将绘图保存在文件中或io.BytesIo 中并在 Kivy 中加载。 嘿@furas 谢谢你的回答。更改 image.source 不是一个选项,因为我没有从 OpenCV 保存编辑后的图像。 OpenCV 应该从 image.source 中获取该图片并将其设置为阈值,然后显示它。明天我会看一段 YouTube 视频 (youtu.be/83C4tl8scoY),展示如何在 Kivy 的 Plot 中显示。那可能会有所帮助。给大家分享一下。 【参考方案1】:

文件.kv仅在启动时加载,之后您必须使用Python代码更新image.sourceimage.texture

cv 保持图像为numpy array,所以我使用numpy 生成随机数组,转换为kivy Texture 并分配给现有的Image

我使用 Clock 每 0.25 秒重复一次,但您可以使用 Button 运行它。

from kivy.app import App
from kivy.uix.image import Image
from kivy.graphics.texture import Texture
from kivy.clock import Clock
import numpy as np
import cv2

# --- functions ---

def generate_texture():
    """Generate random numpy array `500x500` as iamge, use cv2 to change image, and convert to Texture."""
    
    # numpy array
    img = np.random.randint(0, 256, size=(500, 500, 3), dtype=np.uint8)

    cv2.circle(img, (img.shape[1]//2, img.shape[0]//2), 100, 255, -1)

    data = img.tobytes()

    # texture
    texture = Texture.create(size=(500, 500), colorfmt="rgb")
    texture.blit_buffer(data, bufferfmt="ubyte", colorfmt="rgb")
    
    return texture

def update_image(dt):
    """Replace texture in existing image."""
    
    image.texture = generate_texture()

# --- main ---
 
# empty image at start    
image = Image()
    
class MyPaintApp(App):
    def build(self):
        return image

# run function every 0.25 s
Clock.schedule_interval(update_image, 0.25)

if __name__ == '__main__':
    MyPaintApp().run()

结果:


plt 可能需要不同的方法。它可能需要将绘图保存在io.BytesIO(模拟内存中的文件)并将其从io.BytesIO读取到CoreImage并将CoreImage.texture复制到Image.texture

from kivy.app import App
from kivy.uix.image import Image, CoreImage
from kivy.graphics.texture import Texture
from kivy.clock import Clock
import io
import numpy as np
import matplotlib.pyplot as plt

# --- functions ---

def generate_texture():
    """Generate random numpy array, plot it, save it, and convert to Texture."""
    
    # numpy array
    arr = np.random.randint(0, 100, size=10, dtype=np.uint8)
    
    # plot
    plt.clf() # remove previous plot
    plt.plot(arr)
    
    # save in memory
    data = io.BytesIO()
    plt.savefig(data)
    
    data.seek(0)  # move to the beginning of file
    
    return CoreImage(data, ext='png').texture
    
def update_image(dt):
    """Replace texture in existing image."""
    
    image.texture = generate_texture()
    
# --- main ---
 
# empty image at start    
image = Image()
    
class MyPaintApp(App):
    def build(self):
        return image

# run function every 0.25 s
Clock.schedule_interval(update_image, 0.25)

if __name__ == '__main__':
    MyPaintApp().run()

结果:

【讨论】:

我在第一个示例中添加了cv2.circle()

以上是关于在 Kivy 布局上显示 OpenCV 图像结果和绘图的主要内容,如果未能解决你的问题,请参考以下文章

如何在屏幕中选择图像并使用 kivy 将其显示在另一个屏幕上?

将 kivy 纹理转换为 opencv 图像

如何在 Kivy 中将图像放入动态文本中

Kivy 按钮背景图像大小

如何在回调时在 Kivy 布局之间切换?

Kivy 网格布局固定了某些列的列宽