Image Captcha with GUI (Tkinter) | Python

Captcha! That sounds like Gotcha! Well, CAPTCHA stands for Completely Automated Public Turing test to tell Computers and Humans Apart. It does sound similar to gotcha as it detects whether the user is real or a spam robot. How does it work? You get an Image Captcha or Audio Captcha from which you have to determine the letters written/spoken. Then basically the input is matched with the actual string of letters present in the Image/Audio. Finally, if the input matches then you’re allowed past the Verification Gateway.

In this tutorial, we are going to see How we can develop and embed Image Captcha in GUI (Tkinter)-Python. We are going to follow the Algorithm mentioned below for the same:

Algorithm for Image Captcha in Python

Below is the figure of the algorithm structure for our task:

Algorithm

Installing and Loading the Dependencies Required

We will require the following Python Packages:

1. tkinter

Tkinter is a Python binding to the Tk GUI toolkit. It is the standard Python interface to the Tk GUI toolkit and is Python’s de-facto standard GUI. So, we will use Tkinter to create the GUI window.

2. PIL

PIL package, short form for Pillow is an Image Processing library that provides us with extensive methods of operations that can be performed on images. So, we will use it for dealing with operations on the Captcha image.

3. captcha

Captcha is a library that is used in the generation of Audio or Image CAPTCHAs. We will use it for Image Captcha Generation.

We can install these packages easily using the pip module.

pip install tk
pip install Pillow
pip install captcha

After the installation part is done, we will be importing:

  • random and string module
  • Tk, Label, Entry, Button, END from tkinter
  • ImageTk and Image modules from PIL
  • ImageCaptcha module from captcha.image
# Importing the Required Libraries
import random
import string
from tkinter import Tk, Label, Entry, Button, END
from PIL import ImageTk, Image
from captcha.image import ImageCaptcha

Defining the CreateImage Function

The createImage function creates and places the captcha Image inside the GUI window. Firstly, we define the required variables including:

  • random_string: which keeps a track of the random string generated globally.
  • image_label: the label which displays the image inside the window.
  • image_display: stores the Captcha Image to be displayed. Making it global so that the garbage collector doesn’t empty its contents.
  • entry: used for emptying the contents of the textbox.
  • verify_label: used for displaying the status of Verification.

When we press the reload button, we basically call this function again and pass 1 as a parameter so that the function can know that the call is made through the reload button. So, the verify_label is removed from the GUI window when a call is made through the reload button,

Whenever we call this function, it firstly deletes the contents of the TextBox. Then, it generates a random string using the choices method, passing the letters and digits and length = 6 as parameters. After that, it creates an object of ImageCaptcha class and passes width and height as parameters. Then, it generates a captcha image for the random_string, and further, it is opened and stored in the image_display variable.

Lastly, image_label displays the generated Captcha Image inside the GUI window.

def createImage(flag=0):
    """
    Defining the method createImage() which will create
    and generate a Captcha Image based on a randomly
    generated strings. The Captcha Image generated is then
    incorporated into the GUI window we have designed.
    """
    global random_string
    global image_label
    global image_display
    global entry
    global verify_label

    # The if block below works only when we press the
    # Reload Button in the GUI. It basically removes
    # the label (if visible) which shows whether the
    # entered string is correct or incorrect.
    if flag == 1:
        verify_label.grid_forget()

    # Removing the contents of the input box.
    entry.delete(0, END)

    # Generating a random string for the Captcha
    random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=6))

    # Creating a Captcha Image
    image_captcha = ImageCaptcha(width=250, height=125)
    image_generated = image_captcha.generate(random_string)
    image_display = ImageTk.PhotoImage(Image.open(image_generated))

    # Removing the previous Image (if present) and
    # displaying a new one.
    image_label.grid_forget()
    image_label = Label(root, image=image_display)
    image_label.grid(row=1, column=0, columnspan=2,
                     padx=10)

 

Defining the Check Function

