Jaggy results with using maps for perspective transform

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
perspector
Posts: 7
Joined: 2020-02-17T06:18:13-07:00
Authentication code: 1152

Jaggy results with using maps for perspective transform

Post by perspector »

Hi!

I’m trying to use image maps to get input images into perspective, positioned, cropped and later on also curved/warped in one go. This works in principle, but the results have terrible quality.

Empty template:
Image

Mock page for testing purposes:
Image

Map “front” as exported from Inkscape:
Image

Map “verso”:
Image

Map “recto”:
Image

Result:
Image


The only way I found to get the mapping right, is to first resize input images to the size of the maps. Is there another option?

The core of it:

Code: Select all

convert ${!p} -resize $size\! -matte "maps/$p.png" -compose Distort -composite "intermediate/$p.png"
The full script:

Code: Select all

#! /bin/bash


# PARAMETERS

map_src_svg="map_src.svg"
template="input/template.png"
product_base="input/test"
output="test_render.png"


# SETUP

front="$product_base"".png"  # Front page
verso="$front"               # Inner left
recto="$front"               # Inner right

parts=(
    front
    verso
    recto
)

mkdir -p maps
mkdir -p intermediate

# Store resolution of the template:
size=$(convert "$template" \
	       -format "%wx%h" info:)


# EXPORT MAPS

# Export only the map by ID, but as it is positioned on the page, to not have to
# deal with coordinates.
for p in "${parts[@]}"; do
    inkscape --export-area-page --export-id-only --export-id="$p" \
	     --export-png="maps/$p.png" "$map_src_svg"
done


# RENDER

# Resize inputs to template resolution, as otherwise the result will be cropped
# to the original input resolution. Then apply distortion.
for p in "${parts[@]}"; do
    # ${!p} resolves to the variables from setup,
    # i.e. paths to the productimages
    convert ${!p} -resize $size\! -matte "maps/$p.png" -compose Distort \
	    -composite "intermediate/$p.png"
done

# Compose final image, lowest layer is listed first. There’s likely more than
# one way to do this within one incantation, but I couldn’t figure out, how!
convert -composite -compose multiply "$template" "intermediate/verso.png" "1.png"
convert	-composite -compose multiply "1.png" "intermediate/recto.png" "2.png"
convert	-composite -compose multiply "2.png" "intermediate/front.png" "$output"

convert "$output" ${output%".png"}.jpg


# CLEANUP

rm 1.png 2.png

snibgo
Posts: 12904
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Jaggy results with using maps for perspective transform

Post by snibgo »

You are generating a map from an SVG, then downsampling an image to that size, and distorting. Is that right? Is the SVG file just wrapper for a raster image, or a genuine vector image?

Instead of downsampling then distorting, you will get a better result if you distort then downsample.

The result may be even better if you supersample the image and map before distorting (ie enlarge them). If the SVG file is vector, then tell Inkscape to make a larger PNG.
snibgo's IM pages: im.snibgo.com

User avatar
fmw42
Posts: 26269
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Jaggy results with using maps for perspective transform

Post by fmw42 »

Why go to all the trouble of a map solution when you can do perspective directly with -distort and high quality sampling?

snibgo
Posts: 12904
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Jaggy results with using maps for perspective transform

Post by snibgo »

Yes, as Fred says, if you can distort without using a map, the result will be better, without having to supersample.
snibgo's IM pages: im.snibgo.com

perspector
Posts: 7
Joined: 2020-02-17T06:18:13-07:00
Authentication code: 1152

Re: Jaggy results with using maps for perspective transform

Post by perspector »

snibgo: Yes, one SVG, completely vector with gradient-meshes for the maps.

Without downsampling to map-size first, this happens:
Image

Earlier attempts with the maps at x2 and x4 the size showed very little improvement.

fmw42: Because the templates include paper with a slight bend. I can tweak the gradient-meshes accordingly.

snibgo
Posts: 12904
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Jaggy results with using maps for perspective transform

Post by snibgo »

perspector wrote:Without downsampling to map-size first, this happens: ...
I suggest you upsample the map, then distort, then downsample as needed.

As the map comes from a vector SVG, you should tell IM to make a larger PNG. I suppose this is the "--export-dpi" option.
snibgo's IM pages: im.snibgo.com

perspector
Posts: 7
Joined: 2020-02-17T06:18:13-07:00
Authentication code: 1152

Re: Jaggy results with using maps for perspective transform

Post by perspector »

Yes, that’s what I tried already: increase --export-dpi to n-times the size, scale input images to that maps size, distort, downsample. Did so with n = 2, 4 and 8. Always coarse results.

