如何计算叠加图像的旋转角度,使其恰好适合底层图像的对角线?

How to calculate the rotation angle for an overlying image, so that it just fits diagonally iniside an underlying image?

我想在多张图片上斜放水印。这些图片的宽度和长度各不相同,有些甚至比水印本身还小。

这将在脚本中使用,用户可以在脚本中选择不同的选项,例如 "horizontal"、"vertical"、"diagonal" 或通过 himself/herself 指定角度.因此我需要计算旋转角度。
角度应该

它看起来像 this。 (我也画了对角线。)
如您所见,上层图片刚好适合下层图片。如果我选择其他角度,叠加图像会变小。

我已经计算了底层图像的对角线,然后计算了相应的角度。问题是长度不一定最大化,如 here.

我在 Ubuntu Linux.

上使用 ImageMagick 6.8.9-9 Q16 x86_64

这是没有计算的 bash 代码(正如我所说,它运行不佳)。请注意,代码实际上是通过 Python3 执行的。我发现 shell 命令在 bash.

中更容易阅读
for pic in *
do
    # if there transparency around the picture, remove it and get the dimensions
    size_ui=`convert -density 300 "$pic" -page a4 -bordercolor none -border 1x1 -trim +repage jpg:- | identify -format "%wx%h" -`

    # get dimensions of the watermark (in case it changes over time)
    size_wm=`identify -format "%wx%h" "wm.png"`

    degree=`CALCULATE_THE_PERFECT_ANGLE`

    # center the watermark, rotate it and resize it to the same size as the underlying picture
    convert -density 300 "$pic" -page a4 \( "wm.png" -background none -gravity center -rotate "$degree" -resize "$size_ui" \) -compose over -composite "${pic%%.*}.jpg"
done

我很确定这个问题已经在 Whosebug 的某个地方解决了,但到目前为止还找不到任何东西。

此致
阿福

让我们有宽度 W 和高度 H 的基础矩形,比例 K=H/W 和旋转的矩形,宽度和高度未知但比例固定 k=h/w

我在图片上标出了相似的角度f。我们可以看到

 H = h * cos(f) + w * sin(f)
 W = h * sin(f) + w * cos(f)
 or
 K * W = k * w * cos(f) + w * sin(f)
 W = k * w * sin(f) + w * cos(f)
 divide the first by the second
 K = (k * cos(f) + sin(f)) / (k * sin(f) + cos(f))
 divide denominator and nominator by cos(f)
 K = (k + tg(f)) / (k * tg(f) + 1)
 K * (k * tg(f) + 1) = k + tg(f)
 K * k * tg(f) + K = k + tg(f)
 tg(f) * (1 - K * k) = K - k

结果是

 tg(f)  = (K - k) / (1 - K * k)
 f = atan((K - k) / (1 - K * k))

快速检查:正方形 K=1 和任何 k<1 tg(f)=1,因此 f = Pi/4(45 度)

注意并不是所有的k和k的组合都有意义

此 ImageMagick 命令应采用任何输入图像 $pic 和任何覆盖图像 $wmark,将覆盖旋转到 $angle,将其调整大小以适应输入图像的最大可能尺寸,然后合成以 $wmark 为中心的覆盖输入图像。

convert $pic -density 300 -background none \( $wmark -rotate $angle \) \
   +distort SRT \
      "%[fx:(u.w<v.w&&u.h<v.h)&&t?min(min(u.w/v.w,v.w/u.w),min(u.h/v.h,v.h/u.h)):1] 0" \
   -shave 1x1 \
   +distort SRT \
      "%[fx:(u.w>v.w||u.h>v.h)&&t?min(max(u.w/v.w,v.w/u.w),max(u.h/v.h,v.h/u.h)):1] 0" \
   -shave 1x1 \
      -gravity center -compose over -composite $result

读取您的输入图像并设置密度和背景颜色。然后在括号内读取叠加图像并将其旋转 $angle 度数。

之后是两个“+扭曲”操作。两者都按原样保留主输入图像并有条件地缩放叠加图像。如果覆盖比输入图像大,第一个“+distort”会缩小覆盖。如果覆盖小于主输入,则第二个放大覆盖。在任何一种情况下,叠加层都会缩放到适合主输入图像的最大尺寸。

当然,您必须在 运行 命令之前设置 $pic、$wmark 和 $angle 变量的值。此外,如果您需要对输入图像执行任何操作,例如 trim 或调整大小,请在命令中但在读取叠加图像之前执行此操作。

请注意,使用“+distort”会在每条边上添加一个像素,因此每次操作后都会使用“-shave 1x1”移除这些像素。