Search code examples
pythonandroidopencvlayoutkivy

Displaying an OpenCV Imageresult and Plots on Kivy Layouts


im an beginner with OpenCV an kivy trying to create an Android application.

My App should display images which went through some OpenCV Commands.

At the moment im having trouble to show these Images im my Kivy Layouts.

I know that you can display Images on Kivy with:

    Image:

                source: 'Images/Cats.jpg'

But i need an other way when i got an "edited" Image like this Threshold Image:

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

Same with the plot of an Histogram which I want to display in my Kivy Layout.

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()

If someone could give me tips to Display them on my Kivy Layout id be very thankfull.

Thank you for your help!


Solution

  • File .kv is loaded only at start and later you have to use Python code to update image.source or image.texture.

    cv keeps image as numpy array so I used numpy to generate random array, convert to kivy Texture and assign to existing Image.

    I used Clock to repeate it every 0.25 s but you can use Button to run it.

    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()
    

    Result:

    enter image description here


    plt may need different method. It may need to save plot in io.BytesIO (which simulates file in memory) and read it from io.BytesIO to CoreImage and copy CoreImage.texture to 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()
    

    Result:

    enter image description here