Giter VIP home page Giter VIP logo

texture-synthesis's Introduction

🎨 texture-synthesis

Embark Embark Crates.io Docs dependency status Build Status

A light Rust API for Multiresolution Stochastic Texture Synthesis [1], a non-parametric example-based algorithm for image generation.

The repo also includes multiple code examples to get you started (along with test images), and you can find a compiled binary with a command line interface under the release tab.

Also see our talk More Like This, Please! Texture Synthesis and Remixing from a Single Example which explains this technique and the background more in-depth:

Video thumbnail

Maintenance note

We at Embark are not actively using or developing these crates and would be open to transferring them to a maintainer or maintainers that would be more active. See #166.

Features and examples

1. Single example generation

Imgur

Generate similar-looking images from a single example.

use texture_synthesis as ts;

fn main() -> Result<(), ts::Error> {
    //create a new session
    let texsynth = ts::Session::builder()
        //load a single example image
        .add_example(&"imgs/1.jpg")
        .build()?;

    //generate an image
    let generated = texsynth.run(None);

    //save the image to the disk
    generated.save("out/01.jpg")
}

CLI

cargo run --release -- --out out/01.jpg generate imgs/1.jpg

You should get the following result with the images provided in this repo:

2. Multi example generation

Imgur

We can also provide multiple example images and the algorithm will "remix" them into a new image.

use texture_synthesis as ts;

fn main() -> Result<(), ts::Error> {
    // create a new session
    let texsynth = ts::Session::builder()
        // load multiple example image
        .add_examples(&[
            &"imgs/multiexample/1.jpg",
            &"imgs/multiexample/2.jpg",
            &"imgs/multiexample/3.jpg",
            &"imgs/multiexample/4.jpg",
        ])
        // we can ensure all of them come with same size
        // that is however optional, the generator doesnt care whether all images are same sizes
        // however, if you have guides or other additional maps, those have to be same size(s) as corresponding example(s)
        .resize_input(ts::Dims {
            width: 300,
            height: 300,
        })
        // randomly initialize first 10 pixels
        .random_init(10)
        .seed(211)
        .build()?;

    // generate an image
    let generated = texsynth.run(None);

    // save the image to the disk
    generated.save("out/02.jpg")?;

    //save debug information to see "remixing" borders of different examples in map_id.jpg
    //different colors represent information coming from different maps
    generated.save_debug("out/")
}

CLI

cargo run --release -- --rand-init 10 --seed 211 --in-size 300x300 -o out/02.png --debug-out-dir out generate imgs/multiexample/1.jpg imgs/multiexample/2.jpg imgs/multiexample/3.jpg imgs/multiexample/4.jpg

You should get the following result with the images provided in this repo:

3. Guided Synthesis

Imgur

We can also guide the generation by providing a transformation "FROM"-"TO" in a form of guide maps

use texture_synthesis as ts;

fn main() -> Result<(), ts::Error> {
    let texsynth = ts::Session::builder()
        // NOTE: it is important that example(s) and their corresponding guides have same size(s)
        // you can ensure that by overwriting the input images sizes with .resize_input()
        .add_example(ts::Example::builder(&"imgs/2.jpg").with_guide(&"imgs/masks/2_example.jpg"))
        // load target "heart" shape that we would like the generated image to look like
        // now the generator will take our target guide into account during synthesis
        .load_target_guide(&"imgs/masks/2_target.jpg")
        .build()?;

    let generated = texsynth.run(None);

    // save the image to the disk
    generated.save("out/03.jpg")
}

CLI

cargo run --release -- -o out/03.png generate --target-guide imgs/masks/2_target.jpg --guides imgs/masks/2_example.jpg -- imgs/2.jpg

NOTE: Note the use of -- to delimit the path to the example imgs/2.jpg, if you don't specify --, the path to the example will be used as another guide path and there won't be any examples.

You should get the following result with the images provided in this repo:

4. Style Transfer

Imgur

Texture synthesis API supports auto-generation of example guide maps, which produces a style transfer-like effect.

use texture_synthesis as ts;

fn main() -> Result<(), ts::Error> {
    let texsynth = ts::Session::builder()
        // load example which will serve as our style, note you can have more than 1!
        .add_examples(&[&"imgs/multiexample/4.jpg"])
        // load target which will be the content
        // with style transfer, we do not need to provide example guides
        // they will be auto-generated if none were provided
        .load_target_guide(&"imgs/tom.jpg")
        .guide_alpha(0.8)
        .build()?;

    // generate an image that applies 'style' to "tom.jpg"
    let generated = texsynth.run(None);

    // save the result to the disk
    generated.save("out/04.jpg")
}

CLI

cargo run --release -- --alpha 0.8 -o out/04.png transfer-style --style imgs/multiexample/4.jpg --guide imgs/tom.jpg

You should get the following result with the images provided in this repo:

5. Inpaint

Imgur

We can also fill-in missing information with inpaint. By changing the seed, we will get different version of the 'fillment'.

use texture_synthesis as ts;

fn main() -> Result<(), ts::Error> {
    let texsynth = ts::Session::builder()
        // let the generator know which part we would like to fill in
        // if we had more examples, they would be additional information
        // the generator could use to inpaint
        .inpaint_example(
            &"imgs/masks/3_inpaint.jpg",
            // load a "corrupted" example with missing red information we would like to fill in
            ts::Example::builder(&"imgs/3.jpg")
                // we would also like to prevent sampling from "corrupted" red areas
                // otherwise, generator will treat that those as valid areas it can copy from in the example,
                // we could also use SampleMethod::Ignore to ignore the example altogether, but we
                // would then need at least 1 other example image to actually source from
                // example.set_sample_method(ts::SampleMethod::Ignore);
                .set_sample_method(&"imgs/masks/3_inpaint.jpg"),
            // Inpaint requires that inputs and outputs be the same size, so it's a required
            // parameter that overrides both `resize_input` and `output_size`
            ts::Dims::square(400),
        )
        // Ignored
        .resize_input(ts::Dims::square(200))
        // Ignored
        .output_size(ts::Dims::square(100))
        .build()?;

    let generated = texsynth.run(None);

    //save the result to the disk
    generated.save("out/05.jpg")
}

CLI

Note that the --out-size parameter determines the size for all inputs and outputs when using inpaint!

cargo run --release -- --out-size 400 --inpaint imgs/masks/3_inpaint.jpg -o out/05.png generate imgs/3.jpg

