All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.simiacryptus.mindseye.texture_generation.StyleSurvey Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
/*
 * Copyright (c) 2019 by Andrew Charneski.
 *
 * The author licenses this file to you under the
 * Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance
 * with the License.  You may obtain a copy
 * of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.simiacryptus.mindseye.texture_generation;

import com.simiacryptus.mindseye.ImageScript;
import com.simiacryptus.mindseye.applications.ArtistryUtil;
import com.simiacryptus.mindseye.applications.ColorTransfer;
import com.simiacryptus.mindseye.applications.ImageArtUtil;
import com.simiacryptus.mindseye.applications.TextureGeneration;
import com.simiacryptus.mindseye.lang.Tensor;
import com.simiacryptus.mindseye.lang.cudnn.Precision;
import com.simiacryptus.mindseye.models.CVPipe_VGG19;
import com.simiacryptus.mindseye.test.TestUtil;
import com.simiacryptus.notebook.NotebookOutput;

import javax.annotation.Nonnull;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * The type Hi def.
 */
public abstract class StyleSurvey extends ImageScript {

  public final double coeff_style_mean;
  /**
   * The Coeff style bandCovariance.
   */
  public final double coeff_style_cov;
  /**
   * The Style sources.
   */
  public final String[] styleSources;
  private final double plasma_intensity;
  private final int style_resolution;
  private final String[] text;
  private final int padding;
  private final Color color;
  private final String fontName;
  private final int style;
  /**
   * The Dream coeff.
   */
  public double dreamCoeff;
  double aspect_ratio;
  Precision precision = Precision.Float;

  public StyleSurvey(
      final double coeff_style_mean,
      final double coeff_style_cov,
      final double dreamCoeff,
      final int style_resolution,
      final int padding,
      final String fontName,
      final int style,
      final Color fontColor,
      String[] text,
      final double aspect_ratio,
      final double plasma_intensity,
      final String... styleSources
  ) {
    this.coeff_style_mean = coeff_style_mean;
    this.coeff_style_cov = coeff_style_cov;
    this.dreamCoeff = dreamCoeff;
    this.style_resolution = style_resolution;
    this.styleSources = styleSources;
    this.text = text;
    this.padding = padding;
    color = fontColor;
    this.fontName = fontName;
    this.style = style;
    this.aspect_ratio = aspect_ratio;
    this.plasma_intensity = plasma_intensity;
  }

  public void accept(@Nonnull NotebookOutput log) {
    int index = 0;
    List filteredSources = log.subreport("load_styles", subreport -> {
      return Arrays.stream(styleSources).filter(styleSource -> {
        try {
          subreport.p(subreport.png(ArtistryUtil.load(styleSource, style_resolution), "Style Image"));
          return true;
        } catch (Throwable e) {
          e.printStackTrace(System.out);
          return false;
        }
      }).collect(Collectors.toList());
    });
    for (final String styleSource : filteredSources) {
      for (final String txt : text) {
        int seedResolution = 200;
        if (!txt.isEmpty()) {
          fontSurvey(log, txt, seedResolution);
        }
        BufferedImage initialImage = getInitialImage(txt, padding, style, color, fontName, seedResolution);
        final AtomicReference canvas = new AtomicReference<>(Tensor.fromRGB(initialImage));
        canvas.set(log.subreport("Color_Space_Analog", subreport -> {
          ColorTransfer contentColorTransform = new ColorTransfer.VGG19() {
          }.setOrtho(false).setUnit(false);
          //colorSyncContentCoeffMap.set(CVPipe_VGG19.Layer.Layer_1a, 1e-1);
          int colorSyncResolution = 600;
          Tensor resizedCanvas = Tensor.fromRGB(TestUtil.resize(
              canvas.get().toImage(),
              colorSyncResolution,
              (int) (aspect_ratio * colorSyncResolution)
          ));
          final ColorTransfer.StyleSetup styleSetup = ImageArtUtil.getColorAnalogSetup(
              Arrays.asList(styleSource),
              precision,
              resizedCanvas,
              ImageArtUtil.getStyleImages(
                  new String[]{styleSource},
                  new HashMap<>(),
                  colorSyncResolution, (int) (aspect_ratio * colorSyncResolution)
              ),
              CVPipe_VGG19.Layer.Layer_0
          );
          contentColorTransform.transfer(
              subreport,
              resizedCanvas,
              styleSetup,
              getTrainingMinutes(),
              contentColorTransform.measureStyle(styleSetup),
              getMaxIterations(),
              isVerbose()
          );
          return contentColorTransform.forwardTransform(canvas.get());
        }));
        Tensor subresult = log.subreport("Rendering_" + index++, subreport -> {
          subreport.p(subreport.png(ArtistryUtil.load(styleSource, style_resolution), "Style Image"));
          canvas.set(tiledTexturePaintingPhase(subreport, canvas.get().copy(), styleSource));
          return canvas.get();
        });
        log.p(log.png(subresult.toImage(), txt));
      }
    }
  }

