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
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')
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')
Hello is written in img object at poin 10X10

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)
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)

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")
this one will throws the dot points in the image at the given XY coordinates.

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
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
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))
this will spite out the random value between 5 and 84,
Note: 85 not taken
   random.randrange(5, 85)
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)]
To get a random value from list, this will get a random color value one
   random.choice(colors)
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
                          **WE MADE IT** 🥳🥳🥳
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.
 




 
    
Top comments (0)