如何使用 FFMPEG+Imagemagick 从 image/video 中提取有组织的调色板?

How to extract organized palette from image/video with FFMPEG+Imagemagick?

我使用 FFMPEG 和 Imagemagick 通过 Windows 批处理文件从图像或视频中提取调色板,

:: get current folder name
for %%* in (.) do set CurrDirName=%%~nx*

:: get current filename
for /R %1 %%f in (.) do (
    set CurrFileName=%%~nf
)

ffmpeg -i "%1" -vf palettegen "_%CurrFileName%_temp_palette.png"
convert "_%CurrFileName%_temp_palette.png" -filter point -resize 4200%% "_%CurrFileName%_palette.png"

del "_%CurrFileName%_temp_palette.png"

这输出类似,

我需要它在整个色块中有更好的过渡,就像所有的蓝色从最暗到最亮然后过渡到绿色、黄色等,比如,

是否有 way/switch 可以用 Imagemagick/FFMPEG 创建这个?

我不喜欢研究 Windows,但我想向您展示一种您可以使用的技术。因此,我用 bash 编写了它,但几乎避免了所有 Unix-y 的内容,并使它变得非常简单。为了在 Windows 上 运行 它,您只需要 ImageMagick 和 awk 以及 sort,您可以从 here and here 获得 Windows。

我将使用脚本在第三行附近创建的随机数据图像进行演示:

这是脚本。它的评论很好,如果您喜欢它的功能,应该很容易转换为 Windows。

#!/bin/bash

# Create an initial image of random data 100x100
convert -size 100x100 xc:gray +noise random image.png

# Extract unique colours in image and convert to HSL colourspace and thence to text for "awk"
convert image.png -unique-colors -colorspace hsl -depth 8 txt: | awk -F"[(), ]+" '
!/^#/{
       H=; S=; L=            # Pick up HSL. For Hue, 32768=180deg, 65535=360deg. For S&L, 32768=50%, 65535=100%
       NGROUPS=4                   # Change this according to the number of groups of colours you want
       bin=65535/NGROUPS           # Calculate bin size
       group=int(int(H/bin)*bin)   # Split Hue into NGROUPS
       printf "%d %d %d %d\n",group,H,S,L
     }' > groupHSL.txt

# Sort by column 1 (group) then by column 4 (Lightness)
sort -n -k1,1 -k4,4 < groupHSL.txt > groupHSL-sorted.txt

# Reassemble the sorted pixels back into a simple image, 16-bit PNM format of HSL data
# Discard the group in column 1 () that we used to sort the data
awk '  { H[++i]=; S[i]=; L[i]= }
  END  {
           printf "P3\n"
           printf "%d %d\n",i,1
           printf "65535\n"
           for(j=1;j<=i;j++){
              printf "%d %d %d\n",H[j],S[j],L[j]
           }
        }' groupHSL-sorted.txt > HSL.pnm

# Convert HSL.pnm to sRGB.png
convert HSL.pnm -set colorspace hsl -colorspace sRGB sRGB.png

# Make squareish shape
convert sRGB.png -crop 1x1 miff:- | montage -geometry +0+0 -tile 40x - result.png

如果我将 NGROUPS 设置为 10,我得到:

如果我将 NGROUPS 设置为 4,我得到:

请注意,脚本生成中间文件而不是使用管道和 shell 技巧,因此您可以轻松查看处理的每个阶段以便对其进行调试。

例如,如果您 运行 这个:

convert image.png -unique-colors -colorspace hsl -depth 8 txt: | more

您将看到 convert 传递给 awk 的输出:

# ImageMagick pixel enumeration: 10000,1,255,hsl
0,0: (257,22359,1285)  #015705  hsl(1.41176,34.1176%,1.96078%)
1,0: (0,0,1542)  #000006  hsl(0,0%,2.35294%)
2,0: (41634,60652,1799)  #A2EC07  hsl(228.706,92.549%,2.7451%)
3,0: (40349,61166,1799)  #9DEE07  hsl(221.647,93.3333%,2.7451%)
4,0: (31868,49858,2056)  #7CC208  hsl(175.059,76.0784%,3.13725%)
5,0: (5140,41377,3341)  #14A10D  hsl(28.2353,63.1373%,5.09804%)
6,0: (61423,59367,3598)  #EFE70E  hsl(337.412,90.5882%,5.4902%)

如果你看一下 groupHSL-sorted.txt,你会看到像素是如何被分类成组然后增加亮度的:

0 0 53456 10537
0 0 18504 20303
0 0 41377 24158
0 0 21331 25700
0 0 62708 28270
0 0 53199 31354
0 0 23130 32896
0 0 8738 33410
0 0 44204 36494
0 0 44204 36751
0 0 46260 38293
0 0 56283 40606
0 0 53456 45489
0 0 0 46517
0 0 32896 46517
0 0 16191 50372
0 0 49601 55769
0 257 49601 11565
0 257 42148 14392
0 257 53713 14649
0 257 50115 15677
0 257 48830 16191

Windows 在引用东西时特别笨拙——尤其是单引号中的脚本,就像我上面为 awk 使用的那样。我建议您将两个单独的 awk 脚本提取到单独的文件中,如下所示:

script1.awk

!/^#/{
   H=; S=; L=            # Pick up HSL. For Hue, 32768=180deg, 65535=360deg. For S&L, 32768=50%, 65535=100%
   NGROUPS=4                   # Change this according to the number of groups of colours you want
   bin=65535/NGROUPS           # Calculate bin size
   group=int(int(H/bin)*bin)   # Split Hue into NGROUPS
   printf "%d %d %d %d\n",group,H,S,L
 }

script2.awk

{ H[++i]=; S[i]=; L[i]= }
END  {
       printf "P3\n"
       printf "%d %d\n",i,1
       printf "65535\n"
       for(j=1;j<=i;j++){
          printf "%d %d %d\n",H[j],S[j],L[j]
       }
    }

那么主脚本中的两行会变成这样:

convert image.png -unique-colors -colorspace hsl -depth 8 txt: | awk -F"[(), ]+" -f script1.awk > groupHSL.txt

awk -f script2.awk groupHSL-sorted.txt > HSL.pnm