14个版本
0.8.3 | 2022年2月7日 |
---|---|
0.8.2 | 2021年3月26日 |
0.8.1 | 2020年11月17日 |
0.8.0 | 2020年2月26日 |
0.7.1 | 2019年11月19日 |
#130 在 图像
每月162次 下载
140KB
3K SLoC
🎨 texture-synthesis
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
功能和示例
1. 单个示例生成
从单个示例生成相似外观的图像。
API - 01_single_example_synthesis
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运行 --发布 ----out out/01.jpg 生成 imgs/1.jpg
您应该得到以下结果,使用本仓库提供的图像
2. 多个示例生成
我们还可以提供多个示例图像,算法将“混搭”它们生成新图像。
API - 02_multi_example_synthesis
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运行 --发布 ----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
您应该得到以下结果,使用本仓库提供的图像
3. 引导合成
我们还可以通过提供“从...到...”的转换“引导图”来引导生成。
API - 03_guided_synthesis
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运行 --发布 ---o out/03.png generate --target-guide imgs/masks/2_target.jpg --guides imgs/masks/2_example.jpg -- imgs/2.jpg
注意:注意使用--
来分隔到示例imgs/2.jpg
的路径,如果不指定--
,示例的路径将被用作另一个引导路径,并且将没有示例。
您应该得到以下结果,使用本仓库提供的图像
4. 风格迁移
纹理合成API支持自动生成示例引导图,产生类似风格迁移的效果。
API - 04_style_transfer
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运行 --发布 ----alpha 0.8 -o out/04.png transfer-style --style imgs/multiexample/4.jpg --guide imgs/tom.jpg
您应该得到以下结果,使用本仓库提供的图像
5. 填充
我们还可以使用填充来填补缺失的信息。通过更改种子,我们将获得不同版本的“填充”。
API - 05_inpaint
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
请注意,在填充时使用--out-size
参数确定所有输入和输出的尺寸!
cargo运行 --发布 ----out-size 400 --inpaint imgs/masks/3_inpaint.jpg -o out/05.png generate imgs/3.jpg
您应该得到以下结果,使用本仓库提供的图像
6. 填充通道
我们不必使用单独的图像作为填充掩码,而是可以从特定的通道中获取信息。在这个例子中,alpha通道是图像中间的一个圆。
API - 06_inpaint_channel
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运行 --发布 ----inpaint-channel a -o out/06.png generate imgs/bricks.jpg
您应该得到以下结果,使用本仓库提供的图像
7. 平铺纹理
我们可以使生成的图像平铺(这意味着如果将多个图像并排放置,则不会有接缝)。通过同时调用填充模式和平铺,我们可以使现有的图像平铺。
API - 07_tiling_texture
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运行 --发布 ----inpaint imgs/masks/1_tile.jpg --out-size 400 --tiling -o out/07.bmp generate imgs/1.jpg
您应该得到以下结果,使用本仓库提供的图像
8. 在新图像上重复纹理合成变换
我们可以将纹理合成执行的坐标变换重新应用于新图像。
API - 08_repeat_transform
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
- 首先,我们需要创建一个可重复使用的变换
这里值得注意的是--save-transform out/multi.xform
,它创建了一个文件,可以用它来生成新的输出。
cargo运行 --发布 ----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
- 接下来,我们使用
repeat
子命令重复变换与不同的输入
这里值得注意的是使用repeat
子命令而不是generate
,以及--transform out/multi.xform
,它告诉应用于输入的变换。唯一的限制是您指定的图像数量必须与原始示例数量完全相同。如果输入图像的尺寸与示例图像不同,它们将自动为您调整尺寸。
cargo运行 --发布 ---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
请注意,与generate
一起使用的正常参数不适用于repeat
子命令,并且将被忽略。
9. 样本掩码
样本掩码允许您指定在生成过程中如何采样示例图像。
API - 09_sample_masks
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运行 --发布 ----seed 211 --out-size 200 --sample-masks IGNORE ALL --out 09_sample_masks.png generate imgs/4.png imgs/5.png
您应该得到以下结果,使用本仓库提供的图像
10. 组合纹理合成“动词”
我们还可以将多种模式组合在一起。例如,多示例引导合成
或将生成多个阶段串联起来
有关更多用例和示例,请参阅演示文稿 "更多类似这样的,请!从单个示例进行纹理合成和混搭"
额外的 CLI 功能
某些功能仅通过 CLI 暴露,并未集成到库中。
翻转和旋转
此子命令将每个示例翻转和旋转,以生成额外的示例输入用于生成。此子命令不支持目标或示例引导。
示例: cargo run --release -- -o out/output.png flip-and-rotate imgs/1.jpg
命令行二进制文件
- 为您的操作系统下载二进制文件。
- 或者 从源代码安装。
- 打开终端
- 导航到您下载二进制文件的目录,如果您没有直接运行
cargo install
- 运行
texture_synthesis --help
以获取您可以运行的所有选项和命令列表 - 请参阅此说明文档中的示例部分以获取运行二进制文件的示例
注意事项
- 默认情况下,生成输出将使用您所有的逻辑核心
- 当使用多个线程进行生成时,输出图像不一定具有相同的输入的可确定性。为了达到 100% 的可确定性,您必须使用一个线程数,这可以通过以下方式完成
- CLI -
texture-synthesis --threads 1
- API -
SessionBuilder::max_thread_count(1)
- CLI -
限制
- 处理超出像素颜色之外复杂语义的能力有限(除非您引导它)
- 对于常规纹理表现不佳(接缝可能变得明显)
- 不能从现有信息中推断新信息(仅操作已存在的信息)
- 设计用于单个示例或非常小的数据集(与基于深度学习的方法不同)
其他依赖项
如果您正在为 Linux 编译,则需要安装 libxkbcommon
开发库。对于 Ubuntu,这是 libxkbcommon-x11-dev
。
链接/参考
[1] [Opara & Stachowiak] "更多类似这样的,请!从单个示例进行纹理合成和混搭"
[2] [Harrison] 图像纹理工具
[3] [Ashikhmin] 自然纹理合成
[4] [Efros & Leung] 基于非参数采样的纹理合成
【5】 [Wey & Levoy] 使用树结构矢量量化进行快速纹理合成
【6】 [De Bonet] 用于纹理图像分析和合成的多分辨率采样过程
【7】 本仓库中所有测试图像均来自 Unsplash
贡献
我们欢迎社区为此项目做出贡献。
请阅读我们的 贡献指南 了解如何开始。
许可
以下任一许可下提供:
- Apache License, Version 2.0, (LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确声明,否则您提交给作品以包含在内的任何贡献,根据 Apache-2.0 许可定义,将如上双许可,不附加任何额外条款或条件。
依赖项
~14–23MB
~167K SLoC