# How to display images (np.hstack) in tkinter frame

**URL:** <https://forum.opencv.org/t/how-to-display-images-np-hstack-in-tkinter-frame/19653>\
**Category:** Python\
**Tags:** programming\
**Created:** [December 31, 2024, 12:15am UTC](https://forum.opencv.org/t/how-to-display-images-np-hstack-in-tkinter-frame/19653 "2024-12-31T00:15:59Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alan\_Miller](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/alan_miller/32/5560_2.png) [@Alan\_Miller](https://forum.opencv.org/u/Alan_Miller)\
**Post date:** [December 31, 2024, 12:15am UTC](https://forum.opencv.org/t/how-to-display-images-np-hstack-in-tkinter-frame/19653/1 "2024-12-31T00:15:59Z")

</div>

I’m trying to build a tkinter GUI to show frames from 2 captures side-by-side.  
This code works.

```python
import cv2, numpy as np
from tkinter import NW, Tk, Canvas, PhotoImage

def photo_image(img):
    h, w = img.shape[:2]
    data = f'P6 {w} {h} 255 '.encode() + img[..., ::-1].tobytes()
    return PhotoImage(width=w, height=h, data=data, format='PPM')
def update():
    ret1, img1 = cap1.read()
    ret2, img2 = cap2.read()
    if ret1:
        photo = photo_image(np.hstack((img1, img2)))
        canvas.create_image(0, 0, image=photo, anchor=NW)
        canvas.image = photo
    root.after(15, update)
root = Tk()
root.title("Video")
cap1 = cv2.VideoCapture('/tmp/fto-20241229_184824_Sports2D.mp4')
cap2 = cv2.VideoCapture('/tmp/dtl-20241229_184824_Sports2D.mp4')
canvas = Canvas(root, width=1650, height=700)
canvas.pack()
update()
root.mainloop()
cap1.release()
cap2.release()

```

 ![pic1](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/7/79de29441b62c000ed0df184cf84128b19e6e313.jpeg)

But when I try to implement the same code in a class I get the error  
when I slide through the frames. ie  
pyimage2" doesn’t exist  
pyimage3" doesn’t exist  
pyimage4" doesn’t exist

```auto
_tkinter.TclError: image "pyimage2" doesn't exist

```

```python
import tkinter as tk
import cv2
import numpy as np
from tkinter import *
from tkinter.ttk import *

class Application(tk.Tk):
    def __init__ (self, width, height, video1, video2):
        super(). __init__ ()

        self.root = tk.Tk()
        self.root.option_add("*tearOff", False)
        self.root.title("Golf Swing Analysis")
        self.photo = None
        self.style = Style()
        self.width = width
        self.height = height
        self.cap1 = cv2.VideoCapture(video1)
        self.cap2 = cv2.VideoCapture(video2)
        self.cap1.set(cv2.CAP_PROP_FRAME_WIDTH, self.width)
        self.cap1.set(cv2.CAP_PROP_FRAME_HEIGHT, self.height)
        self.cap2.set(cv2.CAP_PROP_FRAME_WIDTH, self.width)
        self.cap2.set(cv2.CAP_PROP_FRAME_HEIGHT, self.height)

        # Create toolbar
        toolbar = tk.Frame(self.root, bd=1, height=50, relief=tk.RAISED)
        toolbar.pack(side=tk.TOP, fill=tk.X)

        self.paned = PanedWindow(self.root)
        self.paned.pack()
        self.pane1 = Frame(self.paned)
        self.paned.add(self.pane1, weight=1)
        self.pane1.pack()
        self.notebook = Notebook(self.pane1)
        self.notebook.pack()

        self.tab1 = Frame(self.notebook)
        self.notebook.add(self.tab1, text="Swing View")
        self.tab2 = Frame(self.notebook)
        self.label2 = Label(self.tab2, text="Reference", justify="center")
        self.label2.pack()
        self.notebook.add(self.tab2, text="Reference Swing")

        # Add buttons to toolbar
        backBtn = tk.Button(toolbar, text='Previous', command=self.previous_file)
        backBtn.pack(side=tk.LEFT)
        nextBtn = tk.Button(toolbar, text="Next", command=self.next_file)
        nextBtn.pack(side=tk.LEFT)

        self.sep = Separator(orient="vertical")
        self.sep.pack(side=tk.LEFT)
        label = Label(toolbar, text="Drawing Tools: ")
        label.pack(side="left")
        self.var = tk.IntVar()
        drawOn = Radiobutton(toolbar, text="enable", variable=self.var, value=1, command=self.toggle_radio)
        drawOn.pack(side="left")
        drawOff = Radiobutton(toolbar, text="disable", variable=self.var, value=0, command=self.toggle_radio)
        drawOff.pack(side="left")
        plotBtn = tk.Button(toolbar, text="Show Plots", command=self.show_plot)
        plotBtn.pack(side=tk.LEFT)
        exportBtn = tk.Button(toolbar, text="Export", command=self.export_results)
        exportBtn.pack(side=tk.LEFT)
        quitBtn = tk.Button(toolbar, text="Quit", command=self.exit_app)
        quitBtn.pack(side=tk.RIGHT)

        label = Label(toolbar, text="Frame: ")
        label.pack(side="left")
        self.scale = tk.Scale(toolbar, from_=0, to=240, orient="horizontal", length=240, command=self.slider_changed)
        self.scale.pack(side=tk.LEFT)

        self.root.bind("<Left>", lambda e: self.scale.set(self.scale.get()-1))
        self.root.bind("<Right>", lambda e: self.scale.set(self.scale.get()+1))

        self.canvas = Canvas(self.tab1, width=1610, height=640, highlightbackground="red", highlightthickness=2)
        self.canvas.pack()

        self.notebook.pack(expand=True, fill="both", padx=5, pady=5)
        self.root.after(0, self.update)

    def next_file(self):
        print("Open next swing")

    def previous_file(self):
        print("Open previous swing")

    def export_results(self):
        print("Exporting results")

    def show_plot(self):
        print("Plotting results")

    def exit_app(self):
        self.root.destroy()

    def toggle_radio(self):
        if self.var.get() == 1:
            print("drawings enabled")
        elif self.var.get() == 0:
            print("drawings disabled")

    def slider_changed(self,value):
        self.cap1.set(cv2.CAP_PROP_POS_FRAMES, int(value))
        self.cap2.set(cv2.CAP_PROP_POS_FRAMES, int(value))
        self.update()

    def photo_image(self,img):
        h, w = img.shape[:2]
        data = f'P6 {w} {h} 255 '.encode() + img[..., ::-1].tobytes()
        return PhotoImage(width=w, height=h, data=data, format='PPM')

    def update(self):
        ret1, img1 = self.cap1.read()
        ret2, img2 = self.cap2.read()

        if ret1 and ret2:
            photo = self.photo_image(np.hstack((img1, img2)))
            self.canvas.create_image(0, 0, image=photo, anchor=NW)
            self.canvas.image = photo
        
        self.root.after(15, self.update)

    def __del__ (self):
        self.cap1.release()
        self.cap2.release()

if __name__ == " __main__":
    video1='/tmp/fto-20241229_184824_Sports2D.mp4'
    video2='/tmp/dtl-20241229_184824_Sports2D.mp4'
    app = Application(800,600,video1,video2)
    app.mainloop()

```

 ![pic2](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/0/08613d1ccec587e3e95205870354a9ecb687899a.png)

---

<div class="post-metadata">

**Author:** ![Alan\_Miller](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/alan_miller/32/5560_2.png) [@Alan\_Miller](https://forum.opencv.org/u/Alan_Miller)\
**Post date:** [December 31, 2024, 1:36pm UTC](https://forum.opencv.org/t/how-to-display-images-np-hstack-in-tkinter-frame/19653/2 "2024-12-31T13:36:13Z")

</div>

Nevermind, it’s working. Was not really an opencv but a Tkinter question anyway.

![demo](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/a/a21adb52c5f46b65404b241521b34465590fc6b1.gif)

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [December 31, 2024, 1:44pm UTC](https://forum.opencv.org/t/how-to-display-images-np-hstack-in-tkinter-frame/19653/3 "2024-12-31T13:44:00Z")

</div>


