Swap Red and Blue Pixels of Image - python

I am trying to create a function that will allow me to swap every red and blue pixel of an image. However, when running the function, new image does not change or do the intended. So far, I am only trying to change the image to only blue filter to test the function.
from CSE8AImage import *
img = load_img('images/cat.jpg')
def complement(img):
for r in range(len(img)):
for c in range(len(img[r])):
pix = img[r][c]
img[r][c] = (0, 0, pix[2])
return img
save_img(img, 'complement_cat.jpg')

What you're doing in your code is simply setting the red and green pixels to 0(assuming it's RGB? I couldn't find anything about the CSE8AImage library outside of this page which perfectly matches your question). I will continue assuming it's in RGB.
What you should change in your code to make it work is simply change img[r][c] = (0,0,pix[2]) to img[r][c] = pix[[2,1,0]] as this is saying to reorder the pixels (RGB, index 0,1,2) to the new order (BGR, index 2,1,0).
A simpler way would just be to do the whole array at once:
def complement(img):
return img[:,:,[2,1,0]]
This will only work if you can index it like an array in python. Ignore this if this is not the case.

Related

How to remove the empty images using python [duplicate]

Using the Python Imaging Library PIL how can someone detect if an image has all it's pixels black or white?
~Update~
Condition: Not iterate through each pixel!
if not img.getbbox():
... will test to see whether an image is completely black. (Image.getbbox() returns the falsy None if there are no non-black pixels in the image, otherwise it returns a tuple of points, which is truthy.) To test whether an image is completely white, invert it first:
if not ImageChops.invert(img).getbbox():
You can also use img.getextrema(). This will tell you the highest and lowest values within the image. To work with this most easily you should probably convert the image to grayscale mode first (otherwise the extrema might be an RGB or RGBA tuple, or a single grayscale value, or an index, and you have to deal with all those).
extrema = img.convert("L").getextrema()
if extrema == (0, 0):
# all black
elif extrema == (1, 1):
# all white
The latter method will likely be faster, but not so you'd notice in most applications (both will be quite fast).
A one-line version of the above technique that tests for either black or white:
if sum(img.convert("L").getextrema()) in (0, 2):
# either all black or all white
Expanding on Kindall:
if you look at an image called img with:
extrema = img.convert("L").getextrema()
It gives you a range of the values in the images. So an all black image would be (0,0) and an all white image is (255,255). So you can look at:
if extrema[0] == extrema[1]:
return("This image is one solid color, so I won't use it")
else:
# do something with the image img
pass
Useful to me when I was creating a thumbnail from some data and wanted to make sure it was reading correctly.
from PIL import Image
img = Image.open("test.png")
clrs = img.getcolors()
clrs contains [("num of occurences","color"),...]
By checking for len(clrs) == 1 you can verify if the image contains only one color and by looking at the second element of the first tuple in clrs you can infer the color.
In case the image contains multiple colors, then by taking the number of occurences into account you can also handle almost-completly-single-colored images if 99% of the pixles share the same color.
I tried the Kindall solution ImageChops.invert(img).getbbox() without success, my test images failed.
I had noticed a problem, white should be 255 BUT I have found white images where numeric extrema are (0,0).. why? See the update below.
I have changed Kindall second solution (getextrema), that works right, in a way that doesn't need image conversion, I wrote a function and verified that works with Grayscale and RGB images both:
def is_monochromatic_image(img):
extr = img.getextrema()
a = 0
for i in extr:
if isinstance(i, tuple):
a += abs(i[0] - i[1])
else:
a = abs(extr[0] - extr[1])
break
return a == 0
The img argument is a PIL Image object.
You can also check, with small modifications, if images are black or white.. but you have to decide if "white" is 0 or 255, perhaps you have the definitive answer, I have not. :-)
Hope useful
UPDATE: I suppose that white images with zeros inside.. may be PNG or other image format with transparency.

how to separate image using color channel in python?

Hello I want to separate an object based it's color into a new image using python PIL
but I don't quite get the gasp of it. I'm still new with python.
what I already done is a code from matlab and it works
G = imread('x.png');
L = G;
for i=1:217 #this is image height
for j=1:286 #this is image width
for k=1:3 #this is color RGB channel
if(L(i,j,2) < 174) #if green value is under 174
L(i,j,k) = L(i,j,k);
else
L(i,j,k) = 256; #change to white
end
if(L(i,j,3) < 174) #if blue value is under 174
L(i,j,k) = L(i,j,k);
else
L(i,j,k) = 256; #change to white
end
end
end
end
imshow(L)
Can I get a proper explanation about how you do it using python PIL ?
thank you very much
edit :
What I'm trying to do is something like this
https://imgur.com/6n1QCfR
Then the result is this
https://imgur.com/p99kN5p
Here is a very easy way to do it using PIL/Pillow:
#!/usr/bin/env python3
from PIL import Image
import numpy as np
# Load image and ensure it is RGB (not palette)
im = Image.open('circles.jpg').convert('RGB')
# Make into Numpy array so we can do fast, vectorised operations
na = np.array(im)
# Make a mask, which is True wherever Blue channel is high, False elsewhere - see #1 below
mBlueHi = na[...,2] >= 174
# Likewise for Green channel - see #2 below
mGreenHi = na[...,1] >= 174
# In our original image "na", anywhere the Green or Blue mask is set, make it white
na[mGreenHi | mBlueHi] = [255,255,255]
# Make back into PIL Image and save
Image.fromarray(na).save('result.png')
Note #1: The image is stored in a 3 dimensional array, height x width x RGB channels. Red is in channel 0, so it is na[:,:,0] and na[...,0] is shorthand for that same thing.
Note #2: Green is in the second channel starting from index 0, so the green pixels can be addressed using na[:,:,1] or equally na[...,1]
Note that JPEG is lossy and often a poor choice for intermediate files in image processing because it changes values to make files smaller. Consider using PNG which is lossless.

