I would like to average two grayscale images (both png files of the same size) using R.
Consider the images below as an example:
img1.png
img2.png
img3.png
The average of img1.png
and img2.png
should result in something like img3.png
. I've looked into the magick and imager packages without success.
Surely there are multiple solutions to this problem. Here's one that shows clearly what's happening and allows for more flexibility.
Let's load your two example pictures.
library(png)
img1 <- readPNG("owzUE.png")
img2 <- readPNG("HMka0.png")
It happens that they are not of identical size:
dim(img1)
# [1] 145 190 4
dim(img2)
# [1] 144 191 4
So, let's make the size the same with
img1 <- img1[1:144, 1:190, 1:4]
img2 <- img2[1:144, 1:190, 1:4]
Each image consists of four matrices, the first three corresponding to the RGB channels and the last one to alpha. Let's define the resulting image by
img3 <- img1 * 0
which nicely gives an array of the same size as img1
and img2
.
A closely related concept is alpha blending but the formulas are not exactly what you need; there the relationship between images doesn't seem to be symmetric. What we may do is to consider a weighted average for each RGB channel, where weights correspond to the corresponding alphas:
for(d in 1:3)
img3[, , d] <- (img1[, , d] * img1[, , 4] + img2[, , d] * img2[, , 4] ) / (img1[, , 4] + img2[, , 4])
Since in some cases both alphas are 0, we fix those cases with
img3[is.nan(img3)] <- 0
Lastly, we set alpha value to a larger one of the two images with
img3[, , 4] <- pmax(img1[, , 4], img2[, , 4])
and save the result
writePNG(img3, "img3.png")
So, this method also applies to color images and allows one to experiment with the formula by varying weights, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With