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 = 
  FE`Evaluate[FEPrivate`GetPopupList["MenuListFonts"]] /. 
   Rule[x_, y_] :> y;
effectslist = ImageEffect[];
captcha := With[{key = RandomChoice[WordList["CommonWords"], 2]},
  Print@StringJoin@Riffle[key, " "];
  With[{font = RandomChoice[fontlist]},
            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:

enter image description here

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


1 Answer 1


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

enter image description here

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]

enter image description here

Lets add some additional distortion.

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

enter image description here

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

enter image description here

img = Import["https://i.sstatic.net/9UlVv.png"] 

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

enter image description here

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

  • $\begingroup$ That image looks great! $\endgroup$
    – Jason B.
    Commented Apr 26, 2016 at 18:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.