mnowotka
mnowotka

Reputation: 17258

Python CAPTCHA-like image disortion

I would like to disort some images the same way standard CAPTCHA disorts fonts. How would I achieve it in python? What libraries/algorithms I should use? Any proof-of-concept?

DISCLAIMER: I was googling for some time before I asked this question but I couldn't find any satisfying answer. I'm new to the field so I can't provide any code proving my 'research effort'...

Upvotes: 3

Views: 2969

Answers (4)

Arya-2790306
Arya-2790306

Reputation: 115

Distorting an image means shuffling of an pixel with any of its neighbouring pixel.

If algorithm shuffle a far pixel, distortion is high, and if a nearby pixel is shuffled distortion is low

I had worked on a similar problem few days ago, I've used PIL for this.

import math
from PIL import Image

img = Image.open('image.jpg')  #open a image
width ,height = img.size
img_data = img.load()          #loading it, for fast operation
output = Image.new('RGB',img.size,"gray")  #New image for putput
output_img = output.load()    #loading this also, for fast operation

pix=[0, 0]
delta_x = 40     #you can lower the delta for high distortion
delta_y = 90     #or you can higher the delta for low distortion

for x in range(width):
    for y in range(height):
        #following expression calculates the snuffling 
        x_shift, y_shift =  ( int(abs(math.sin(x)*width/delta_x)) ,
                              int(abs(math.tan(math.sin(y)))*height/delta_y))

        #checking bounds
        if x + x_shift < width:
            pix[0] = x + x_shift
        else:
            pix[0] = x
        if y + y_shift < height :
            pix[1] = y + y_shift
        else:
            pix[1] = y

        # do the shuffling
        output_img[x,y] = img_data[tuple(pix)]
#Saving the image
output.save('output.jpeg')

The following expression is the key here, you can modify or create any similar expression by doing little mathematics, although this may also suit you as it is.

x_shift, y_shift =  ( int(abs(math.sin(x)*width/delta_x)) ,
                              int(abs(math.tan(math.sin(y)))*height/delta_y))

I have a sample: Input imageenter image description here Output Imageenter image description here

I hope this helps.

Upvotes: 2

fasouto
fasouto

Reputation: 4511

You can adapt the code of django-simple-captcha, there's a function captcha_image in https://raw.github.com/mbi/django-simple-captcha/master/captcha/views.py that you can adapt easily.

Upvotes: 0

Alex I
Alex I

Reputation: 20317

I think you are looking for PyCaptcha http://svn.navi.cx/misc/trunk/pycaptcha/

The actual code to distort is here: http://svn.navi.cx/misc/trunk/pycaptcha/Captcha/Visual/Distortions.py

The work is done by PIL's transform function, like this:

image.transform(image.size, Image.MESH, mesh, self.filtering)

The rest of the code is there essentially to generate the mesh that is used.

Upvotes: 7

Faultier
Faultier

Reputation: 1326

put simple: you have an image, which is a 2D array, each array element represents a pixel. Distorting an image means, that you put some pixel value also to neighboring places where it has not been before.

To give you something like an example, I modified an example from the matplotlib; I relocate the regular x/y to an irregular spacing, thus, distorting the image. For captcha looks, you have to come up with some more creative remapping than I did. More professional would obviously be to just remap the values to the array to keep the regular spaced data.

So some fun is still left for you to play around (; Hope this helped you out as a starter.

import pylab as P
import numpy as N

# http://matplotlib.org/examples/images_contours_and_fields
# /pcolormesh_levels.html
dx, dy = 0.05, 0.05
y, x = N.mgrid[slice(1, 5 + dy, dy),
                slice(1, 5 + dx, dx)]
z = N.sin(x) ** 10 + N.cos(10 + y * x) * N.cos(x)

#distort from regular pixels to something else...
x1 = N.exp(x)  
y1 = N.sqrt(y)

P.figure()
P.pcolormesh(x,y,z)
P.figure()
P.pcolormesh(x1,y1,z)
P.show()

Upvotes: 2

Related Questions