You should get the following result with the images provided in this repo:

6. Inpaint Channel

bricks

Instead of using a separate image for our inpaint mask, we can instead obtain the information from a specific channel. In this example, the alpha channel is a circle directly in the middle of the image.

use texture_synthesis as ts;

fn main() -> Result<(), ts::Error> {
    let texsynth = ts::Session::builder()
        // Let the generator know that it is using 
        .inpaint_example_channel(
            ts::ChannelMask::A,
            &"imgs/bricks.png",
            ts::Dims::square(400),
        )
        .build()?;

    let generated = texsynth.run(None);

    //save the result to the disk
    generated.save("out/06.jpg")
}

CLI

cargo run --release -- --inpaint-channel a -o out/06.png generate imgs/bricks.jpg

You should get the following result with the images provided in this repo:

7. Tiling texture

We can make the generated image tile (meaning it will not have seams if you put multiple images together side-by-side). By invoking inpaint mode together with tiling, we can make an existing image tile.

use texture_synthesis as ts;

fn main() -> Result<(), ts::Error> {
    // Let's start layering some of the "verbs" of texture synthesis
    // if we just run tiling_mode(true) we will generate a completely new image from scratch (try it!)
    // but what if we want to tile an existing image?
    // we can use inpaint!

    let texsynth = ts::Session::builder()
        // load a mask that specifies borders of the image we can modify to make it tiling
        .inpaint_example(
            &"imgs/masks/1_tile.jpg",
            ts::Example::new(&"imgs/1.jpg"),
            ts::Dims::square(400),
        )
        //turn on tiling mode!
        .tiling_mode(true)
        .build()?;

    let generated = texsynth.run(None);

    generated.save("out/07.jpg")
}

CLI

cargo run --release -- --inpaint imgs/masks/1_tile.jpg --out-size 400 --tiling -o out/07.bmp generate imgs/1.jpg

You should get the following result with the images provided in this repo:

8. Repeat texture synthesis transform on a new image

We can re-apply the coordinate transformation performed by texture synthesis onto a new image.

use texture_synthesis as ts;

fn main() -> Result<(), ts::Error> {
    // create a new session
    let texsynth = ts::Session::builder()
        //load a single example image
        .add_example(&"imgs/1.jpg")
        .build()?;

    // generate an image
    let generated = texsynth.run(None);

    // now we can apply the same transformation of the generated image
    // onto a new image (which can be used to ensure 1-1 mapping between multiple images)
    // NOTE: it is important to provide same number of input images as the 
    // otherwise, there will be coordinates mismatch
    let repeat_transform_img = generated
        .get_coordinate_transform()
        .apply(&["imgs/1_bw.jpg"])?;

    // save the image to the disk
    // 08 and 08_repeated images should match perfectly
    repeat_transform_img.save("out/08_repeated.jpg").unwrap();
    generated.save("out/08.jpg")
}

CLI

  1. First, we need to create a transform that can be reused

The notable bit here is the --save-transform out/multi.xform which creates the file that can be used to generate new outputs with.

cargo run --release -- --rand-init 10 --seed 211 --in-size 300x300 -o out/02.png generate --save-transform out/multi.xform imgs/multiexample/1.jpg imgs/multiexample/2.jpg imgs/multiexample/3.jpg imgs/multiexample/4.jpg

  1. Next, we use the repeat subcommand to repeat transform with different inputs

The important bits here are the use of the repeat subcommand instead of generate, and --transform out/multi.xform which tells what transform to apply to the inputs. The only restriction is that the number of images you specify must match the original number of examples exactly. If the input images have different dimensions than the example images, they will be automatically resized for you.

cargo run --release -- -o out/02-repeated.png repeat --transform out/multi.xform imgs/multiexample/1.jpg imgs/multiexample/2.jpg imgs/multiexample/4.jpg imgs/multiexample/3.jpg

Also note that the normal parameters that are used with generate don't apply to the repeat subcommand and will be ignored.

9. Sample masks

Sample masks allow you to specify how an example image is sampled during generation.

use texture_synthesis as ts;

fn main() -> Result<(), ts::Error> {
    let session = ts::Session::builder()
        .add_example(
            ts::Example::builder(&"imgs/4.png").set_sample_method(ts::SampleMethod::Ignore),
        )
        .add_example(ts::Example::builder(&"imgs/5.png").set_sample_method(ts::SampleMethod::All))
        .seed(211)
        .output_size(ts::Dims::square(200))
        .build()?;

    // generate an image
    let generated = session.run(None);

    // save the image to the disk
    generated.save("out/09.png")
}

CLI

cargo run --release -- --seed 211 --out-size 200 --sample-masks IGNORE ALL --out 09_sample_masks.png generate imgs/4.png imgs/5.png

You should get the following result with the images provided in this repo:

10. Combining texture synthesis 'verbs'

We can also combine multiple modes together. For example, multi-example guided synthesis:

Or chaining multiple stages of generation together:

For more use cases and examples, please refer to the presentation "More Like This, Please! Texture Synthesis and Remixing from a Single Example"

Additional CLI functionality

Some functionality is only exposed through the CLI and not built into the library.

flip-and-rotate

This subcommand takes each example and performs flip and rotation transformations to it to generate additional example inputs for generation. This subcommand doesn't support target or example guides.

Example: cargo run --release -- -o out/output.png flip-and-rotate imgs/1.jpg

Command line binary

  • Download the binary for your OS.
  • Or Install it from source.
    • Install Rust - The minimum required version is 1.37.0
    • Clone this repo
    • In a terminal cd to the directory you cloned this repository into
    • Run cargo install --path=cli
    • Or if you wish to see the texture as it is being synthesized cargo install --path=cli --features="progress"
  • Open a terminal
  • Navigate to the directory where you downloaded the binary, if you didn't just cargo install it
  • Run texture_synthesis --help to get a list of all of the options and commands you can run
  • Refer to the examples section in this readme for examples of running the binary

Notes

  • By default, generating output will use all of your logical cores
  • When using multiple threads for generation, the output image is not guaranteed to be deterministic with the same inputs. To have 100% determinism, you must use a thread count of one, which can by done via
    • CLI - texture-synthesis --threads 1
    • API - SessionBuilder::max_thread_count(1)

