0

I want to create image with numpy (just create array that represents image), then I want to draw something on it using open-cv, and then show that image on a tkinter Canvas widget (with help from Pillow Image and ImageTk). The thing is that if I execute this code, nothing shows up in Canvas widget.

import numpy as np
import cv2
from PIL import Image, ImageTk
from tkinter import *

frame = np.full((150, 150, 3), 240, dtype="uint8")
cv2.circle(frame, (75, 75), 50, [0, 0, 0], -1, cv2.LINE_AA)
img = Image.fromarray(frame)
img2 = ImageTk.PhotoImage(image=img)
btns[i][j].create_image(75, 75, anchor="center", image=img2)  # btns[i][j] is Canvas object

But if I execute this code:

import numpy as np
import cv2
from PIL import Image, ImageTk
from tkinter import *

frame = np.full((150, 150, 3), 240, dtype="uint8")
cv2.circle(frame, (75, 75), 50, [0, 0, 0], -1, cv2.LINE_AA)
img = Image.fromarray(frame)
img.show()
img2 = ImageTk.PhotoImage(image=img)
btns[i][j].create_image(75, 75, anchor="center", image=img2)  # btns[i][j] is Canvas object

(after closing popup window showing the image, which looks fine) it shows correctly on Canvas. The only difference was that I used show() on Pillow Image. I can't understand why would I need to show Image first for it to work in tkinter.

Dark Lord
  • 41
  • 9
  • In your actual program, is the code that adds the image to a Canvas at the top level (as shown here), or is it actually inside a function? A PhotoImage that is only referenced by a local variable will be garbage-collected, probably before becoming visible. – jasonharper Jun 05 '22 at 21:58
  • It is in function, but I don't understand why would it work with img.show() and not work without it? What do you suggest for me to try to fix this? Should I define PhotoImage outside function? – Dark Lord Jun 05 '22 at 22:03
  • Try the fix from https://stackoverflow.com/questions/16424091/why-does-tkinter-image-not-show-up-if-created-in-a-function - which would be something like `btns[i][j].image = img2` in this case. I don't see how `img.show()` could have any effect, either - but since you haven't shown us a [mcve], I'm just going to assume that something else you haven't shown us is responsible for the difference. – jasonharper Jun 05 '22 at 22:11
  • Your code failed to run because `Image` is from `tkinter` module (because `from tkinter import *` is after `from PIL import Image`) which does not have `.fromarray()` function. Fixing the import order, it works fine (after adding missing parts). That is why wildcard import is not recommended. – acw1668 Jun 06 '22 at 00:55
  • @jasonharper You were right, the fix works. As to why it worked before when I used show(), I don't know but that was definitely the cause of it, because with line omitted, it didn't work, and with it it worked. Maybe because show() supposedly saves temp file that can be opened in image viewer it didn't get garbage-collected? – Dark Lord Jun 06 '22 at 13:52
  • @acw1668 Pretty sure that Image is from Pillow module, and not tkinter as you suggested. It works fine now that I put it outside function. – Dark Lord Jun 06 '22 at 13:53
  • @DarkLord Based on the import order in your posted code, it is pretty sure that `Image` is from `tkinter` module. – acw1668 Jun 06 '22 at 14:52

0 Answers0