DEV Community

Mageshwaran
Mageshwaran

Posted on • Edited on

Captcha image generator

We will build a logic to create some random captcha image using python with the help of pillow package.

For more detailed reference about pillow check this.

install this package using this command

   pip install pillow
Enter fullscreen mode Exit fullscreen mode

To learn more about virtual environment

Create new image

this piece of code will create a white image with 90X60 and saved a blank_image.png

   from PIL import Image
   img = Image.new('RGB', (90, 60), color = 'white')
   img.save('blank_image.png')
Enter fullscreen mode Exit fullscreen mode

blank_image.png
blank_image.png

Draw text on image

now we created a image and saved it, lets add some text to it

   from PIL import Image, ImageDraw
   draw = ImageDraw.Draw(img)
   draw.text((20,20), "Hello", fill=(38, 38, 38))
   img.save('blank_image.png')
Enter fullscreen mode Exit fullscreen mode

Hello is written in img object at poin 10X10
Alt Text

Draw lines

Let draw some line on the image

   draw.line((40,30, 150,300), fill=120, width=1)
   draw.line((20,30, 30,20), fill=88, width=2)
Enter fullscreen mode Exit fullscreen mode

fill is the color and you set the width size,
(40,30) is the starting point for line 1 and ends at (150,300).
You can notice that the end point is larger than the image size, it will be omitted.

Same as line 1, line 2 starts at (20,30) and ends in (30,20)
Alt Text

Draw points

Let add some more stuff
pass points as python tuples of tuples to draw points in the image

   draw.point(((30, 40), (10, 20), (14, 25), (35, 10), (14, 28), (17, 25)), fill="black")
Enter fullscreen mode Exit fullscreen mode

this one will throws the dot points in the image at the given XY coordinates.
Alt Text

Generate the captcha string

This same logic is used in Url Shortener, you can check it here

Build Url Shortener API In Django - Redis

random_string function generate a random string of length 5, you can adjust it.

import string, random 

# generate thr random captcha string
def random_string():
    # hash length
    N = 5
    s = string.ascii_uppercase + string.ascii_lowercase + string.digits
    # generate a random string of length 5
    random_string = ''.join(random.choices(s, k=N))
    return random_string
Enter fullscreen mode Exit fullscreen mode

Python lambda function

what is lambda?
Is a special function with one line, and with one expression. It can get multiple arguments.

# Normal funtion
def square(a):
    return a*a

square(5) ---> 25

# lambda funtion
square = lambda a: a*a
square(5) ---> 25
Enter fullscreen mode Exit fullscreen mode

lambda function to get the random location in the image

   # lambda function - used to pick a random loaction in image
getit = lambda : (random.randrange(5, 85),random.randrange(5, 55))
Enter fullscreen mode Exit fullscreen mode

this will spite out the random value between 5 and 84,
Note: 85 not taken

   random.randrange(5, 85)
Enter fullscreen mode Exit fullscreen mode

values for colors which will be randomly picked

   # pick a random colors for points
   colors = ["black","red","blue","green",(64, 107, 76),(0, 87, 128),(0, 3, 82)]
   fill_color = [120,145,130,89,58,50,75,86,98,176,]
   # pick a random colors for lines
   fill_color = [(64, 107, 76),(0, 87, 128),(0, 3, 82),(191, 0, 255),(72, 189, 0),(189, 107, 0),(189, 41, 0)]
Enter fullscreen mode Exit fullscreen mode

To get a random value from list, this will get a random color value one

   random.choice(colors)
Enter fullscreen mode Exit fullscreen mode

Full logic to generate the captcha image

from PIL import Image, ImageDraw, ImageFont
import string, random 

# generate thr random captcha string
def random_string():
    # hash length
    N = 5
    s = string.ascii_uppercase + string.ascii_lowercase + string.digits
    # generate a random string of length 5
    random_string = ''.join(random.choices(s, k=N))
    return random_string

# lambda function - used to pick a random loaction in image
getit = lambda : (random.randrange(5, 85),random.randrange(5, 55))

# pick a random colors for points
colors = ["black","red","blue","green",(64, 107, 76),(0, 87, 128),(0, 3, 82)]

# fill_color = [120,145,130,89,58,50,75,86,98,176,]
# pick a random colors for lines
fill_color = [(64, 107, 76),(0, 87, 128),(0, 3, 82),(191, 0, 255),(72, 189, 0),(189, 107, 0),(189, 41, 0)]

# generate thr random captcha string
def random_string():
    # hash length
    N = 5
    s = string.ascii_uppercase + string.ascii_lowercase + string.digits
    # generate a random string of length 5
    random_string = ''.join(random.choices(s, k=N))
    return random_string

# generate the captcha image
def gen_captcha_img():
    # create a img object
    img = Image.new('RGB', (90, 60), color="white")
    draw = ImageDraw.Draw(img)

    # get the random string
    captcha_str = random_string()
    # get the text color
    text_colors = random.choice(colors)
    font_name = "fonts/SansitaSwashed-VariableFont_wght.ttf"
    font = ImageFont.truetype(font_name, 18)
    draw.text((20,20), captcha_str, fill=text_colors, font=font)

    # draw some random lines
    for i in range(5,random.randrange(6, 10)):
        draw.line((getit(), getit()), fill=random.choice(fill_color), width=random.randrange(1,3))

    # draw some random points
    for i in range(10,random.randrange(11, 20)):
        draw.point((getit(), getit(), getit(), getit(), getit(), getit(), getit(), getit(), getit(), getit()), fill=random.choice(colors))

    # save image in captcha_img directory
    img.save("captcha_img/"+ captcha_str +".png")

    return True
Enter fullscreen mode Exit fullscreen mode

Alt Text

                          **WE MADE IT** 🥳🥳🥳
Enter fullscreen mode Exit fullscreen mode

Alt Text

You will notice the code for i in range(5,random.randrange(6, 10)): which is used to randomise the line and points in each new image.
font used in this is from google fonts
https://fonts.google.com/specimen/Sansita+Swashed

Note: To validate the value(Backend) in the string you can store the string in the session or you can use your own way.
To generate more detailed image used some small images with different shapes in it and throws it randomly.

More articles

Build Url Shortener API In Django - Redis

Scrape IMDB movie rating and details using python

Build a News app using django - App like google news

Django News App Deployment On Heroku

Thanks you, have a great day ahead.🤪😎

Top comments (0)