Limitations

  • Struggles with complex semantics beyond pixel color (unless you guide it)
  • Not great with regular textures (seams can become obvious)
  • Cannot infer new information from existing information (only operates on what’s already there)
  • Designed for single exemplars or very small datasets (unlike Deep Learning based approaches)

Additional Dependencies

If you're compiling for Linux, you'll need to have libxkbcommon development libraries installed. For ubuntu this is libxkbcommon-x11-dev.

Links/references

[1] [Opara & Stachowiak] "More Like This, Please! Texture Synthesis and Remixing from a Single Example"

[2] [Harrison] Image Texture Tools

[3] [Ashikhmin] Synthesizing Natural Textures

[4] [Efros & Leung] Texture Synthesis by Non-parametric Sampling

[5] [Wey & Levoy] Fast Texture Synthesis using Tree-structured Vector Quantization

[6] [De Bonet] Multiresolution Sampling Procedure for Analysis and Synthesis of Texture Images

[7] All the test images in this repo are from Unsplash

Contributing

Contributor Covenant

We welcome community contributions to this project.

Please read our Contributor Guide for more information on how to get started.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

texture-synthesis's People

Contributors

1bardesign avatar anopara avatar austinjones avatar bnjbvr avatar celialewis3 avatar dependabot-preview[bot] avatar dependabot[bot] avatar h3r2tic avatar jake-shadle avatar jd557 avatar lpil avatar lukaskalbertodt avatar moppius avatar mr4k avatar phimuemue avatar repi avatar soniasingla avatar theotherphil avatar xampprocky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

texture-synthesis's Issues

16 Bit Image Support?

I'm not sure if I'm just missing it somewhere, but I'm using a 16 bit grayscale (height map) png as the input, but still getting an 8 bit rgb output. Am I just missing something, or is it not capable of this yet? I thought I saw some terrain tests, and I was assuming those were 16 bit

Make a release!

We've had some really nice performance improvements landed thanks to @Mr4k that should be released, but I haven't had time this week to finish up some lingering issues that should also be in the release.

  • - #89 (cutting this because we can refactor the docs separately from releasing)
  • - #38
  • - #86

Make cdylib

One of the current users of texture-synthesis is in Blender addons, but these are interacting with the CLI rather than with a library, and makes the CLI a de facto standard interface which is not its intention. We should add a C wrapper into the library to allow the use of texture-synthesis as a C shared library which can have a smaller, simpler, API surface that can be more stable and easier to interact with for cases such as the above.

Nightly failure

There is a nightly only failure due to gfx but it's not a big deal, we can wait for a fix or just fix it ourselves if needed.

Please update the addon to also function on macOS and Linux

The texture-synthesis executable is available for several platforms, including Windows, macOS and Linux.

At current, the blender addon only works for MS Windows. It specifically looks for "texture-synthesis.exe' and fails to find the macOS executable "texture-synthesis". Please update the addon to include other platforms.

I got the addon to work on macOS by editing addon_preferences.py as follows:

import os, platform
(...)

class TextureSynthPreferences(bpy.types.AddonPreferences):
    bl_idname = addon_name_lowercase()

    def check_ts_exist(self, context):
        absPath, ts_exists = check_file_exist(self.text_synth_path)
        self['text_synth_path'] = absPath
        if platform.system() in ["Darwin","Linux"]:
            if ts_exists and os.path.basename(absPath) == "texture-synthesis":
                self.display_info = "texture-synthesis found in: " + absPath
        else:
            if ts_exists and os.path.basename(absPath) == "texture-synthesis.exe":
                self.display_info = "texture-synthesis.exe found in: " + absPath
            else:
                self.display_info = "texture-synthesis.exe not found in: " + absPath

(...)

Split deploy of lib and cli

For now we've been using the same version for both the lib and the cli, as well as the same tag, mostly for convenience. We should split it so that the lib and cli get a separate tag and a separate publish.

Is a 3d (voxel) version of this tool planned?

Hi,

I watched the talk linked in the Readme. At the end Anastasia mentions that you are currently working on bringing the 2d concept to 3d.

I am currently working on a (hobby) Voxel enigne in rust+vulkan and thought it might be easy to transfer the algorithm to 3d given a good Voxel loading/editing crate similar to the image crate.

Are there already working prototypes internally which take some 3d information and apply the algorithm to generate a new 3d model? Do you have some more crates in this direction planed or would it make sense for me to either extent this project to also worke in 3d or create a new one from scratch?

Greetings
Tendsin Mende

Infer new information

First of all, I wanted to congratulate this project because it is really incredible.

I am doing a similar project, to generate images of huge textures with one or several input images, but I have the problem that I would need to infer new information (as a neural network but with your quality). I would like to know if you know of any Git or paper that addresses this problem.

King regards

Update to v0.3 of Embark's standard lints

Embark uses a standard set of lints across all repositories. We just upgraded
to version 0.3 of these lints, and this repository needs to be updated to
the new set of lints with any warnings fixed.

Steps

  1. Copy the contents of the lints.rs file from
    EmbarkStudios/rust-ecosystem and replace the old list of lints in the
    src/lib.rs and/or src/main.rs files with the new list.
  2. Run cargo clippy
  3. Update and fix any code that now triggers a new warning.

Suggestion: CLI option to automatically add mirrorings and rotations of input image

Suggesting to have something like --fips-and-rotates option:

texture-synthesis -o out.png --tiling generate --fips-and-rotates in.png

Which does approximately this:

convert in.png -rotate 0 in1.png
convert in.png -rotate 90 in2.png
convert in.png -rotate 180 in3.png
convert in.png -rotate 270 in4.png
convert in.png -rotate 0 -flip in5.png
convert in.png -rotate 90 -flip in6.png
convert in.png -rotate 180 -flip in7.png
convert in.png -rotate 270 -flip in8.png
texture-synthesis -o out.png --tiling generate --fips-and-rotates in*.png

Compiling on Os X

Hello and first of all thank you for releasing this, this is fantastic.
I have trouble compiling on os x:

When I do cargo install --path=. I get :

MacBook:texture-synthesis-master-2 macbook$ cargo install --path=.
error: found a virtual manifest at `/Users/macbook/Desktop/Downloads/texture-synthesis-master-2/Cargo.toml` instead of a package manifest

Or if I try to run the example :
cargo run --release -- --out out/01.jpg generate imgs/1.jpg