  public Object fontSurvey(@Nonnull final NotebookOutput log, final String txt, final int textResolution) {
    return log.subreport("Fonts", subreport -> {
      Arrays.stream(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames())
          .filter(x -> !x.equals("EmojiOne Color"))
          .forEach(fontname -> {
            subreport.p(fontname);
            subreport.p(subreport.png(getInitialImage(txt, padding, Font.PLAIN, color, fontname, textResolution), fontname));
            subreport.p(subreport.png(getInitialImage(txt, padding, Font.ITALIC, color, fontname, textResolution), fontname));
            subreport.p(subreport.png(getInitialImage(txt, padding, Font.BOLD, color, fontname, textResolution), fontname));
          });
      return null;
    });
  }

  public Tensor tiledTexturePaintingPhase(
      final NotebookOutput log,
      Tensor canvas,
      final String styleSource
  ) {
    setMaxIterations(20);
    int styleFactor = style_resolution / 600;

    this.dreamCoeff *= 1e1;
    canvas = tiledTexturePaintingPhase(log, canvas.copy(), 200, getStyleSetup(
        styleSource, 200 * styleFactor,
        CVPipe_VGG19.Layer.Layer_0,
        CVPipe_VGG19.Layer.Layer_1d,
        CVPipe_VGG19.Layer.Layer_1e
    ));
    canvas = tiledTexturePaintingPhase(log, canvas.copy(), 250, getStyleSetup(
        styleSource, 250 * styleFactor,
        CVPipe_VGG19.Layer.Layer_0,
        CVPipe_VGG19.Layer.Layer_1d,
        CVPipe_VGG19.Layer.Layer_1e
    ));
    canvas = tiledTexturePaintingPhase(log, canvas.copy(), 300, getStyleSetup(
        styleSource, 300 * styleFactor,
        CVPipe_VGG19.Layer.Layer_1b,
        CVPipe_VGG19.Layer.Layer_1c,
        CVPipe_VGG19.Layer.Layer_1d
    ));
    canvas = tiledTexturePaintingPhase(log, canvas.copy(), 350, getStyleSetup(
        styleSource, 350 * styleFactor,
        CVPipe_VGG19.Layer.Layer_1b,
        CVPipe_VGG19.Layer.Layer_1c,
        CVPipe_VGG19.Layer.Layer_1d
    ));
    canvas = tiledTexturePaintingPhase(log, canvas.copy(), 400, getStyleSetup(
        styleSource, 400 * styleFactor,
        CVPipe_VGG19.Layer.Layer_0,
        CVPipe_VGG19.Layer.Layer_1b,
        CVPipe_VGG19.Layer.Layer_1c
    ));
    this.dreamCoeff /= 1e1;

    canvas = tiledTexturePaintingPhase(log, canvas.copy(), 500, getStyleSetup(
        styleSource, 500 * styleFactor,
        CVPipe_VGG19.Layer.Layer_1a,
        CVPipe_VGG19.Layer.Layer_1b,
        CVPipe_VGG19.Layer.Layer_1c
    ));
    canvas = tiledTexturePaintingPhase(log, canvas.copy(), 550, getStyleSetup(
        styleSource, 550 * styleFactor,
        CVPipe_VGG19.Layer.Layer_1a,
        CVPipe_VGG19.Layer.Layer_1b,
        CVPipe_VGG19.Layer.Layer_1c
    ));
    //this.dreamCoeff /= 1e1;
    canvas = tiledTexturePaintingPhase(log, canvas.copy(), 600, getStyleSetup(
        styleSource, 600 * styleFactor,
        CVPipe_VGG19.Layer.Layer_0,
        CVPipe_VGG19.Layer.Layer_1a,
        CVPipe_VGG19.Layer.Layer_1b,
        CVPipe_VGG19.Layer.Layer_1c
    ));
    return canvas;
  }

