Cloudinary is a cloud-based service that provides solutions for image and video management, including server or client-side upload, on-the-fly image and video manipulations, quick CDN delivery, and a variety of asset management options.
The Neural Artwork Style Transfer add-on takes Cloudinary image transformations to a new level with the style_transfer
effect. This effect applies a complex deep learning neural network algorithm that extracts artistic styles from a source image and applies them to the content of a target photograph.
Before you can use the Neural Art Style Transfer add-on:
You must have a Cloudinary account. If you don't already have one, you can sign up for a free account.
Register for the add-on: make sure you're logged in to your account and then go to the Add-ons page. For more information about add-on registrations, see Registering for add-ons.
Keep in mind that many of the examples on this page use our SDKs. For SDK installation and configuration details, see the relevant SDK guide.
If you are new to Cloudinary, you may want to take a look at How to integrate Cloudinary in your app for a walk through on the basics of creating and setting up your account, working with SDKs, and then uploading, transforming and delivering assets.
Gatys et al is credited with using the VGG neural network to demonstrate how different abstractions of the source and target images can be filtered at different layers, so that the essential elements of the input image can be applied without losing the essence of the target content. Cloudinary's algorithm takes advantage of Xun Huange and Serge Belongie's enhancement on the Gatys algorithm, which make it possible to use any image for both source and target, and still deliver a good quality style transfer in real time, using a single feed-forward neural network.
To apply this style transfer effect on any photograph, specify the public ID of the source artwork as an image overlay (l_
in URLs) and style_transfer
as the overlay effect
(e_style_transfer
in URLs). The target photograph is the public ID of the image to deliver.
In the example below, the styles of the Sailing Angel artwork are transferred to the Golden Gate Bridge photo:
Ruby:
cl_image_tag("golden_gate.jpg", :transformation=>[
{:width=>700, :height=>700, :crop=>"fill"},
{:effect=>"style_transfer", :overlay=>"sailing_angel"}
])
PHP v1:
cl_image_tag("golden_gate.jpg", array("transformation"=>array(
array("width"=>700, "height"=>700, "crop"=>"fill"),
array("effect"=>"style_transfer", "overlay"=>"sailing_angel")
)))
PHP v2:
(new ImageTag('golden_gate.jpg'))
->resize(Resize::fill()->width(700)->height(700))
->effect(Effect::styleTransfer(Source::image('sailing_angel')));
Python:
CloudinaryImage("golden_gate.jpg").image(transformation=[
{'width': 700, 'height': 700, 'crop': "fill"},
{'effect': "style_transfer", 'overlay': "sailing_angel"}
])
Node.js:
cloudinary.image("golden_gate.jpg", {transformation: [
{width: 700, height: 700, crop: "fill"},
{effect: "style_transfer", overlay: "sailing_angel"}
]})
Java:
cloudinary.url().transformation(new Transformation()
.width(700).height(700).crop("fill").chain()
.effect("style_transfer").overlay(new Layer().publicId("sailing_angel"))).imageTag("golden_gate.jpg");
JS:
cloudinary.imageTag('golden_gate.jpg', {transformation: [
{width: 700, height: 700, crop: "fill"},
{effect: "style_transfer", overlay: new cloudinary.Layer().publicId("sailing_angel")}
]}).toHtml();
jQuery:
$.cloudinary.image("golden_gate.jpg", {transformation: [
{width: 700, height: 700, crop: "fill"},
{effect: "style_transfer", overlay: new cloudinary.Layer().publicId("sailing_angel")}
]})
React:
<Image publicId="golden_gate.jpg" >
<Transformation width="700" height="700" crop="fill" />
<Transformation effect="style_transfer" overlay="sailing_angel" />
</Image>
Vue.js:
<cld-image publicId="golden_gate.jpg" >
<cld-transformation width="700" height="700" crop="fill" />
<cld-transformation effect="style_transfer" :overlay="sailing_angel" />
</cld-image>
Angular:
<cl-image public-id="golden_gate.jpg" >
<cl-transformation width="700" height="700" crop="fill">
</cl-transformation>
<cl-transformation effect="style_transfer" overlay="sailing_angel">
</cl-transformation>
</cl-image>
.NET:
cloudinary.Api.UrlImgUp.Transform(new Transformation()
.Width(700).Height(700).Crop("fill").Chain()
.Effect("style_transfer").Overlay(new Layer().PublicId("sailing_angel"))).BuildImageTag("golden_gate.jpg")
iOS:
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
.setWidth(700).setHeight(700).setCrop("fill").chain()
.setEffect("style_transfer").setOverlay("sailing_angel")).generate("golden_gate.jpg")!, cloudinary: cloudinary)
Android:
MediaManager.get().url().transformation(new Transformation()
.width(700).height(700).crop("fill").chain()
.effect("style_transfer").overlay(new Layer().publicId("sailing_angel"))).generate("golden_gate.jpg");
Kotlin:
cloudinary.image {
publicId("golden_gate.jpg")
resize(Resize.fill() {
width(700)
height(700)
})
effect(Effect.styleTransfer(Source.image("sailing_angel")))}.generate()
Source artwork
Target photo
Style transfer result
To apply this transformation using the Media Library, first select to
Add overlay & watermark and specify the source artwork's
Image ID. Then select
Style transfer as the effect of the overlay image.
The algorithm is able to recognize styles in the source painting, such as brush stroke style, textures, and dominant colors. It can then apply those styles to the content elements of the target photograph. In the resulting image, there is some content loss, and some style loss, but the neural network algorithm optimizes these losses so that the main elements of the artwork's style come through while ensuring that the content of the target photo is clearly recognizable.
- If you want to retain the target photograph's colors, you can include the
preserve_color
option.
- If you want to control how much of the style from the source painting is transferred, you can adjust the
style_strength
(1-100, default: 100).
For example, if you transfer the styles of the lighthouse source artwork to the beach_2_kids target photo, you clearly get a result that is heavily influenced by the lighthouse image's colors and brushstroke styles:
Source artwork
Target photo
Default style transfer
Now take a look at the next three images to see how the result changes with the use of the adjustment settings:
Preserve original colors
Adjust style strength
to 60
Adjust strength and
preserve colors
Here's the transformation code for that last image, using both the preserve_color
and style_strength
options:
Ruby:
cl_image_tag("beach_2_kids.jpg", :transformation=>[
{:height=>700, :width=>700, :crop=>"fill"},
{:effect=>"style_transfer:preserve_color:40", :overlay=>"lighthouse"}
])
PHP v1:
cl_image_tag("beach_2_kids.jpg", array("transformation"=>array(
array("height"=>700, "width"=>700, "crop"=>"fill"),
array("effect"=>"style_transfer:preserve_color:40", "overlay"=>"lighthouse")
)))
PHP v2:
(new ImageTag('beach_2_kids.jpg'))
->resize(Resize::fill()->width(700)->height(700))
->effect(Effect::styleTransfer(Source::image('lighthouse'))
->preserveColor()->strength(40));
Python:
CloudinaryImage("beach_2_kids.jpg").image(transformation=[
{'height': 700, 'width': 700, 'crop': "fill"},
{'effect': "style_transfer:preserve_color:40", 'overlay': "lighthouse"}
])
Node.js:
cloudinary.image("beach_2_kids.jpg", {transformation: [
{height: 700, width: 700, crop: "fill"},
{effect: "style_transfer:preserve_color:40", overlay: "lighthouse"}
]})
Java:
cloudinary.url().transformation(new Transformation()
.height(700).width(700).crop("fill").chain()
.effect("style_transfer:preserve_color:40").overlay(new Layer().publicId("lighthouse"))).imageTag("beach_2_kids.jpg");
JS:
cloudinary.imageTag('beach_2_kids.jpg', {transformation: [
{height: 700, width: 700, crop: "fill"},
{effect: "style_transfer:preserve_color:40", overlay: new cloudinary.Layer().publicId("lighthouse")}
]}).toHtml();
jQuery:
$.cloudinary.image("beach_2_kids.jpg", {transformation: [
{height: 700, width: 700, crop: "fill"},
{effect: "style_transfer:preserve_color:40", overlay: new cloudinary.Layer().publicId("lighthouse")}
]})
React:
<Image publicId="beach_2_kids.jpg" >
<Transformation height="700" width="700" crop="fill" />
<Transformation effect="style_transfer:preserve_color:40" overlay="lighthouse" />
</Image>
Vue.js:
<cld-image publicId="beach_2_kids.jpg" >
<cld-transformation height="700" width="700" crop="fill" />
<cld-transformation effect="style_transfer:preserve_color:40" :overlay="lighthouse" />
</cld-image>
Angular:
<cl-image public-id="beach_2_kids.jpg" >
<cl-transformation height="700" width="700" crop="fill">
</cl-transformation>
<cl-transformation effect="style_transfer:preserve_color:40" overlay="lighthouse">
</cl-transformation>
</cl-image>
.NET:
cloudinary.Api.UrlImgUp.Transform(new Transformation()
.Height(700).Width(700).Crop("fill").Chain()
.Effect("style_transfer:preserve_color:40").Overlay(new Layer().PublicId("lighthouse"))).BuildImageTag("beach_2_kids.jpg")
iOS:
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
.setHeight(700).setWidth(700).setCrop("fill").chain()
.setEffect("style_transfer:preserve_color:40").setOverlay("lighthouse")).generate("beach_2_kids.jpg")!, cloudinary: cloudinary)
Android:
MediaManager.get().url().transformation(new Transformation()
.height(700).width(700).crop("fill").chain()
.effect("style_transfer:preserve_color:40").overlay(new Layer().publicId("lighthouse"))).generate("beach_2_kids.jpg");
Kotlin:
cloudinary.image {
publicId("beach_2_kids.jpg")
resize(Resize.fill() {
width(700)
height(700)
})
effect(Effect.styleTransfer(Source.image("lighthouse")) {
preserveColor()
strength(40)
})}.generate()
The Neural Artwork add-on supports generating images with the style_transfer
effect for any resolution up to 3000x3000, and it's capable of rendering the new image very quickly even at large sizes. However, because of the way the algorithm analyzes the content of the target photo, you will get different results for different sizes of the target photo. Also, keep in mind that the neural network algorithm behind our Neural Artwork add-on was initially designed for optimum output of images at resolutions in the range of 600x600 - 800x800.
Therefore, when this optimum resolution range is appropriate for your intended usage, use resize or cropping transformations to bring the target photo into this range in one transformation component, and then apply the style_transfer
effect in a later transformation component.
For example: ....w_700/e_style_transfer,l_your_artwork/your_target_photo.jpg
Likewise, if you want to output images that are significantly smaller than the above recommended resolution range, you may want to apply the style_transfer
effect in an earlier transformation component, and then apply the resizing to the small size in a later transformation component.
For example: ....w_700/e_style_transfer,l_your_artwork/w_200/your_target_photo.jpg
Cloudinary's dynamic image manipulation URLs are powerful tools for agile web and mobile development. However, due to the potential costs of your customers accessing unplanned dynamic URLs that apply the neural art algorithm, image manipulation add-on URLs are required (by default) to be signed using Cloudinary's authenticated API or, alternatively, you can eagerly generate the requested derived images using Cloudinary's authenticated API.
To create a signed Cloudinary URL, set the sign_url
parameter to true when building a URL or creating an image tag.
The following code example generates a neural artwork by overlaying the davinci_mona_lisa
artwork with the coffee_cup_st
photo, including a signed Cloudinary URL:
Ruby:
cl_image_tag("coffee_cup_st.jpg", :effect=>"style_transfer", :overlay=>"davinci_mona_lisa", :sign_url=>true)
PHP v1:
cl_image_tag("coffee_cup_st.jpg", array("effect"=>"style_transfer", "overlay"=>"davinci_mona_lisa", "sign_url"=>true))
PHP v2:
(new ImageTag('coffee_cup_st.jpg'))
->effect(Effect::styleTransfer(Source::image('davinci_mona_lisa')))
->signUrl(true);
Python:
CloudinaryImage("coffee_cup_st.jpg").image(effect="style_transfer", overlay="davinci_mona_lisa", sign_url=True)
Node.js:
cloudinary.image("coffee_cup_st.jpg", {effect: "style_transfer", overlay: "davinci_mona_lisa", sign_url: true})
Java:
cloudinary.url().transformation(new Transformation().effect("style_transfer").overlay(new Layer().publicId("davinci_mona_lisa"))).signed(true).imageTag("coffee_cup_st.jpg");
JS:
cloudinary.imageTag('coffee_cup_st.jpg', {effect: "style_transfer", overlay: new cloudinary.Layer().publicId("davinci_mona_lisa"), signUrl: true}).toHtml();
jQuery:
$.cloudinary.image("coffee_cup_st.jpg", {effect: "style_transfer", overlay: new cloudinary.Layer().publicId("davinci_mona_lisa")})
React:
<Image publicId="coffee_cup_st.jpg" signUrl="true">
<Transformation effect="style_transfer" overlay="davinci_mona_lisa" />
</Image>
Vue.js:
<cld-image publicId="coffee_cup_st.jpg" signUrl="true">
<cld-transformation effect="style_transfer" :overlay="davinci_mona_lisa" />
</cld-image>
Angular:
<cl-image public-id="coffee_cup_st.jpg" sign-url="true">
<cl-transformation effect="style_transfer" overlay="davinci_mona_lisa">
</cl-transformation>
</cl-image>
.NET:
cloudinary.Api.UrlImgUp.Transform(new Transformation().Effect("style_transfer").Overlay(new Layer().PublicId("davinci_mona_lisa"))).Signed(true).BuildImageTag("coffee_cup_st.jpg")
iOS:
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setEffect("style_transfer").setOverlay("davinci_mona_lisa")).generate("coffee_cup_st.jpg", signUrl: true)!, cloudinary: cloudinary)
Android:
MediaManager.get().url().transformation(new Transformation().effect("style_transfer").overlay(new Layer().publicId("davinci_mona_lisa"))).signed(true).generate("coffee_cup_st.jpg");
Kotlin:
cloudinary.image {
publicId("coffee_cup_st.jpg")
effect(Effect.styleTransfer(Source.image("davinci_mona_lisa")))
signUrl(true)}.generate()
The generated Cloudinary URL shown below includes a signature component (/s--yNvfjq2e--/
). Only URLs with a valid signature that matches the requested image manipulation will be approved for on-the-fly image manipulation and delivery.
For more details on signed URLs, see Signed delivery URLs.
You can optionally remove the signed URL default requirement for a particular add-on by selecting it in the
Allow unsigned add-on transformations section of the
Security account settings in the Cloudinary console.
|
2 Pick a target photo below OR Upload your own
|
3 Press the magic button:
Generate Neural Artwork
|
You can create even more unique results by combining the Neural Artwork style_transfer
effect with other transformations. For details, see Image transformations and the Transformation URL API Reference.