remove a particular color from an image - python

Is it possible to remove a particular rbg color from an image? For example, I want to create a function such that I pass an image and color as a parameter and it returns the same image but without that color.
For example, this function
fuction(image, "R")
should give me an image that has no R shades. How can I do so?
Currently, something like this works:
def exclusionWithPIL(image, channel):
out = None
image = Image.open(image)
image_data = image.load()
height,width = image.size
for loop1 in range(height):
for loop2 in range(width):
r,g,b = image_data[loop1,loop2]
image_data[loop1,loop2] = 0,g,b
return image
result = rgb_exclusion('./image.jpg', "G")
result.save('new.jpg')
but here, I'm reading the image like this Image.open(image) inside the function. Instead, I want to pass in image1 which is already read like this:
image1 = load(image1_path)
def load(image_path):
out = io.imread(image_path)
out = out.astype(np.float64) / 255
return out
How can I modify the function accordingly?
P.S I use io.imread from skimage to read images.
Edit:
if I pass the image loaded by io.imread directly into the function, something like this seems to work:
out = image.copy()
if (channel == "R"):
out[:, :, 0] = 0
But I don't quite quite understand the indexes [:, :, 0]

found a tutorial online which solves exactly your problem:
Tutorial Link
The main idea behind their solution is to use PIL in order to open the image, load it, and then iterate over every pixel in the image (using 2 loops) and setting the chosen color to zero.
EDIT: I think that your problem occurs because of the fact that you're trying to pass to the function as a parameter an image which was loaded using sicikit-image library (io.imread()), and then inside the function you're trying to use PILLOW library's features on the same image.
That's why it shouldn't work, you're merging between 2 different libraries.
As I see it, there are 2 possible solution:
Make the function's parameter the image's path instead of the image itself, and then save the image in the same directory and do not return anything.
Stay consistent, and before passing the function an image as a parameter, load it using the PILLOW library, and when returning it, refer to the returned image in terms of the PILLOW library only.

Related

How to convert a 1 channel image into a 3 channel with PIL?

I have an image that has one channel. I would like duplicate this one channel such that I can get a new image that has the same channel, just duplicated three times. Basically, making a quasi RBG image.
I see some info on how to do this with OpenCV, but not in PIL. It looks easy in Numpy, but again, PIL is different. I don't want to get into the habit of jumping from library to library all the time.
Here's one way without looking too hard at the docs..
fake image:
im = Image.new('P', (16,4), 127)
Get the (pixel) size of the single band image; create a new 3-band image of the same size; use zip to create pixel tuples from the original; put that into the new image..
w, h = im.size
ima = Image.new('RGB', (w,h))
data = zip(im.getdata(), im.getdata(), im.getdata())
ima.putdata(list(data))
Or even possibly
new = im.convert(mode='RGB')
just use:
image = Image.open(image_info.path).convert("RGB")
can convert both 1-channel and 4-channel to 3-channel

How to get title from an image in openCV python

I was wondering how to get a title from a image in OpenCV.
At the moment I have this:
#Load a color image in grayscale
img = cv2.imread('lena.jpg',0)
From here, I'd like to get the title from 'img' by doing something like
img.title()
but I don't find any method for doing this.
Any suggestion?
Thanks in advance.
You have set the name of the image, in which case you can store that and refer back to it in the future. There is no way of retriving it from the Mat object as all that stores is the data of the image itself.
instead of:
#Load a color image in grayscale
img = cv2.imread('lena.jpg',0)
save the file name first then use that wherever you need it
image_filename = 'lena.jpg'
img = cv2.imread(image_filename,0)
There is no direct method in opencv to extract the title from an image. After we load the image in opencv by "imread", the image will be transformed into arrays/matrices. Its all numericals(Christopher Nolan) stuff :P .
One way I can suggest is, you can find "contours" by applying some heuristics like averaging/mean/medium of Area, width, height etc. and also try applying "RLSA(Run Length Smoothing Algorithm)" on those classified contours.
Documention and Code for RLSA is here

How to merge 2 transparent png's in python Pillow

I have 2 transparent PNG images of the same size (142,43). I am trying to vertically stack them. This is one of them:
The end result should be like this (142,86):
It also should retain its transparancy.
I've tried the following code:
from PIL import Image
img_list = [Image.open("example.png"), Image.open("example.png")]
bg = Image.open("1x1_transparent.png")
bg = bg.resize(size=(142, 43*2))
img_list[0] = img_list[0].convert('RGBA')
bg.paste(img_list[0], (0, 0), img_list[0])
bg.save('final.png')
Which imports a 1x1 transparent image, resizes it to the final target size, then tries to put the first image on it. This does not work. The saved image 'final.png' shows an empty image.
Any thoughts what I would be doing wrong?
If your output doesn't seem properly sized, it's probably because of this line:
bg.resize(size=(142, 43*2))
resize returns a new version of the image, leaving the original one unmodified. Try assigning the returned value to something so you can do additional operations on it and ultimately save the output.
bg = bg.resize(size=(142, 43*2))

