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!
CodePudding user response:
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:
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: