以下是使用 ImageMagick 的一种方法,虽然不完美。 我将色调设置为红色的 0 度,并且将容差设置为 25 度,都在 0 到 360 的范围内。
输入:
hue=0
tolerance=25
toler=`convert xc: -format "%[fx:(100*$tolerance/360)]" info:`
hueval=`convert xc: -format "%[fx:50-$hue]" info:`
thresh=`convert xc: -format "%[fx:100-$tolerance]" info:`
convert tomato.jpg \
\( -clone 0 -colorspace gray -colorspace sRGB \) \
\( -clone 0 -colorspace HSL -channel 0 -separate +channel \
-evaluate AddModulus ${hueval}% \
-solarize 50% -level 0x50% \
-threshold $thresh% \) \
-swap 0,1 -alpha off -compose over -composite \
result.jpg
虽然不完美,但相当易于理解。基本上,您可以使用fx operator来检查每个像素的色调,并根据其色调/颜色返回原始像素或其灰度等效像素。
因此,作为第一步,您可能会执行以下操作,将所有显示高色调值的像素替换为它们的灰度(亮度)等效像素:
magick ripe.jpg -fx "(u.hue<0.1)? u : u.lightness" result.jpg
那么你可能会意识到,在色相圆上,红色色调在0/360度处环绕,因此您可以这样做:
magick ripe.jpg -fx "(u.hue<0.1)||(u.hue>0.9)? u : u.lightness" result.jpg
解释
这里有几个事情要注意。首先,-fx
操作符是一种非常底层、极其强大(但很慢因为它是解释执行的)的方法,可以在图像中的每个像素上运行一个"代码"。其次,我正在使用如下格式的三元运算符:
condition? valueA : valueB
valueA
,如果为假,则返回valueB
。当我提到u
、u.hue
和u.lightness
时,u
表示命令中的第一个图像 - 我可以加载两个图像并使用第一个的特征选择第二个的特征,然后我将使用u
和v
来区分。最后,这些值在范围[0,1]上进行缩放,因此我不会测试"Hue>350在范围[0,360]之内",而是测试Hue>0.9
作为一个粗略等价物 - 我想我本可以使用Hue>(350/360)
。请注意,您可以使表达式任意复杂,并将其放入单独的文件中以便像这样重用:magick ripe.jpg -fx @DeSatNonRed.fx result.jpg
DeSatNonRed.fx
可能长这样:
hueMin=350/360;
hueMax=20/360;
(hue>hueMin) || (hue<hueMax) ? u : u.lightness