将灰度图像转换并保存为例如绿色配色方案
Converting and saving grayscale image to e.g. viridis colour scheme
假设我有这个 image:
我想将灰度转换为 viridis 颜色模式并保存。我已经使用这段代码让它工作了:
system('wget https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Von_einem_Schrecklichen_vnd_Wunderbarlichen_Cometen_so_sich_den_Dienstag_nach_Martini_dieses_lauffenden_M._D._Lxxvij._Jahrs_am_Himmel_erzeiget_hat_%28grayscale%29.png/320px-thumbnail.png')
library(png)
library(viridisLite)
x <- png::readPNG('320px-thumbnail.png')
x <- x[, ,1]
intmat <- x * 255
image(1:nrow(intmat), 1:ncol(intmat), intmat, col=viridis(256))
结果是:
我对颜色方案的应用方式非常满意。然而,这不再是原始图像,而只是一个情节。我想要的是交换灰度中的每个像素,并将转换后的图像再次保存为 png,所以不使用 image()
。我查看了 magick 中的 image_convert
函数,但无法弄清楚如何获得所需的行为。
我敢肯定有很多方法可以做到这一点而无需重新发明轮子,但仅使用您加载的库,操作 viridis 颜色将它们分成 3 个通道并另存为 png 是相当简单的。
这是为任何 png 完成此工作的函数:
png_to_viridis <- function(in_file, out_file)
{
PNG_raw <- readBin(in_file, "raw", 10e6)
x <- png::readPNG(PNG_raw)
intmat <- 255 * x[, ,1]
virmat <- viridisLite::viridis(256)[intmat + 1]
virmat <- c(substr(virmat, 2, 3), substr(virmat, 4, 5),
substr(virmat, 6, 7), substr(virmat, 8, 9))
virmat <- as.numeric(as.hexmode(virmat))/255
dim(virmat) <- c(dim(intmat), 4)
png::writePNG(virmat, out_file)
}
所以现在如果我这样做:
png_to_viridis("https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Von_einem_Schrecklichen_vnd_Wunderbarlichen_Cometen_so_sich_den_Dienstag_nach_Martini_dieses_lauffenden_M._D._Lxxvij._Jahrs_am_Himmel_erzeiget_hat_%28grayscale%29.png/320px-thumbnail.png",
"viridis.png")
我将以下结果另存为 viridis.png:
我从 https://matplotlib.org/3.1.1/tutorials/colors/colormap-manipulation.html 的 Mathplotpy 中提取了 Verdis 颜色图,并将其转换为一组 ImageMagick 格式的颜色。然后创建一维彩色贴图图像并使用 ImageMagick -clut 将其应用于图像。
输入:
convert picture.png \
\( -size 1x1 \
xc:"rgba(0.267004,0.004874,0.329415,1.)" \
xc:"rgba(0.283072,0.130895,0.449241,1.)" \
xc:"rgba(0.262138,0.242286,0.520837,1.)" \
xc:"rgba(0.220057,0.343307,0.549413,1.)" \
xc:"rgba(0.177423,0.437527,0.557565,1.)" \
xc:"rgba(0.143343,0.522773,0.556295,1.)" \
xc:"rgba(0.119512,0.607464,0.540218,1.)" \
xc:"rgba(0.166383,0.690856,0.496502,1.)" \
xc:"rgba(0.319809,0.770914,0.411152,1.)" \
xc:"rgba(0.525776,0.833491,0.288127,1.)" \
xc:"rgba(0.762373,0.876424,0.137064,1.)" \
xc:"rgba(0.993248,0.906157,0.143936,1.)" \
-append \) -clut -evaluate multiply 255 PNG24:picture_verdis.png
结果:
如果您想要 8 位颜色而不是 24 位颜色,请使用 PNG8: 代替 PNG24:。
请注意,ImageMagick rgb 颜色在 0 到 255 范围内,而 Mathplotpy 使用 0 到 1 范围。所以最后我不得不将结果乘以 255。
假设我有这个 image:
我想将灰度转换为 viridis 颜色模式并保存。我已经使用这段代码让它工作了:
system('wget https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Von_einem_Schrecklichen_vnd_Wunderbarlichen_Cometen_so_sich_den_Dienstag_nach_Martini_dieses_lauffenden_M._D._Lxxvij._Jahrs_am_Himmel_erzeiget_hat_%28grayscale%29.png/320px-thumbnail.png')
library(png)
library(viridisLite)
x <- png::readPNG('320px-thumbnail.png')
x <- x[, ,1]
intmat <- x * 255
image(1:nrow(intmat), 1:ncol(intmat), intmat, col=viridis(256))
结果是:
我对颜色方案的应用方式非常满意。然而,这不再是原始图像,而只是一个情节。我想要的是交换灰度中的每个像素,并将转换后的图像再次保存为 png,所以不使用 image()
。我查看了 magick 中的 image_convert
函数,但无法弄清楚如何获得所需的行为。
我敢肯定有很多方法可以做到这一点而无需重新发明轮子,但仅使用您加载的库,操作 viridis 颜色将它们分成 3 个通道并另存为 png 是相当简单的。
这是为任何 png 完成此工作的函数:
png_to_viridis <- function(in_file, out_file)
{
PNG_raw <- readBin(in_file, "raw", 10e6)
x <- png::readPNG(PNG_raw)
intmat <- 255 * x[, ,1]
virmat <- viridisLite::viridis(256)[intmat + 1]
virmat <- c(substr(virmat, 2, 3), substr(virmat, 4, 5),
substr(virmat, 6, 7), substr(virmat, 8, 9))
virmat <- as.numeric(as.hexmode(virmat))/255
dim(virmat) <- c(dim(intmat), 4)
png::writePNG(virmat, out_file)
}
所以现在如果我这样做:
png_to_viridis("https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Von_einem_Schrecklichen_vnd_Wunderbarlichen_Cometen_so_sich_den_Dienstag_nach_Martini_dieses_lauffenden_M._D._Lxxvij._Jahrs_am_Himmel_erzeiget_hat_%28grayscale%29.png/320px-thumbnail.png",
"viridis.png")
我将以下结果另存为 viridis.png:
我从 https://matplotlib.org/3.1.1/tutorials/colors/colormap-manipulation.html 的 Mathplotpy 中提取了 Verdis 颜色图,并将其转换为一组 ImageMagick 格式的颜色。然后创建一维彩色贴图图像并使用 ImageMagick -clut 将其应用于图像。
输入:
convert picture.png \
\( -size 1x1 \
xc:"rgba(0.267004,0.004874,0.329415,1.)" \
xc:"rgba(0.283072,0.130895,0.449241,1.)" \
xc:"rgba(0.262138,0.242286,0.520837,1.)" \
xc:"rgba(0.220057,0.343307,0.549413,1.)" \
xc:"rgba(0.177423,0.437527,0.557565,1.)" \
xc:"rgba(0.143343,0.522773,0.556295,1.)" \
xc:"rgba(0.119512,0.607464,0.540218,1.)" \
xc:"rgba(0.166383,0.690856,0.496502,1.)" \
xc:"rgba(0.319809,0.770914,0.411152,1.)" \
xc:"rgba(0.525776,0.833491,0.288127,1.)" \
xc:"rgba(0.762373,0.876424,0.137064,1.)" \
xc:"rgba(0.993248,0.906157,0.143936,1.)" \
-append \) -clut -evaluate multiply 255 PNG24:picture_verdis.png
结果:
如果您想要 8 位颜色而不是 24 位颜色,请使用 PNG8: 代替 PNG24:。
请注意,ImageMagick rgb 颜色在 0 到 255 范围内,而 Mathplotpy 使用 0 到 1 范围。所以最后我不得不将结果乘以 255。