How can I use Mathematica to make a captcha image?

This was inspired by this post which is about the serious business of website deployment in the Wolfram Cloud, and interaction with Google's reCaptcha system.

I started thinking of how to make those neat (and annoying) images that feature some variant of scrambled text that you have to type in to prove that you are human.

There are plenty of posts on the web about using Mathematica to beat captchas via OCR and wavelet transforms, here is an example.

This is what I've come up with (with a nod to kglr for showing how to grab the font information),

fontlist =
FEEvaluate[FEPrivateGetPopupList["MenuListFonts"]] /.
Rule[x_, y_] :> y;
effectslist = ImageEffect[];
captcha := With[{key = RandomChoice[WordList["CommonWords"], 2]},
Print@StringJoin@Riffle[key, " "];
With[{font = RandomChoice[fontlist]},
(Rotate[
Style[#, FontFamily -> font, RandomColor[]]
, RandomReal[{-.5, .5}]] &) /@ #] & /@
(Characters /@
key) // Grid // Rasterize[#, ImageSize -> 600] & //

ImageEffect[#, RandomChoice[effectslist]] &
]


It's limited to applying a different font to two different dictionary words and then giving each letter a random color and orientation, and finally applying an image transformation chosen from a non-exhaustive list. But I feel like the results are lacking, and they would be very easy to defeat via the methods described above:

Captchas I see on the web often use a swirling effect, or a rippling effect, and some nonlinear distortions, but I don't know how to do that in Mathematica

Here is something I tried based on Simon's answer to How to create a new “person curve”?

I am starting from a text.

pic = Rasterize[Style["Captcha", FontFamily -> "Sans"], ImageSize -> 300] // Image


Now introducing Simon functions

param[x_, m_, t_] := Module[{f, n = Length[x], nf},
f = Chop[Fourier[x]][[;; Ceiling[Length[x]/2]]];
nf = Length[f];
Total[Rationalize[2 Abs[f]/Sqrt[n] Sin[Pi/2 - Arg[f]
+ 2. Pi Range[0, nf - 1] t], .01][[;; Min[m, nf]]]]]

tocurve[Line[data_], m_, t_] := param[#, m, t] & /@ Transpose[data]

lines = Cases[Normal@ListContourPlot[Reverse@ImageData[img],
Contours -> {0.5}], _Line, -1];


Evaluating this with 25 modes gives you

ParametricPlot[Evaluate[tocurve[#, 25, t] & /@ lines], {t, 0, 1},
Frame -> True, Axes -> False]


modes = 7;
distort[t_] := 20 Cos[t]
ParametricPlot[Evaluate[(tocurve[#, modes, t] + distort[t]) & /@ lines],
{t, 0, 1}, Frame -> True, Axes -> False]


You can always find a function which will give you better distortion. For better result you can play with separate alphabets and rotate or displace them as you wish.

To add more spice you can use ImageTransformation. Actually you can directly use it to your captha in the beginning. For example lets try the last part of your image

img = Import["http://i.stack.imgur.com/9UlVv.png"]

f[x_, y_] := {x + 10 Sin[.05 x], y + 5 Sin[.1 y]}
ImageTransformation[img, f @@ # &, DataRange -> Full]


And again, you can define any transformation function (f[x_,y_]) you want.

• That image looks great! – Jason B. Apr 26 '16 at 18:22