Search code examples
pythontkinter-canvasimage-upload

Python - tkinter; TypeError: Expected Ptr<cv::UMat> for argument 'src'


I'm trying to build a graphical interface for image processing. I have problem uploading function. When I try to check if the file / image exists and modify it, I get this error and I don't know how to fix it.

TypeError: Expected Ptr<cv::UMat> for argument 'src'

This is my code:

import cv2

import instructions as instructions
from PIL import Image,ImageTk
from tkinter.filedialog import askopenfile

root = tk.Tk()

logo = Image.open('logo.png')
logo = ImageTk.PhotoImage(logo)
logo_label = tk.Label(image = logo)
logo_label.image = logo
logo_label.grid(column=1,row=0)

def upload():
    browse.set("loading...")
    file = askopenfile(parent=root,mode="rb",title="Choose an image",filetypes =[("JPG file","*.jpg"),("PNG file","*.png"),("JPEG file","*.jpeg")])
    if file:
        gray = cv2.cvtColor(file, cv2.COLOR_RGB2GRAY)
        gray = cv2.medianBlur(gray,5)
        edges = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY, 9, 9)

        color = cv2.bilateralFilter(file,9,250,250)
        cartoon =cv2.bitwise_and(color,color,mask=edges)
        cv2.imshow("Cartoon", cartoon)

intructions = tk.Label(root,text= "Select an image",font = "Raleway")
instructions.grid(columnspan=3,column=0,row=1)



browse = tk.StringVar()
browse_button = tk.Button(root,textvariable = browse,command = lambda:upload(),font = "Raleway",bg="#20bebe",fg ="white",width=15,height =2)
browse.set("Browse")
browse_button.grid(column=1,row=2)

canvas = tk.Canvas(root,width = 600,height = 300)
canvas.grid(columnspan = 3)
root.mainloop()

Thank you!


Solution

  • In line no 20: you are using CvtColor to change the image to grayscale.
    gray = cv2.cvtColor(file, cv2.COLOR_RGB2GRAY) you need to pass the file pointer in place of file. That is why you are getting the error TypeError: Expected Ptr<cv::UMat> for argument 'src'

    You need to :
    First read the file using img=cv2.imread(file), and then use
    CvtColor on the img data using gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY).

    So delete the content in line 20 and add

    img=cv2.imread(file)
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

    Edit:
    One important thing on line 6 you are importing askopenfile which returns a binary encoded path of the image. This is wrong implementation.
    Instead you should import askopenfilename; this returns the path of the image file.
    I am sharing the entire updated code here :

    import cv2
    import tkinter as tk
    
    import instructions as instructions
    from PIL import Image,ImageTk
    from tkinter.filedialog import askopenfilename
    
    root = tk.Tk()
    
    logo = Image.open('logo.jpg')
    logo = ImageTk.PhotoImage(logo)
    logo_label = tk.Label(image = logo)
    logo_label.image = logo
    logo_label.grid(column=1,row=0)
    
    def upload():
        browse.set("loading...")
        file = askopenfilename(parent=root,title="Choose an image",filetypes =[("JPG file","*.jpg"),("PNG file","*.png"),("JPEG file","*.jpeg")])
        print(file)
        if file:
            img=cv2.imread(file)
            gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
            gray = cv2.medianBlur(gray,5)
            edges = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY, 9, 9)
    
            color = cv2.bilateralFilter(img,9,250,250)
            cartoon =cv2.bitwise_and(color,color,mask=edges)
            cv2.imshow("Cartoon", cartoon)
    
    intructions = tk.Label(root,text= "Select an image",font = "Raleway")
    instructions.grid(columnspan=3,column=0,row=1)
    
    
    
    browse = tk.StringVar()
    browse_button = tk.Button(root,textvariable = browse,command = lambda:upload(),font = "Raleway",bg="#20bebe",fg ="white",width=15,height =2)
    browse.set("Browse")
    browse_button.grid(column=1,row=2)
    
    canvas = tk.Canvas(root,width = 600,height = 300)
    canvas.grid(columnspan = 3)
    root.mainloop()
    This should work let me know.
    Hope this solves your purpose