I want to 'decompose' an Image (i.e. split()), modify one of the channels by combining it with another one and re-'compose' (i.e. merge()) them again.
This example should highlight edges by mapping them onto the RED-channel using the feature I wish existed:
from PIL import Image, ImageFilter
base = Image.open("example.jpg")
base.show()
edges = (base
.convert("L")
.filter(ImageFilter.Kernel((3, 3), (-1, -1, -1, -1, 8,-1, -1, -1, -1), 1, 0))
.point(lambda p: 255 if p > 10 else 0))
edges.show()
r, g, b = base.split()
# now I want the blue channel/band for each pixel to be whatever respective
# pixel is brighter on a given set of bands
# this is what I want to do, but `combine()` does not exist
b_with_edges = Image.combine((r, edges), lambda pixels: max(pixels))
# instead - for the example I'm dropping blue and take just the edges
b_with_edges = edges
new_image = Image.merge("RGB", (r, g, b_with_edges))
new_image.show()
Of course I can manually iterate through all pixels and combine them manually. From what I've seen from PIL it seems to be a quite well developed and flexible library, so I expect there to be some built-in way..
Update:
Since CrazyChucky's answer works quite well for this use case, I dare to add a distilled version:
from PIL import Image, ImageFilter, ImageChops
base = Image.open("example.jpg").reduce(1)
r, g, b = base.split()
edges = (base
.convert("L")
.filter(ImageFilter.Kernel((3, 3), (-1, -1, -1, -1, 8,-1, -1, -1, -1), 1, 0))
.point(lambda p: 255 if p > 10 else 0))
image_with_edge_highlighting = Image.merge("RGB", (r, g, ImageChops.lighter(b, edges)))
image_with_edge_highlighting.show()




