1. AnimatedRotor
  2. Resolution 300.0
    1. 1
    2. 2
    3. 3
    4. 5

AnimatedRotor

Paints a series of images, each to match the content of one while in the style of another using:
  1. Random noise initialization
  2. Standard VGG16 layers
  3. Operators to match content and constrain and enhance style
  4. Progressive resolution increase
  5. Rotational symmerty constraint caused by a kaliedoscopic image layer
The parameters for each frame are fixed, but due to the random initialization and loose constraints we can achive a dynamic effect.

Code from AnimatedRotor.scala:74 executed in 0.01 seconds (0.000 gc):

    () => {
      implicit val _ = log
      // First, basic configuration so we publish to our s3 site
      log.setArchiveHome(URI.create(s"s3://$s3bucket/${getClass.getSimpleName.stripSuffix("$")}/${log.getId}/"))
      log.onComplete(() => upload(log): Unit)
      // Fetch input images (user upload prompts) and display rescaled copies
      log.p(log.jpg(ImageArtUtil.load(log, styleUrl, (maxResolution * Math.sqrt(magnification)).toInt), "Input Style"))
      log.p(log.jpg(ImageArtUtil.load(log, contentUrl, maxResolution), "Input Content"))
      val canvases = (1 to frames).map(_ => new AtomicReference[Tensor](null)).toList
      // Execute the main process while registered with the site index
      val registration = registerWithIndexGIF_Cyclic(canvases.map(_.get()))
      try {
        paintBisection(contentUrl, initUrl, canvases, (1 to frames).map(f => f.toString -> {
          new VisualStyleContentNetwork(
            styleLayers = List(
              // We select all the lower-level layers to achieve a good balance between speed and accuracy.
              VGG16.VGG16_0,
              VGG16.VGG16_1a,
              VGG16.VGG16_1b1,
              VGG16.VGG16_1b2,
              VGG16.VGG16_1c1,
              VGG16.VGG16_1c2,
              VGG16.VGG16_1c3
            ),
            styleModifiers = List(
              // These two operators are a good combination for a vivid yet accurate style
              new GramMatrixEnhancer(),
              new MomentMatcher()
            ),
            styleUrl = List(styleUrl),
            contentLayers = List(
              VGG16.VGG16_1b2
            ),
            contentModifiers = List(
              new ContentMatcher()
            ),
            magnification = magnification,
            // Our optimization network should be built with a kaliedoscope appended to the canvas
            viewLayer = dims => getKaleidoscope(dims.toArray)
          )
        }).toList, new BasicOptimizer {
          override val trainingMinutes: Int = 60
          override val trainingIterations: Int = 30
          override val maxRate = 1e9
          // The canvas result should be processed by the kaliedoscope
          override def renderingNetwork(dims: Seq[Int]) = getKaleidoscope(dims.toArray).copyPipeline()
          // By default, we use a trust region that constrains the canvas pixel values from 0-256.
          // This conflicts with using a kaliedoscope, whose output is bounded and input may be out of that range.
          override def trustRegion(layer: Layer): TrustRegion = null
        }, x => new PipelineNetwork(1), keyframes, new GeometricSequence {
          override val min: Double = minResolution
          override val max: Double = maxResolution
          override val steps = AnimatedRotor.this.steps
        }.toStream.map(_.round.toDouble): _*)
        null
      } finally {
        registration.foreach(_.stop()(s3client, ec2client))
      }
    }

Returns:

    <function0>

Input Style

Input Content

Resolution 300.0

1

Subreport: Optimization

2

Subreport: Optimization

3

Subreport: Optimization

5

Subreport: Optimization