Attempt for a "Marker Drawing" Filter

Yesterday, I did a little experiment with spline tracing, and I came up with an algorithm that I quite like, which transforms an image into a felt-tip pen drawing, but it’s still a bit messy to make it into a usable filter for G’MIC-Qt.
I’m copying and pasting the code here, along with some of the results I got. I’m not sure I’ll have time to do anything with it in the next few days.

Code:

marker :
  sp colorful,1024 => img
  +diffusiontensors 0,0.85,0,1,0 channels. 0,3 f. "[ i0,i1,i1,i2 ]" => tensors
  +b[img] 1 gradient_norm. n. 0,1 => gnorm
  {img,[w,h,1,1]} => shape
  +f[img] 255 => canvas

  w[canvas]

  do {
    170,1,1,1,":
      spline(_X0,_U0,_X1,_U1) = (
        ref(_X0,spline_X0); ref(_U0,spline_U0); ref(_X1,spline_X1); ref(_U1,spline_U1);
        spline_C = transpose(solve([ 0,0,0,1,1,1,1,1,0,0,1,0,3,2,1,0 ],[ spline_X0,spline_X1,spline_U0,spline_U1 ],2),2);
        spline_N = ceil(norm(spline_X1 - spline_X0) + 0.5*(norm(spline_U0) + norm(spline_U1)))/5;
        repeat (spline_N,spline_n,
          spline_t = lerp(0,1,spline_n/(spline_N - 1));
          spline_X = mul(spline_C,[ spline_t^3, spline_t^2, spline_t, 1 ],1);
          spline_U = mul(spline_C,[ 3*spline_t^2, 2*spline_t, 1, 0 ],1);
          spline_ang = atan2(spline_U[1],spline_U[0]);
          ellipse(#$canvas,round(spline_X),7,4,spline_ang,opac,RGB);
          i(#$shape,round(spline_X)) = 1;
        );
      );

      const N = 100;
      const opac = max(0.005,0.075*1.001^-$>);
      Xs = vector(#2*N,-1);
      Us = vector(#2*N,-1);

      # Randomly pick a starting location and a starting orientation.
      do (
        X = X0 = v([w#$img,h#$img] - 1),
        i(#$shape,X); # || i(#$gnorm,X)<1.1^-$>;
      );
      U = U0 = cexp([0,u(360°)]);
      RGB = I(#$img,X);
      copy(Xs[0],X0);
      copy(Us[0],U0);

      # Draw streamline.
      ind = 1;
      nb_cross = 0;
      repeat (512,
        T = I(#$tensors,X,1,1);
        U = T*U;
        U/=max(1e-8,abs(U));
        nX = X + U;
        i(#$shape,nX,1)?++nb_cross;
        nb_cross>40?break();
        X = nX;
        copy(Xs[2*ind],X);
        copy(Us[2*ind],U);
        ind = (ind + 1)%N;
      );

      pind = (ind + 1)%N;
      Xp = Xs[2*pind,2];
      Up = Us[2*pind,2];
      Xp[0]>=0?(
        spline(Xp,100*unitnorm(Up),X,100*unitnorm(U));
      );

      " rm.
    w[canvas]
#    +rs[canvas] 50% on. frame.jpg,$> rm.
  } while {*}

Results:

Algorithm animated:

4 Likes

Nice results! Math is awesome! :nerd_face:

1 Like

Very cool :slight_smile: I like artsy filters.
How does it behave on flat regions/ straight objects?
I wonder if it’s possible to have it follow the object’s natural shapes. Draw splines on round(er) regions (according to shading/bump?) and “somewhat” straight lines on flat surfaces, etc. That’s probably asking for a lot though :stuck_out_tongue:

Pushed as a new filter for G’MIC-QT (Filter Artistic / Marker Drawing).
Quite fun filter to play with!


Guys, this filter is so cool!
Really happy to see how it turned out!

Thank You so much for this incredibly interesting new art filter.