Substitute pixels of an image with other images yet retaining the image

I have seen an image of a girl which is made up of multiple images of her.So I want to achieve the same thing using a python script.(I am completely new to image processing)
I am using pil library for this script.
import sys,os
from PIL import Image
img = Image.open("DSC_0149.jpg")
pixels = img.load()
for i in range(img.size[0]):
for j in range(img.size[1]):
pixels[i,j] = (i, j, 100) # I will change this to some pic image.
img.show()
I am trying first just to change the colour of pixel retaining the pic,But this code dint work.
Can anyone guide me how to achieve it.
Edit : I want to fill the picture with multiple pictures and yet RETAIN the original picture.
Something like this : http://www.photoshopessentials.com/photo-effects/photo-fill/ but in a much better way.
So first you need to edit each pixel with this to change the color:
If it is rgb:
img.putpixel((10,15),(r,g,b))
or
faster: pixels[1, 1] = (r, g, b)
otherwise:
Is it possible to change the color of one individual pixel in Python?
After knowing how to edit each pixel you have to create a small copy of your image with a resize like this:
Copy Image:
// Not tested : Make sure it's rgb
img = Image.new( 'RGB', (img.size[0],(img.size[1]), "black") # create a new black image
pixels = img.load() # create the pixel map
for i in range(img.size[0]): # for every pixel:
for j in range(img.size[1]):
pixels[i,j] = other_image_pixel[i,j] # set the colour accordingly
https://opensource.com/life/15/2/resize-images-python
Apply a Color filter to each small image to match the area color you will replace with this image.
The best way to understand the whole process is to take time to read this code in the same language, it's around 200 lines:
https://github.com/codebox/mosaic
Hope it solve your problems

Pygame Changing Hue of Image

I have a question to do with the Python module pygame.
I want to change the hue of an image for a sprite, like applying a filter to the image. I have seen many posts concerning changing specific pixels from one color to another, although this is not what I want to do. I want to do something similar to what can be done in simple photo editing software such as paint.net, changing the overall color of an image. I could of course change the hue of the image in a photo editing software, but this would lead to lots of images needing to be made and loaded and managed, it would quickly become very tedious. I am hoping that there is some sort of way to change the hue of an image in pygame.
You can do this with Python PIL. Take a look at this question and answer, and especially the original question and answer that they link to:
Changing the color of an image based on RGB value
'''
Original post https://www.reddit.com/r/pygame/comments/hprkpr/how_to_change_the_color_of_an_image_in_pygame/
'''
blue_rgb = (0,0,255) red_rgb = (255,0,0) img =
pygame.image.load("sky_picture.png") # loads the picture from the path
given var = pygame.PixelArray(img)
# var.replace(([Colour you want to replace]), [Colour you want]) var.replace((blue_rgb), (red_rgb)) # replaces all blue in the picture
to red del var
"""
if the picture has some unchanged pixels left it's probably because they are not EXACTLY the rgb given for example (254,0,0) is not
(255,0,0) and won't be changed (to fix this you will have to calculate
the approx number ot just change the main picture)
"""
# I also uploaded this to grepper
The hue of each pixel in an image can be shifted using
PixelArray to
iterate over each pixel,
Surface.unmap_rgb to get a Color object from each pixel, and
Color.hsla to do the
hue shift.
# Get the pixels
pixels = PixelArray(surface)
# Iterate over every pixel
for x in range(surface.get_width()):
for y in range(surface.get_height()):
# Turn the pixel data into an RGB tuple
rgb = surface.unmap_rgb(pixels[x][y])
# Get a new color object using the RGB tuple and convert to HSLA
color = Color(*rgb)
h, s, l, a = color.hsla
# Add 120 to the hue (or however much you want) and wrap to under 360
color.hsla = (int(h) + 120) % 360, int(s), int(l), int(a)
# Assign directly to the pixel
pixels[x][y] = color
# The old way of closing a PixelArray object
del pixels
If the surface is small, this could be run in real time. However, it would be better to run once at load time, especially if the surface is large.

Python (creating a negative of this black and white image)

I am trying to create a negative of this black and white image. The opposite of white (255) is black (0) and vice versa. The opposite of a pixel with a value of 100 is 155.
I cannot use convert, invert, point, eval, lambda.
Here is my code but it doesnt work yet. Could you please let me know which part i am wrong.
def bw_negative(filename):
"""
This function creates a black and white negative of a bitmap image
using the following parameters:
filename is the name of the bitmap image
"""
#Create the handle and then create a list of pixels.
image = Image.open(filename)
pixels = list(image.getdata())
pixel[255] = 0
pixel[0] = 255
for i in range(255,0):
for j in range(0,255):
pixel[i] = j
print pixels[i]
image.putdata(pixels)
image.save ('new.bmp')
Python is an interpreted language, which has the advantage that you can use an interactive interpreter-session to try out things. Try to open the image file in an interactive session and look at the list you get from list(image.getdata()). Once you understand what that list contains, you can think about a way to invert the image.

Categories