The check function basically compares the two strings passed to it and it displays the result in the verify_label.

It begins by defining the global variables, followed by removing the verify_label if it’s present. Then it converts both the strings passed to it into lowercase and compares them. If they are the same, then “Verified” is displayed inside the verify_label, otherwise, “Incorrect!” is displayed and after that, the createImage function is called so that a new Captcha image is displayed.

def check(x, y):
    """
    Defining the method check() which will check
    whether the string entered by the user matches
    with the randomly generated string. If there is
    a match then "Verified" pops up in the window.
    Otherwise, "Incorrect!" pops up and a new Captcha
    Image is generated for the user to try again.
    """

    # Making the scope of the below mentioned
    # variables because their values are accessed
    # globally in this script.
    global verify_label

    verify_label.grid_forget()

    if x.lower() == y.lower():
        verify_label = Label(master=root,
                             text="Verified",
                             font="Arial 15",
                             bg='#ffe75c',
                             fg="#00a806"
                             )
        verify_label.grid(row=0, column=0, columnspan=2, pady=10)
    else:
        verify_label = Label(master=root,
                             text="Incorrect!",
                             font="Arial 15",
                             bg='#ffe75c',
                             fg="#fa0800"
                             )
        verify_label.grid(row=0, column=0, columnspan=2, pady=10)
        createImage()

Main Driver Code

We set the title as “Image Captcha” and then configure the background color. Then, we initialize the labels to be used. After that, we add the TextBox followed by a call to createImage. Then, we add the Reload Button and Submit Button to the window. Finally, we loop over the GUI window through .mainloop() method.

if __name__ == "__main__":
    # Initializing Tkinter by creating a root widget,
    # setting Title and Background Color
    root = Tk()
    root.title('Image Captcha')
    root.configure(background='#ffe75c')

    # Initializing the Variables to be defined later
    verify_label = Label(root)
    image_label = Label(root)

    # Defining the Input Box and placing it in the window
    entry = Entry(root, width=10, borderwidth=5,
                  font="Arial 15", justify="center")
    entry.grid(row=2, column=0)

    # Creating an Image for the first time.
    createImage()

    # Defining the path for the reload button image
    # and using it to add the reload button in the
    # GUI window
    path = 'ENTER THE PATH OF THE RELOAD BUTTON IMAGE'
    reload_img = ImageTk.PhotoImage(Image.open(path).resize((32, 32), Image.ANTIALIAS))
    reload_button = Button(image=reload_img, command=lambda: createImage(1))
    reload_button.grid(row=2, column=1, pady=10)

    # Defining the submit button
    submit_button = Button(root, text="Submit", font="Arial 10", command=lambda: check(entry.get(), random_string))
    submit_button.grid(row=3, column=0, columnspan=2, pady=10)
    root.bind('<Return>', func=lambda Event: check(entry.get(), random_string))

    # This makes the program loops till the user
    # doesn't close the GUI window
    root.mainloop()

Complete Python Code

# Importing the Required Libraries
import random
import string
from tkinter import Tk, Label, Entry, Button, END
from PIL import ImageTk, Image
from captcha.image import ImageCaptcha


def createImage(flag=0):
    """
    Defining the method createImage() which will create
    and generate a Captcha Image based on a randomly
    generated strings. The Captcha Image generated is then
    incorporated into the GUI window we have designed.
    """
    global random_string
    global image_label
    global image_display
    global entry
    global verify_label

    # The if block below works only when we press the
    # Reload Button in the GUI. It basically removes
    # the label (if visible) which shows whether the
    # entered string is correct or incorrect.
    if flag == 1:
        verify_label.grid_forget()

    # Removing the contents of the input box.
    entry.delete(0, END)

    # Generating a random string for the Captcha
    random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=6))

    # Creating a Captcha Image
    image_captcha = ImageCaptcha(width=250, height=125)
    image_generated = image_captcha.generate(random_string)
    image_display = ImageTk.PhotoImage(Image.open(image_generated))

    # Removing the previous Image (if present) and
    # displaying a new one.
    image_label.grid_forget()
    image_label = Label(root, image=image_display)
    image_label.grid(row=1, column=0, columnspan=2,
                     padx=10)