However, a solution is in sight: I opened the front map in GIMP, changed the precision from 8 bits to 16 bits and applied Gaussian blur, radius 2. With that map, I got smooth results (aside of some staircasing at those really mean diagonal lines):
Image

Either I have to switch to Inkscape 1.0beta to be able to export to 16 bits directly, or do some equivalent of the GIMP operation with imagemagick.

snibgo, fmw42: thank you for your thoughts!


UPDATE: I grabbed the Inkscape 1.0beta2 AppImage and exported at 16 bits. It looked as bad as before, until I added the 2px blur!

snibgo
Posts: 12904
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Jaggy results with using maps for perspective transform

Post by snibgo »

perspector wrote:I opened the front map in GIMP, changed the precision from 8 bits to 16 bits and applied Gaussian blur, radius 2.
You can do those operations in IM.

I should have checked for that obvious problem. Distortion maps should never be 8-bit precision. If they are, quantisation gives an expected error of 1 part in 512, so images around 512x512 pixels or larger will have every pixel in the wrong place.

Note that smoothing (by blur) won't actually correct quantisation error. But it will spread errors across neighbouring pixels so they are not so noticeable.
snibgo's IM pages: im.snibgo.com

perspector
Posts: 7
Joined: 2020-02-17T06:18:13-07:00
Authentication code: 1152

Re: Jaggy results with using maps for perspective transform

Post by perspector »

With Inkscape 1.0beta2 16 bit export leading to the same artifacts, this likely means that the gradients aren't actually rendered at 16 bits, right?

When using IM to convert from 8 to 16 bits per channel, is there an option that will improve results? Afterwards, is there an operation that should lead to better results than a 2px gaussian blur?

snibgo
Posts: 12904
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Jaggy results with using maps for perspective transform

Post by snibgo »

perspector wrote:With Inkscape 1.0beta2 16 bit export leading to the same artifacts, this likely means that the gradients aren't actually rendered at 16 bits, right?
Possibly. IM "identify -verbose" will tell you whether the map image has more than 8 significant bits. But that wouldn't prove the bits are accurate. I don't know the internals of Inkscape.

Blurring will spread the errors. More spreading (eg -blur 0x4, -blur 0x10) is better, as we can expect errors in a larger area to cancel each other out. However, getting a correct map from the start is better still.

Can you link to a sample SVG? Perhaps IM can render it without Inkscape, or perhaps the SVG can be changed to use IM operations.
snibgo's IM pages: im.snibgo.com

snibgo
Posts: 12904
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Jaggy results with using maps for perspective transform

Post by snibgo »

See also Straightening horizons: How much precision?. I did those tests with IM v6. They show that Q8 integer is really horrible, Q16 integer or HDRI is better, but Q32 is best for that example.
snibgo's IM pages: im.snibgo.com

perspector
Posts: 7
Joined: 2020-02-17T06:18:13-07:00
Authentication code: 1152

Re: Jaggy results with using maps for perspective transform

Post by perspector »

“identity -verbose” told me that there are indeed only 8 significant bits. I recall from issues with gradient banding that the problem sits further down the graphics stack, actually.

IM can render these, but I guess because it is using Inkscape to do so. The result is them same, regarding bit-depth. Mesh gradients are not a finalized part of SVG; Firefox and Chromium won’t render them, for example.

The SVG:
https://www.dropbox.com/s/zdv8n9cvp59dw ... c.svg?dl=0
There are only slight curves in this one, but the ability to have them and to edit visually is important.

User avatar
magick
Site Admin
Posts: 11217
Joined: 2003-05-31T11:32:55-07:00

Re: Jaggy results with using maps for perspective transform

Post by magick »

Try this command:

Code: Select all

convert -density 400 map_src.svg -resize 25% map_src.png

perspector
Posts: 7
Joined: 2020-02-17T06:18:13-07:00
Authentication code: 1152

Re: Jaggy results with using maps for perspective transform

Post by perspector »

magick: thanks, but I tried that before, it does not help. So far, I’m happy with the results I get with changing bit depth and 2px blur. Of course Inkscape (or something else offering the same editability) rendering true 16 bit mesh gradients would be better.

User avatar
fmw42
Posts: 26269
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Jaggy results with using maps for perspective transform

Post by fmw42 »

More properly, to get the same size output, use a density factor times 72 and then resize by the inverse factor. For example 4*72 and 1/4=25%

Code: Select all

convert -density 288 map_src.svg -resize 25% map_src.png

Post Reply