Python PIL: Convert RGBA->P - ValueError: image has wrong mode [duplicate]

I would like to convert a PNG32 image (with transparency) to PNG8 with Python Image Library.
So far I have succeeded converting to PNG8 with a solid background.
Below is what I am doing:
from PIL import Image
im = Image.open("logo_256.png")
im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
im.save("logo_py.png", colors=255)
After much searching on the net, here is the code to accomplish what I asked for:
from PIL import Image
im = Image.open("logo_256.png")
# PIL complains if you don't load explicitly
im.load()
# Get the alpha band
alpha = im.split()[-1]
im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
# Set all pixel values below 128 to 255,
# and the rest to 0
mask = Image.eval(alpha, lambda a: 255 if a <=128 else 0)
# Paste the color of index 255 and use alpha as a mask
im.paste(255, mask)
# The transparency index is 255
im.save("logo_py.png", transparency=255)
Source: http://nadiana.com/pil-tips-converting-png-gif
Although the code there does not call im.load(), and thus crashes on my version of os/python/pil. (It looks like that is the bug in PIL).
As mentioned by Mark Ransom, your paletized image will only have one transparency level.
When saving your paletized image, you'll have to specify which color index you want to be the transparent color like this :
im.save("logo_py.png", transparency=0)
to save the image as a paletized colors and using the first color as a transparent color.
This is an old question so perhaps older answers are tuned to older version of PIL?
But for anyone coming to this with Pillow>=6.0.0 then the following answer is many magnitudes faster and simpler.
im = Image.open('png32_or_png64_with_alpha.png')
im = im.quantize()
im.save('png8_with_alpha_channel_preserved.png')
Don't use PIL to generate the palette, as it can't handle RGBA properly and has quite limited quantization algorithm.
Use pngquant instead.

Resize image twice in Django using PIL

I have a function in which I'm trying to resize a photo twice from request.FILES['image']. I'm using the image.thumbnail() with the Parser as well. This works fine when I create one thumbnail, but in my view if I repeat the exact same thing again, it fails in the parser via IOError cannot parse image. I'm very confused. I've created StringIO files in memory instead of using Django's UploadedFile object as-is and it still does the same thing. Any help is much appreciated.
Suppose I wanted to do the following twice (with two different thumbnailing sizes) all without retrieving the URL twice:
import urllib2
from PIL import Image, ImageFile, ImageEnhance
# create Image instance
file = urllib2.urlopen(r'http://animals.nationalgeographic.com/staticfiles/NGS/Shared/StaticFiles/animals/images/primary/kemps-ridley-sea-turtle.jpg')
parser = ImageFile.Parser()
while True:
s = file.read(1024)
if not s:
break
parser.feed(s)
image = parser.close()
# make thumbnail
size = (75, 75)
image.thumbnail(size, Image.ANTIALIAS)
background = Image.new('RGBA', size, (255, 255, 255, 0))
background.paste(
image,
((size[0] - image.size[0]) / 2, (size[1] - image.size[1]) / 2))
background.save('copy.jpg')
For instance:
image = parser.close()
image2 = parser.close() # Obviously this doens't work
image2 = image # Obviously this doesn't either but you get what I need to do here
# Do 2 thumbnails with only one original source.
... other code ommitted ...
image.save('copy.jpg')
image2.save('copy.jpg')
If this works once, as you say, the image you retrieved is just fine. There are at least two different ways to get multiple thumbnails out of single PIL images.
You can use PIL's resize method, which will return a resized copy of the original. You just have to calculate the dimensions you'll need if you want to keep the proportions intact.
Use Image.copy() to get a copy of the image.
Like this:
original = parser.close()
...
thumb1 = original.copy()
size = (75,75)
thumb1.thumbnail(size, Image.ANTIALIAS)
...
thumb2 = original.copy()
thumbnail2 = original.resize(size2, Image.ANTIALIAS)
...
This way, the original will not be altered and you can get as many copies as you need.
A simpler solution than copying the original image is to instead reset the file pointer between calls to thumbnail(...) like so:
original.seek(0)
I'm assuming it's failing on the image = parser.close() line with an IOError. so there's probably something wrong with the way ImageFile is getting the image data. Have you tried making reading from a local file instead?
If the parser managed to decode an image, it returns an Image object.
Otherwise, this method raises an IOError exception.
Source.

Categories

Resources