...
Compiling indicatif v0.12.0
Compiling texture-synthesis v0.6.0 (/Users/macbook/Desktop/Downloads/texture-synthesis-master-2/lib)
error: enum variants on type aliases are experimental
--> lib/src/lib.rs:198:13
 |
198 |             Self::Ignore => true,
 |             ^^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/lib.rs:224:13
 |
224 |             Self::Ignore => true,
 |             ^^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/errors.rs:62:13
|
62 |             Self::Image(ie) => write!(f, "{}", ie),
|             ^^^^^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/errors.rs:63:13
|
63 |             Self::InvalidRange(ir) => write!(f, "{}", ir),
|             ^^^^^^^^^^^^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/errors.rs:64:13
|
64 |             Self::SizeMismatch(sm) => write!(f, "{}", sm),
|             ^^^^^^^^^^^^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/errors.rs:65:13
|
65 |             Self::ExampleGuideMismatch(examples, guides) => {
|             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/errors.rs:80:13
|
80 |             Self::Io(io) => write!(f, "{}", io),
|             ^^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/errors.rs:81:13
|
81 |             Self::UnsupportedOutputFormat(fmt) => {
|             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/errors.rs:84:13
|
84 |             Self::NoExamples => write!(
|             ^^^^^^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/errors.rs:97:9
|
97 |         Self::Image(ie)
|         ^^^^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/errors.rs:103:9
 |
103 |         Self::Io(io)
 |         ^^^^^^^^

error: enum variants on type aliases are experimental
--> lib/src/utils.rs:28:9
|
28 |         Self::Path(path.as_ref())
|         ^^^^^^^^^^

error: aborting due to 12 previous errors

error: Could not compile `texture-synthesis`.
warning: build failed, waiting for other jobs to finish...
error: build failed

I'm on OS 10.13.6
and installed rust like this :
curl https://sh.rustup.rs -sSf | sh

Texture synthesis inpaint - ignores tiling.

Not sure if this is bug but tiling wont work on inpaint image:
image
I think it would be cool to have this option here too.
And the command I tried:
'C:\Users\XXX\Desktop\texture-synthesis-0.5.0-x86_64-pc-windows-msvc\texture-synthesis.exe', '--out', 'C:\Users\XXX\Desktop\Test\TileTest\Free Texture Asphalt_OUT.png', '--out-size', '512x512', '--seed', '1', '--rand-init', '1', '--in-size', '512x512', '--tiling', '--inpaint', 'C:\Users\XXX\Desktop\Test\TileTest\Free Texture Asphalt_inpaint.png', 'generate', 'D:\TexturyDarmowe\Droga\Free Texture Asphalt.jpg'

Add sample mask example

Though #85 is a bug in structopt, we should still have at least one example of using sample masks, so that if users copy it and replace eg, the input image paths, they won't get this confusing error message.

Open source

Tasks remaining to open source this. A bunch of these steps are listed in more detail on https://github.com/EmbarkStudios/rust-ecosystem/blob/master/open-sourcing.md

First steps:

  • Bring over everything from our Rust template: https://github.com/EmbarkStudios/rust-ecosystem
  • Pick and use an emoji for the repo πŸ˜„ 🎨
  • Make sure crate can be packaged with cargo package
  • Bring over README to lib.rs and verify it looks good with cargo doc
  • Add Travis CI to the repo
  • Remove checked in .exe and replace with CI published GitHub release. Believe @Jake-Shadle has a travis script that does that
  • Test switching out and use the crate in our own projects (with file dependency) @Jake-Shadle
  • Team review code & docs

Final steps in-order (after all above are done):

CLI error message is unclear when `--` is in wrong place

Describe the bug

Error message about wrong CLI usage is unclear

To Reproduce

$ texture-synthesis --out-size=171x248 --out=w.png -- generate q1.png 
error: The subcommand 'generate' wasn't recognized
	Did you mean 'generate'?

If you believe you received this message in error, try re-running with 'texture-synthesis -- generate'

USAGE:
    texture-synthesis --out-size <out-size> --out <output-path>

For more information try --help

Expected behavior

Error message helps me to fix the command line, not to substitude generate for generate.

The command line works if -- is removed. As -- is often present in README examples, probability that users would step on this is higher.

Another CLI UI strangeness:

Another CLI UI strangeness:

        --out-fmt <out-fmt>                       
            The format to save the generated image as.
            
            NOTE: this will only apply when stdout is specified via `-o -`, otherwise the image format is determined by
            the file extension of the path provided to `-o` [default: png]

Explicit command-line option should override any sort of auto-detection.

Originally posted by @vi in #20 (comment)

Include license attribution in release binaries

As this project distributes binary executables in the GitHub releases and as now have our cargo-about tool we should use it to include license attribution for all dependencies used in the texture synthesis cli application, for every release.

Would be great to have a sub-command that prints out the licenses, something like texture-synthesis-cli about-licenses that shows a simple list of crates + license, and then maybe a texture-synthesis-cli about-licenses-full that shows the full license text for every unique license as well?

Should have a standard naming, output, and CI set up for this that we (and others) can use in all of our binary tools

Package the Windows release as a .zip file

Is your feature request related to a problem? Please describe.
Windows users may not have suitable tooling or knowledge to unpackage a .tar.gz file using vanilla Windows installs.

Describe the solution you'd like
When new releases are made, the Windows releases should be packaged in .zip format.

Describe alternatives you've considered
We discussed this internally, and most agreed that it would help Windows users to have a .zip version instead of .tar.gz.

Inpaint using other image as example runtime error

I'm trying to use the library directly without the CLI interface.
I'm trying the impainting example as explained inside the library in a comment over inpaint_example() method, below the cited comment:

    /// Inpaints an example. Due to how inpainting works, a size must also be
    /// provided, as all examples, as well as the inpaint mask, must be the same
    /// size as each other, as well as the final output image. Using
    /// `resize_input` or `output_size` is ignored if this method is called.
    ///
    /// To prevent sampling from the example, you can specify
    /// `SamplingMethod::Ignore` with `Example::set_sample_method`.
    ///
    /// See [`examples/05_inpaint`](https://github.com/EmbarkStudios/texture-synthesis/tree/main/lib/examples/05_inpaint.rs)
    ///
    /// # Examples
    ///
    /// ```no_run
    /// let tex_synth = texture_synthesis::Session::builder()
    ///     .add_examples(&[&"imgs/1.jpg", &"imgs/3.jpg"])
    ///     .inpaint_example(
    ///         &"masks/inpaint.jpg",
    ///         // This will prevent sampling from the imgs/2.jpg, note that
    ///         // we *MUST* provide at least one example to source from!
    ///         texture_synthesis::Example::builder(&"imgs/2.jpg")
    ///             .set_sample_method(texture_synthesis::SampleMethod::Ignore),
    ///         texture_synthesis::Dims::square(400)
    ///     )
    ///     .build().expect("failed to build session");
    /// ```

using exactly the script in this comment present in the file session.rs:122 I got this error:

thread 'main' panicked at 'index out of bounds: the len is 2 but the index is 2', lib/src/ms.rs:696:18
stack backtrace:
   0: rust_begin_unwind
             at /rustc/51126be1b260216b41143469086e6e6ee567647e/library/std/src/panicking.rs:577:5
   1: core::panicking::panic_fmt
             at /rustc/51126be1b260216b41143469086e6e6ee567647e/library/core/src/panicking.rs:135:14
   2: core::panicking::panic_bounds_check
             at /rustc/51126be1b260216b41143469086e6e6ee567647e/library/core/src/panicking.rs:77:5
   3: texture_synthesis::ms::Generator::next_pyramid_level
             at ./lib/src/ms.rs:696:18
   4: texture_synthesis::ms::Generator::resolve
             at ./lib/src/ms.rs:797:17
   5: texture_synthesis::session::Session::run
             at ./lib/src/session.rs:55:9

This behavior appears only if I pass texture_synthesis::SampleMethod::Ignore as parameter for set_sample_method() of the example inside the inpaint_example method.
Instead, texture_synthesis::SampleMethod::All and an image as argument work smoothly.

I'm using cargo 1.60.0-nightly (95bb3c92b 2022-01-18)

Anyone know how to solve this bug?

error: failed to fill whole buffer

Hello first of all thank you for 0.8.0 and the CLI documentation with the examples.
This is awesome.
The speed is noticeable.

I have this error when trying to feed a 3k image as an example (3180x 3180) :
error: failed to fill whole buffer

The machine is a 8go mac laptop. Os 10.13.6
So is it normal ? and is there a rule to know the image size limit with an amount of RAM available.

Thank you.

CLI: Upper progress bar jumps from 66% to 100%

[00:00:25] ###########################------------- 66%
 stage   6 ######################################-- 95%

It is almost done, but main progress bar shows 66%. It jumps to 100% immediately before finishing, but it should be 99% when it is 66%. Otherwise it is pretty linear.

could not compile `texture-synthesis`

could not compile texture-synthesis

Steps to reproduce the behavior:

  1. Go to clone repo \texture-synthesis
  2. Run in Terminal cargo install --path=cli
  3. See error

stable-x86_64-pc-windows-msvc (default)
rustc 1.56.1 (59eed8a2a 2021-11-01)

Caused by:
  build failed
PS C:\texture_synthesis> cargo update
    Updating git repository `https://github.com/EmbarkStudios/img_hash.git`
    Updating crates.io index
    Updating bstr v0.2.16 -> v0.2.17
    Updating bumpalo v3.7.0 -> v3.8.0
    Updating cc v1.0.69 -> v1.0.72
    Updating clang-sys v1.2.1 -> v1.3.0
    Updating cmake v0.1.45 -> v0.1.46
    Updating console v0.14.1 -> v0.15.0
    Updating crc32fast v1.2.1 -> v1.2.2
      Adding cty v0.2.2
    Updating encoding_rs v0.8.28 -> v0.8.29
    Updating flate2 v1.0.21 -> v1.0.22
    Updating half v1.7.1 -> v1.8.2
    Updating js-sys v0.3.53 -> v0.3.55
    Updating libc v0.2.101 -> v0.2.108
    Updating libloading v0.7.0 -> v0.7.2
    Removing maybe-uninit v2.0.0
      Adding once_cell v1.8.0
    Updating pdqselect v0.1.0 -> v0.1.1
    Updating pkg-config v0.3.19 -> v0.3.22
    Updating proc-macro2 v1.0.29 -> v1.0.32
    Updating quote v1.0.9 -> v1.0.10
    Removing raw-window-handle v0.3.3
      Adding raw-window-handle v0.3.4
      Adding raw-window-handle v0.4.2
    Updating serde_json v1.0.67 -> v1.0.72
    Updating structopt v0.3.23 -> v0.3.25
    Updating structopt-derive v0.4.16 -> v0.4.18
    Updating syn v1.0.75 -> v1.0.82
    Updating unicode-width v0.1.8 -> v0.1.9
    Updating wasm-bindgen v0.2.76 -> v0.2.78
    Updating wasm-bindgen-backend v0.2.76 -> v0.2.78
    Updating wasm-bindgen-macro v0.2.76 -> v0.2.78
    Updating wasm-bindgen-macro-support v0.2.76 -> v0.2.78
    Updating wasm-bindgen-shared v0.2.76 -> v0.2.78
    Updating web-sys v0.3.53 -> v0.3.55
    Updating x11-dl v2.18.5 -> v2.19.1
PS C:\texture_synthesis> cargo install --path=cli
  Installing texture-synthesis-cli v0.8.2 (C:\texture_synthesis\cli)
    Updating git repository `https://github.com/EmbarkStudios/img_hash.git`
    Updating crates.io index
warning: Patch `img_hash v2.1.0 (https://github.com/EmbarkStudios/img_hash.git?rev=c40da78#c40da789)` was not used in the crate graph.
Check that the patched package version and available features are compatible
with the dependency requirements. If the patch has a different version from
what is locked in the Cargo.lock file, run `cargo update` to use the new
version. This may also occur with an optional dependency that is not enabled.
   Compiling texture-synthesis v0.8.1 (C:\texture_synthesis\lib)
error: failed to compile `texture-synthesis-cli v0.8.2 (C:\texture_synthesis\cli)`, intermediate artifacts can be found at `C:\texture_synthesis\target`

Caused by:
  could not compile `texture-synthesis`

Caused by:
  process didn't exit successfully: `rustc --crate-name texture_synthesis --edition=2018 lib\src\lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C embed-bitcode=no -C metadata=49f1ddcd6f2ccc14 -C extra-filename=-49f1ddcd6f2ccc14 --out-dir C:
\texture_synthesis\target\release\deps -L dependency=C:\texture_synthesis\target\release\deps --extern crossbeam_utils=C:\texture_synthesis\target\release\deps\libcrossbeam_utils-7b399fb1046e66b6.rmeta --extern image=C:\texture_synthesis\target\release\deps\libimage-5e450dcef3d57d47.rmeta --extern num_cpus=C:\text
ure_synthesis\target\release\deps\libnum_cpus-d3a6b4fc392a88ff.rmeta --extern rand=C:\texture_synthesis\target\release\deps\librand-1b42e77a27ea407f.rmeta --extern rand_pcg=C:\texture_synthesis\target\release\deps\librand_pcg-145f9981a0711c53.rmeta --extern rstar=C:\texture_synthesis\target\release\deps\librstar-e
66dad66812cd298.rmeta` (exit code: 0xc000001d, STATUS_ILLEGAL_INSTRUCTION)
PS C:\texture_synthesis>

Please help, what am I doing wrong?

thread '<unnamed>' panicked at 'cannot access stderr during shutdown', src\libcore\option.rs:1188:5

Using texture-synthesis-0.8.0-x86_64-pc-windows-msvc.zip and the provided example images:

C:\texture-synthesis-0.8.0-x86_64-pc-windows-msvc>texture-synthesis.exe --inpaint 1_tile.jpg --out-size 400 --tiling -o out.bmp generate 1.jpg
[00:00:01] ###########################------------- 66%
 stage   6 #############--------------------------- 32%
thread '<unnamed>' panicked at 'cannot access stderr during shutdown', src\libcore\option.rs:1188:5

Sometimes it works, sometimes it doesn't.

Sporatic freezes due to threading

Sometimes it just locks up and fails to progress, keeping CPU (one thread) busy.

Just trying again (another seed?) seems to be resolving the issue.

$ texture-synthesis  --out=z.png --k-neighs 50 --m-rand 50   --tiling generate q.png    && tile2x2 z.png zz.png
[00:00:27] ###########################------------- 66%
 stage   6 ######################################-- 95%

^C
$ texture-synthesis  --out=z.png --k-neighs 50 --m-rand 50   --tiling generate q.png    && tile2x2 z.png zz.png
[00:00:01] ##-------------------------------------- 4%
[00:00:25] ######################################## 100%
 stage   6 ######################################## 100%
$

Using low --k-neighs increases probability of fail. Explicitly specifying --seed seems to have no effect:

$ texture-synthesis  --out=z.png --k-neighs 10 --m-rand 50   --tiling --seed 2 generate q.png 
[00:00:07] ###########################------------- 66%
 stage   6 ######################################-- 95%
^C
$ texture-synthesis  --out=z.png --k-neighs 10 --m-rand 50   --tiling --seed 2 generate q.png 
[00:00:07] ######################################## 100%
 stage   6 ######################################## 100%
$ texture-synthesis  --out=z.png --k-neighs 10 --m-rand 50   --tiling --seed 2 generate q.png 
[00:00:07] ######################################## 100%
 stage   6 ######################################## 100%
$ texture-synthesis  --out=z.png --k-neighs 10 --m-rand 50   --tiling --seed 2 generate q.png 
[00:00:07] ###########################------------- 66%
 stage   6 ######################################-- 95%
^C
$

Workaround: -t 1 to turn off threading. No repro even with --k-neighs 1.

Signal progress when compiling for wasm32

In native mode, progress can be signaled to the user by passing a GeneratorProgress implementation. The WebAssembly mode doesn't support signaling progress, which looks like a not-implemented-yet situation rather than something impossible to solve. So I'd like to add this :-)

Describe the solution you'd like
The code used to compute the current progress percentage could be generalized into a small notifier (not a final name!) data structure/closure wrapping the GeneratorProgress, and passed as an Optional parameter to worker_fn in lib/src/ms.rs.

The main progress loop in the worker would signal progress, if the parameter is not None. In the case of native, a None argument is passed to each worker_fn call. In the case of wasm, the notifier is passed to the one worker_fn call. This is future-proof in the sense that even if wasm multi-threading support was added, the borrow-checker would complain about multiple mutable ownership of the notifier.

Describe alternatives you've considered

  • the above solution is the path of least resistance, but it'll a dynamic check (to check if the Option is some) for each iteration of the progress loop, in both native and wasm. With a little effort, maybe the worker_fn function could be refactored in such a way that it's not a closure anymore. Then this function could be parameterized on some new trait with a signal_progress method; in the case of native, the trait impl would do nothing; in the wasm case, the impl would actually report progress. This is slightly more involved, but would imply no additional cost for the native case. I didn't look into this before getting any numbers with the suggested approach to confirm that the overhead is an actual issue.
  • implementing threading support for the wasm case. Ahem :-)

Thoughts?

Reproducible / deterministic seeding

Are there plans to provide guaranteed deterministic/reproducible seeding of generated textures? Perhaps with some performance hit.

Currently the seed method says the generated output may be slightly different because of indeterminacy of thread execution.

Right now, to achieve reproducible builds one needs to save generated textures; while this is probably a good idea for performance reasons, I would like to delete old textures with some confidence that I can get them back by running the program.

There are some techniques that can mitigate concurrency indeterminacy. One of them is to avoid interior mutability (like atomics and locks) and use something like Rayon's fork-join, which would always produce the same output regardless of thread execution order (edit: clarified that you don't actually need immutable data, you just need to have each memory location being written by just one thread). But I don't know how feasible would it be to apply them to texture-synthesis.

As a last resort, texture-synthesis could at least state in its documentation (in the seed method and/or elsewhere) that if one sets max_thread_count to 1, generation is guaranteed to be deterministic.

web interface for texture synthesis

Hi there!

I have a friend (https://davidberrebi.com/) who wanted to use texture-synthesis software for some of his art work, but he could not manage to use the CLI. I helped him to use it but realized that not anybody is comfortable with this kind of interface. That's why I started to write a GUI for texture-synthesis.
My choice came to the web, because it's easy to use and quite universal. Webassembly lacking multithreading support, I came to a simple wesocket API and a js frontend. My proof of concept is available here and I would like to know if you are interested in this before investing the time needed to submit a proper pull request to your project.

By the way, when looking for "texture synthesis" on GitHub, I found two other repositories who did something similar to you (1, 2). Have you already heard about them?

Automatically deriving mask for inpainting from alpha channel

Currently inpainting requires specifying two congruent images. It may be more convenient to just specify one image with erased regions (alpha channel).

Current UX:

$ convert q1.png -alpha extract q1_mask.png
$ texture-synthesis --out-size=171x248 --in-size=171x248 --out=w.png --inpaint=q1_mask.png generate q1.png

Desired UX:

$ texture-synthesis --out=w.png alpha-inpaint q1.png

Proper alpha channel support in matcher.

Currently alpha channel is ignored in matcher algorithm. It is used just in final phase, leading to illusion of alpha channel support.


Some comments by @austinjones from #22:

@vi @Jake-Shadle I have a prototype of generic pixel support (RGB/RGBA/Luma/LumaA) implemented on austinjones/texture-synthesis/multipixel, but it needs some work. It's just a quick exploration.

I tried handling alpha this way: Premultiply alpha and only consider color channels. This makes sense when later compositing: bright red with very low alpha and bright green with very low alpha are actually similar colors when added to anything. I didn't add alpha to the cost computation though, because the correlation with the color channels will cause bias in the cost metric.

There were some side effects:

* Session requires a type parameter (the pixel type).  It has to be specified by the user whenever SessionBuilder::build() is called.

* There is a decent performance hit.  Need to figure out why...

* The guided synthesis test fails.

Let me know if you are interested in the code. I can try to fix it up.


@vi Yes, you are right! I was trying to solve a different problem (support for example transparency).

I think what is supported right now is cost computation based on RGB, but pixel copies are on the full RGBA. If you add a bunch of transparent bright red, the cost is computed on bright red. Take a look at k_neighs_to_color_pattern - note the multiplier on the first line is 3, not 4. Transparent bright red is considered bright red when running the matching algorithm.

Pattern Transforms

Hello! First, thanks for this amazing project.
I have a question:
Looking at single example generation, I noticed there are not "transformed" patterns in the generated image.
By transformed I mean, rotation, scale and warping. Of patterns in the example.
Is there a way to achieve this?
Thanks!

inpaint using other image as example

My goal is to paint inside an image using an other image as example.

For example I would like to paint in the first image where the 'A' is transparent (here rendered with checkered pattern) using the second image as example. The result would be something like the third image but with pixels generated so the border matches.

I tried with commands like

texture-synthesis --inpaint-channel a --sample-masks IGNORE ALL \
-o output.png generate A-alpha.png dark-smoke.png
# expecting it to paint inside A-alpha using examples from dark-smoke

but it does not work and gives me

as if it did use the alpha channel of A-alpha but choose to paint inside dark-smoke instead of painting inside A-alpha.

CLI: using --sample-masks option

When running:

texture-synthesis --inpaint mask.png -o output.png --sample-masks IGNORE mask.png -- generate white_square.png texture.png

I get:

error: The subcommand 'generate' wasn't recognized
	Did you mean 'generate'?

If you believe you received this message in error, try re-running with 'texture-synthesis -- generate'

USAGE:
    texture-synthesis --inpaint <inpaint> --out-size <out-size> --out <output-path> --sample-masks <sample-masks>...

Is this the expected behavior? How should I use sample-masks option? (there is no example in the README).

The help says:

--sample-masks <sample-masks>...
            Path(s) to sample masks used to determine which pixels in an example can be used as inputs during
            generation, any example that doesn't have a mask, or uses `ALL`, will consider all pixels in the example. If
            `IGNORE` is specified, then the example image won't be used at all, which is useful with `--inpaint`.

I'm precisely trying to use sample-masks in combination with inpaint but can not manage to do it.

How to add example as image bytes/array, not path?

I can't understand how to add images not by path, but as already loaded to memory images? With complex image manipulation pipeline it's quite uncomfortable to save image to disk right before using texture-synthesis. Thanks!

Large backtrack-stages setting causes a crash inside `ImagePyramid::build_gaussian`

Setting backtrack-stages to more than log2(image-dimension) leads to a panic inside ImagePyramid::build_gaussian

To Reproduce
Steps to reproduce the behavior:
cargo run -- --backtrack-stages 10 -o out.png generate 500x500.png

Device:

  • OS: Linux 5.3.0-13
  • Compiler: rustc 1.38.0-nightly

Additional context
Crash backtrace

   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:47
   3: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:36
   4: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:200
   5: std::panicking::default_hook
             at src/libstd/panicking.rs:214
   6: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:477
   7: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:384
   8: rust_begin_unwind
             at src/libstd/panicking.rs:311
   9: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  10: core::panicking::panic
             at src/libcore/panicking.rs:49
  11: core::option::Option<T>::unwrap
             at /rustc/60960a260f7b5c695fd0717311d72ce62dd4eb43/src/libcore/macros.rs:12
  12: image::imageops::sample::horizontal_sample
             at /`hidden`/.cargo/registry/src/github.com-1ecc6299db9ec823/image-0.22.3/./src/imageops/sample.rs:199
  13: image::imageops::sample::resize
             at /`hidden`/.cargo/registry/src/github.com-1ecc6299db9ec823/image-0.22.3/./src/imageops/sample.rs:681
  14: texture_synthesis::img_pyramid::ImagePyramid::build_gaussian
             at lib/src/img_pyramid.rs:29
  15: texture_synthesis::img_pyramid::ImagePyramid::new
             at lib/src/img_pyramid.rs:16
  16: texture_synthesis::Example::resolve
             at lib/src/lib.rs:375
  17: texture_synthesis::SessionBuilder::build
             at lib/src/lib.rs:675
  18: texture_synthesis::real_main
             at cli/src/main.rs:283
  19: texture_synthesis::main
             at cli/src/main.rs:182
  20: std::rt::lang_start::{{closure}}
             at /rustc/60960a260f7b5c695fd0717311d72ce62dd4eb43/src/libstd/rt.rs:64
  21: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:49
  22: std::panicking::try::do_call
             at src/libstd/panicking.rs:296
  23: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:80
  24: std::panicking::try
             at src/libstd/panicking.rs:275
  25: std::panic::catch_unwind
             at src/libstd/panic.rs:394
  26: std::rt::lang_start_internal
             at src/libstd/rt.rs:48
  27: std::rt::lang_start
             at /rustc/60960a260f7b5c695fd0717311d72ce62dd4eb43/src/libstd/rt.rs:64
  28: main
  29: __libc_start_main
  30: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Process finished with exit code 101

Undefined Behavior in Generator::update

This is an awesome tool, thanks for making this available for studying! One minor implementation thing:

In Generator::update you have:

// A little cheat to avoid taking excessive locks.
//
// Access to `coord_map` and `color_map` is governed by values in `self.resolved`,
// in such a way that any values in the former will not be accessed until the latter is updated.
// Since `coord_map` and `color_map` also contain 'plain old data', we can set them directly
// by getting the raw pointers. The subsequent access to `self.resolved` goes through a lock,
// and ensures correct memory ordering.
#[allow(clippy::cast_ref_to_mut)]
unsafe {
    *(self.coord_map.as_ptr() as *mut (Coord2D, MapId)).add(flat_coord.0 as usize) =
        (example_coord, example_map_id);

    *(self.id_map.as_ptr() as *mut (PatchId, MapId)).add(flat_coord.0 as usize) = island_id;

    *(self.color_map.get_pixel(update_coord.x, update_coord.y) as *const image::Rgba<u8>
        as *mut image::Rgba<u8>) = *example_maps[example_map_id.0 as usize]
        .get_pixel(example_coord.x, example_coord.y);
}

Unfortunately, I believe, this is undefined behavior. The documentation for Vec::as_ptr states

"The caller must also ensure that the memory the pointer (non-transitively) points to is never written to (except inside an UnsafeCell) using this pointer or any pointer derived from it."

The problem with UB (here) is not the order of access governance during runtime; but a property of the code during compile time; as a "contract" between the programmer and the compiler are formed regarding what is possible with that pointer.

Although today this might work just fine, any future compiler version (or code change, or different LLVM target backend) could invoke this contract, and exploit the guarantee that e.g., coord_map's backing heap storage "could not" have been changed via the as_ptr() pointer.

When that happens, the program might be 'optimized' in arbitrary ways, basically anything goes.

Possible Solutions

Just some random brainstorming:

  • Put content of the maps into UnsafeCells (might look a bit ugly)
  • Add locks like for other fields (overhead)
  • Take &self as &mut self (probably interferes with the crossbeam_utils::thread::scope closure and needs more rearchitecting)

Misc

Bonus quote from rkruppe since I was unsure about as_ptr myself:

[...] The precise rules for when mutation is allowed and through what pointers are still undecided, but the current best proposals (Ralf Jung's stacked borrows in its various iterations) are not primarily about what references are "floating around" somewhere but about permission to read/write for each part of memory (each of which applies to a subset of pointers and the permissions change as references and pointers get created and used). The code in as_ptr never creates any permission to mutate the Vec's buffer, so writing to it is UB [...]

Force Multi Example Generation

Hello!, I'm testing the multi example generation with two images, but results show predominance of only one.
Is there a way to force the output image to be 50% from the first input image and the other 50% from the second input image?

Basic usage?

Hi there, im a beginner coder. I have downloaded the latest exe from the release and am running it in my CMD on windows 10.
I see the usage is: texture-synthesis.exe [FLAGS] [OPTIONS] --out
Where do I put my input image in this order?
Can you give a few example strings of how I would generate different output images using the methods available?
My image is in the same location as texturesynthesis.exe.

In Painting of Multiple of Maps based on History Maps as per presentation

I'd like to be able to do the texture synthesis on multiple maps the same way, as described on the original talk from Anastasia.

She mentioned there are some dependencies on HDR images and separate executable but I'd like to request that those are also made available.

Thank you so much for your contributions!

Please add to readme manual about how to reproduce "7. Combining texture synthesis 'verbs'"

In provided manual at the moment hard to find out how to reproduce a result from:
"7. Combining texture synthesis 'verbs'' section.

Here is a source image:
nal

Here is a mask file:
nal

And here is a result, which is not even closly nice as the example in readme file :)
nal_1

Could you please help to understand why it is happening?

Command that gave that result:
.\texture-synthesis.exe --inpaint imgs/masks/nal.jpg --in-size 500 --out-size 500 --tiling -o out/nal_1.jpg generate -- imgs/nal.jpg

Investigate musl performance issues

There is a huge performance gap between x86_64-unknown-linux-musl and x86_64-unknown-linux-gnu that needs to be investigated, as we use musl for our pre-built linux binaries.

Doing the same CLI operation shows how severe this performance gap is:

time target/x86_64-unknown-linux-musl/release/texture-synthesis --out out/04-2.png --no-progress transfer-style --style imgs/multiexample/4.jpg --guide imgs/tom.jpg

543.92s user
356.85s system
1808% cpu
49.812 total
time target/release/texture-synthesis --out out/04-2.png --no-progress transfer-style --style imgs/multiexample/4.jpg --guide imgs/tom.jpg

131.32s user
0.25s system
1605% cpu
8.193 total

Looking for maintainers

We at Embark are not actively using or developing these crates and would be open to transferring them to a maintainer or maintainers that would be more active. Please respond in this issue if you are interested.

Very long execution time running the examples

Running the given examples take a lot more time than using the cli version on the same machine.
texture-synthesis --out out/01.jpg generate imgs/1.jpg
took 20 seconds
while
cargo run --example 01_single_example_synthesis
took like 12 minutes with cpu on full throttle.

Device:

  • OS: Os X 10.13.6
  • rustc 1.38.0 (625451e37 2019-09-23)
  • Version 0.6.0 master branch freshly compiled today.

Run the example twice after compilation. Same.
Thanks.
jan

Inpaint error

When using example CLI for texture-synthesis:
.\texture-synthesis.exe --out-size 400 --inpaint imgs/masks/3_inpaint.jpg -o out/05.png generate imgs/3.jpg
I get error:
οΏ½[31merrorοΏ½[0m: the input size (0x0) must match the output size (400x400) when using an inpaint mask
But the mask and image and output are same size 400x400.

Inpaint fails when there is nothing to inpaint

Describe the bug

If inpaint mask is solid white, texture-synthesis just freezes (CPU busy) before showing any progress.

To Reproduce

$ convert -size 100x100 xc:#FFFFFF white.png
$ texture-synthesis --out-size=100x100 --in-size=100x100 --out=w.png --inpaint=white.png generate white.png 
^C

Expected behavior

A picture is generated, probably also fully white.

Support not using filesystem

Currently all of the loading and saving operations or predicated on filesystem paths, but our current use case can actually use remote data sources and never hit disk at all, I need to change the API to support both loading and saving from memory/readers instead.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.