def check(x, y):
    """
    Defining the method check() which will check
    whether the string entered by the user matches
    with the randomly generated string. If there is
    a match then "Verified" pops up in the window.
    Otherwise, "Incorrect!" pops up and a new Captcha
    Image is generated for the user to try again.
    """

    # Making the scope of the below mentioned
    # variables because their values are accessed
    # globally in this script.
    global verify_label

    verify_label.grid_forget()

    if x.lower() == y.lower():
        verify_label = Label(master=root,
                             text="Verified",
                             font="Arial 15",
                             bg='#ffe75c',
                             fg="#00a806"
                             )
        verify_label.grid(row=0, column=0, columnspan=2, pady=10)
    else:
        verify_label = Label(master=root,
                             text="Incorrect!",
                             font="Arial 15",
                             bg='#ffe75c',
                             fg="#fa0800"
                             )
        verify_label.grid(row=0, column=0, columnspan=2, pady=10)
        createImage()


if __name__ == "__main__":
    # Initializing Tkinter by creating a root widget,
    # setting Title and Background Color
    root = Tk()
    root.title('Image Captcha')
    root.configure(background='#ffe75c')

    # Initializing the Variables to be defined later
    verify_label = Label(root)
    image_label = Label(root)

    # Defining the Input Box and placing it in the window
    entry = Entry(root, width=10, borderwidth=5,
                  font="Arial 15", justify="center")
    entry.grid(row=2, column=0)

    # Creating an Image for the first time.
    createImage()

    # Defining the path for the reload button image
    # and using it to add the reload button in the
    # GUI window
    path = 'ENTER THE PATH OF THE RELOAD BUTTON IMAGE'
    reload_img = ImageTk.PhotoImage(Image.open(path).resize((32, 32), Image.ANTIALIAS))
    reload_button = Button(image=reload_img, command=lambda: createImage(1))
    reload_button.grid(row=2, column=1, pady=10)

    # Defining the submit button
    submit_button = Button(root, text="Submit", font="Arial 10", command=lambda: check(entry.get(), random_string))
    submit_button.grid(row=3, column=0, columnspan=2, pady=10)
    root.bind('<Return>', func=lambda Event: check(entry.get(), random_string))

    # This makes the program loops till the user
    # doesn't close the GUI window
    root.mainloop()

Inputs and Outputs:

The GUI Window:

Entering Incorrect Letters:

Entering Correct Letters:

Pressing Reload Button:

Thank you for devoting your valuable time to reading this article. You may check out these other articles as well:

4 responses to “Image Captcha with GUI (Tkinter) | Python”

  1. Sujal Negi says:

    Traceback (most recent call last):
    File “C:\Users\HP\AppData\Local\Programs\Python\Python39\awsdfghjgf.py”, line 107, in
    reload_img = ImageTk.PhotoImage(Image.open(path).resize((32, 32), Image.ANTIALIAS))
    File “C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\site-packages\PIL\Image.py”, line 2912, in open
    fp = builtins.open(filename, “rb”)
    FileNotFoundError: [Errno 2] No such file or directory: ‘ENTER THE PATH OF THE RELOAD BUTTON IMAGE’

    I found above error please help

  2. Karan Trehan says:

    Hey Sujal,
    Did you give the path of the reload button image?
    If not, I suggest you download any Reload Button Image from the Internet, and then replace ENTER THE PATH OF THE RELOAD BUTTON IMAGE with the path of the downloaded image.

  3. Harish Rokhade says:

    Hello Sujal,
    Can you please send the code changes that u have done. I am not getting it .

Leave a Reply

Your email address will not be published. Required fields are marked *