12

I would like to write a Python script that would generate a 3D CAPTCHA like this one: teabag captcha

Which graphics libraries can I use?

Source: ocr-research.org.ua

Paul
  • 42,322
  • 15
  • 106
  • 123

4 Answers4

33

There are many approaches. I would personally create the image in Python Imaging Library using ImageDraw's draw.text, convert to a NumPy array (usint NumPy's asarray) then render with Matplotlib. (Requires Matplotlib maintenance package).

Full code (in 2.5):

import numpy, pylab
from PIL import Image, ImageDraw, ImageFont
import matplotlib.axes3d as axes3d

sz = (50,30)

img = Image.new('L', sz, 255)
drw = ImageDraw.Draw(img)
font = ImageFont.truetype("arial.ttf", 20)

drw.text((5,3), 'text', font=font)
img.save('c:/test.png')

X , Y = numpy.meshgrid(range(sz[0]),range(sz[1]))
Z = 1-numpy.asarray(img)/255

fig = pylab.figure()
ax = axes3d.Axes3D(fig)
ax.plot_wireframe(X, -Y, Z, rstride=1, cstride=1)
ax.set_zlim((0,50))
fig.savefig('c:/test2.png')

alt text

Obviously there's a little work to be done, eliminating axes, changing view angle, etc..

Community
  • 1
  • 1
Paul
  • 42,322
  • 15
  • 106
  • 123
4

Another binding to consider for rendering with opengl is pyglet. Its best feature is that it is just one download. I think it contains everything you need to implement what Anurag spells out.

I will caution you that what you're trying to do is not exactly a simple first project in 3d graphics. If this is your first exposure to OpenGL, consider a series of tutorials like NeHe Tutorials and other help from the OpenGL website.

goger
  • 583
  • 7
  • 15
2

I'm not sure I would bother with a full 3D library for what you have above. Just generate a matrix of 3D points, generate the text with something like PIL, scan over it to find which points on the grid are raised, pick a random camera angle and then project the points into a 2D image and draw them with PIL to the final image.

That being said... you may be able to use VPython if you don't want to do the 3D math yourself.

Branden Hall
  • 4,468
  • 18
  • 19
  • How do I "generate a matrix of 3d ponts"? –  Jun 20 '09 at 14:46
  • That would just be a list of tuples - each tuple would have 3 numbers - representing x, y and z. – Branden Hall Jun 20 '09 at 14:49
  • 1
    RobertW: Without any prior knowledge of 3D graphics at all this calls for quite a bit of readnig before you can try that one, I think. – Joey Jun 20 '09 at 14:50
  • yes , I would say you will need to implement whole matrix manipulations or vector rotations – Anurag Uniyal Jun 20 '09 at 14:51
  • I dont have knowledge of 3D graphics, but I do have much linear algebra knowledge. –  Jun 20 '09 at 15:01
  • It is true that it would require some basic knowledge of 3D to make this work, but I'm not sure that's a bad thing. These things will need to be generated on the fly, so the simpler the better. I just did a little bit of searching and found pyeuclid, a vector library for python that would do the job nicely. http://code.google.com/p/pyeuclid Essentially you would create a list of Vector3 points, and then create a Matrix4, apply some random rotations to it, and then multiply the vectors by the matrix. Then you handle the projection. – Branden Hall Jun 20 '09 at 15:04
  • For the projection bit, the wikipedia article on 3D projection gives you the basic equations you need. After that it's just a matter of applying them and fiddling with the angles of everything to make sure the CAPTCHA is always (human) readable. – Branden Hall Jun 20 '09 at 15:08
  • Yeah - If you have knowledge of linear algebra, then this shouldn't be terribly hard for you (and in fact, should be quite fun!). When I first learned linear I immediately started coding up basic 3D stuff. It's very cool to be able to apply more advanced math to problems you WANT to solve! – Branden Hall Jun 20 '09 at 15:26
1

Use Python bindings for OpenGL, http://pyopengl.sourceforge.net/.

Create a 2D image of white color text over a black surface using PIL. Make a 3D grid from this, increase z of point where color is white, maybe set z=color value, so by blurring the image you can get real curves in the z direction.

Create an OpenGL triangle from these points, use wireframe mode while rendering.

Grab the OpenGL buffer into an image, for example, http://python-opengl-examples.blogspot.com/2009/04/render-to-texture.html.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219