  @Nonnull
  public TextureGeneration.StyleSetup getStyleSetup(
      final String styleSource, final int style_resolution,
      final CVPipe_VGG19.Layer... layers
  ) {
    final Map, TextureGeneration.StyleCoefficients> styles = TestUtil.buildMap(x -> {
      TextureGeneration.StyleCoefficients styleCoefficients = new TextureGeneration.StyleCoefficients<>(
          TextureGeneration.CenteringMode.Origin);
      for (final CVPipe_VGG19.Layer layer : layers) {
        styleCoefficients.set(
            layer,
            coeff_style_mean,
            coeff_style_cov,
            dreamCoeff
        );
      }
      x.put(
          Arrays.asList(styleSource),
          styleCoefficients
      );
    });
    return new TextureGeneration.StyleSetup<>(
        precision,
        TestUtil.buildMap(y -> y.putAll(
            styles.keySet().stream().flatMap(
                x -> x.stream())
                .collect(Collectors.toMap(
                    x -> x,
                    file -> ArtistryUtil.load(
                        file,
                        style_resolution
                    )
                )))),
        styles
    );
  }

  public Tensor tiledTexturePaintingPhase(
      final NotebookOutput log,
      Tensor canvas,
      final int width,
      final TextureGeneration.StyleSetup styleSetup
  ) {
    TextureGeneration.VGG19 textureGeneration = new TextureGeneration.VGG19();
    textureGeneration.parallelLossFunctions = true;
    int height = (int) (aspect_ratio * width);
    textureGeneration.setTiling((int) Math.max(Math.min((2.0 * Math.pow(600, 2)) / (width * height), 9), 2));
    canvas = (Tensor.fromRGB(TestUtil.resize(canvas.toImage(), width, height)));
    log.p("Input Parameters:");
    log.eval(() -> {
      return ArtistryUtil.toJson(styleSetup);
    });
    return (textureGeneration.optimize(
        log,
        textureGeneration.measureStyle(styleSetup), canvas,
        getTrainingMinutes(),
        getMaxIterations(), isVerbose(), styleSetup.precision
    ));
  }

  @Nonnull
  public BufferedImage getInitialImage(
      final String text,
      final int padding,
      final int style,
      final Color color,
      final String fontName, final int resolution
  ) {
    if (text.isEmpty()) {
      return ArtistryUtil.paint_Plasma(3, 1000.0, 1.1, resolution, (int) (aspect_ratio * resolution))
          .map(x -> x * plasma_intensity).toImage();
    }
    BufferedImage image = ArtistryUtil.paint_Plasma(3, 1000.0, 1.1, resolution).toImage();
    Font font = ImageArtUtil.fitSize(text, resolution, padding, fontName, style);
    Rectangle2D bounds = ImageArtUtil.measure(font, text);
    aspect_ratio = (2 * padding + bounds.getHeight()) / (2 * padding + bounds.getWidth());
    image = ArtistryUtil.paint_Plasma(3, 1000.0, 1.1, resolution, (int) (aspect_ratio * resolution))
        .map(x -> x * plasma_intensity).toImage();
    Graphics2D graphics = (Graphics2D) image.getGraphics();
    graphics.setColor(color);
    graphics.setFont(font);
    int y = (int) ((Rectangle2D.Double) bounds).y + padding;
    for (final String line : text.split("\n")) {
      Rectangle2D stringBounds = graphics.getFontMetrics().getStringBounds(line, graphics);
      double centeringOffset = (bounds.getWidth() - stringBounds.getWidth()) / 2;
      graphics.drawString(line, (int) (padding + centeringOffset), y);
      y += stringBounds.getHeight();
    }
    return image;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy