I have a folder with 230400 images, each representing one pixel in a 480 x 480 image.
How can I use Python to make a single image out of each image?
I tried to creat a npy-array but I believe it resulted in a 3d array instead of a 2d array:
import cv2
import glob
import numpy as np
data = []
files = glob.glob("./data/*.PNG")
for myFile in files:
print(myFile)
image = cv2.imread(myFile)
data.append(image)
print('shape:', np.array(data).shape)
np.save('data',data)
Output: shape: (230400, 100, 100, 3)
How do I create a 2d array of images? And how do I convert it to an image?
Start by creating an empty numpy image with the size of your output image. For each pixel load the image in.
import numpy as np
import cv2
import glob
image_x = 480
image_y =480
files = glob.glob("./data/*.PNG")
output = np.zeros((image_x, image_y, 3))
for i in range(image_x):
for j in range(image_y):
pixel = cv2.imread(files[image_x*i+j])
output[i,j] = pixel[0,0]
Note: This is neither fast nor nice, but explicit.
For saving, use cv2.imwrite on the resulting array as in:
cv2.imwrite('output.png', output)
Related
I have written a code to flip an image vertically pixel-by-pixel. However, the code makes the image being mirrored along the line x = height/2.
I have tried to correct the code by setting the range of "i" from (0, h) to (0, h//2) but the result is still the same.
Original Photo Resulted Photo
#import libraries
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
#read image (set image as m)
m = Image.open('lena.bmp')
#change image to array (set array as np_array)
np_array = np.array(m)
#define the width(w) and height(h) of the image
h, w = np_array.shape
#make the image upside down
for i in range(0,h):
for j in range(0,w):
np_array[i,j] = np_array[h-1-i,j]
#change array back to image (set processed image as pil_image)
pil_image = Image.fromarray(np_array)
#open the processed image
pil_image.show()
#save the processed image
pil_image.save('upsidedown.bmp')
The above given code is replacing the image pixels inplace, that is why the result is a mirrored image.
If you want to flip the image pixel by pixel, just create a new array with same shape and then replace pixels in this new array. For example:
#import libraries
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
#read image (set image as m)
m = Image.open('A-Input-image_Q320.jpg')
#change image to array (set array as np_array)
np_array = np.array(m)
new_np_array = np.copy(np_array)
#define the width(w) and height(h) of the image
h, w = np_array.shape
#make the image upside down
for i in range(0,h):
for j in range(0,w):
new_np_array[i,j] = np_array[h-1-i,j]
#change array back to image (set processed image as pil_image)
pil_image = Image.fromarray(new_np_array)
#open the processed image
pil_image.show()
#save the processed image
pil_image.save('upsidedown.bmp')
Trying to convert image from RGB color space to YDbDr color space according to the formula:
Y = 0.299R + 0.587G + 0.114B
Db = -0.45R - 0.883G +1.333B
Dr = -1.333R + 1.116G + 0.217B
With the following code I'm trying to show only Y channel which should be grayscale image but I keep getting image all in blue color:
import numpy as np
from PIL import Image
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("./pics/Slike_modela/Test/Proba/1_Color.png")
new_img = []
for row in img:
new_row = []
for pixel in row:
Y = 0.299*pixel[2]+0.587*pixel[1]+0.114*pixel[0]
Db = -0.45*pixel[2]-0.883*pixel[1]+1.333*pixel[0]
Dr = -1.333*pixel[2]+1.116*pixel[1]+0.217*pixel[0]
new_pixel = [Y, Db, Dr]
new_row.append(new_pixel)
new_img.append(new_row)
new_img_arr = np.array(new_img)
new_img_arr_y = new_img_arr.copy()
new_img_arr_y[:,:,1] = 0
new_img_arr_y[:,:,2] = 0
print (new_img_arr_y)
cv2.imshow("y image", new_img_arr_y)
key = cv2.waitKey(0)
When printing the result array I see correct numbers according to formula and correct shape of the array.
What is my mistake? How to get Y channel image i.e. grayscale image?
When processing images with Python, you really, really should try to avoid:
treating images as lists and appending millions and millions of pixels, each of which creates a whole new object and takes space to administer
processing images with for loops, which are very slow
The better way to deal with both of these is through using Numpy or other vectorised code libraries or techniques. That is why OpenCV, wand, scikit-image open and handle images as Numpy arrays.
So, you basically want to do a dot product of the colour channels with a set of 3 weights:
import cv2
import numpy as np
# Load image
im = cv2.imread('paddington.png', cv2.IMREAD_COLOR)
# Calculate Y using Numpy "dot()"
Y = np.dot(im[...,:3], [0.114, 0.587, 0.299]).astype(np.uint8)
That's it.
I'm using PIL and numpy to combine two images while one is a .jpg and the other image is represented by a numpy array, which defines a mask that I want to put on top of the original image (basically just a matrix with one and zero entries and the same size as the .jpg). PIL’s composite function works just fine for that but for some reason, after saving the composite image, the file size shrinks to approximately 1/3 of the original image size. Can someone explain this behavior to me?
Here's a code snippet:
import numpy as np
import PIL
from PIL import Image
from PIL import ImageColor
rgb = ImageColor.getrgb('black')
# Read image and write into numpy array
image = Image.open('test_image.jpg')
(im_width, im_height) = image.size
# Create empty mask
mask = np.zeros((im_width, im_height))
# Composite image and mask
solid_color = np.expand_dims(np.ones_like(mask), axis=2) *
np.reshape(list(rgb), [1, 1, 3])
pil_solid_color =
Image.fromarray(np.uint8(solid_color)).convert('RGBA')
pil_mask = Image.fromarray(np.uint8(255.*mask)).convert('L')
image = Image.composite(pil_solid_color, image, pil_mask)
# save image
image.save('test_image_with_mask.jpg')
Code was inspired by tnesorflow's object detection api. Thanks in advance.
This is with respect to the FER2013 dataset. The data consists of 48x48 pixel grayscale images of faces. The CSV file contains three columns as (emotion, pixels, Usage), where Usage has any of three value - training, PrivateTest and PublicTest. I want to read the array of pixels, convert them into an image and save them in the respective folder named as per their Usage type.
I need python code that can do the above.
Following is my code
import pandas as pd
import numpy as np
from PIL import Image
df=pd.read_csv("fer2013.csv")
for rows in df:
arr=np.array(df['pixels'])
print(arr)
print(arr.shape)
img = Image.fromarray(arr.reshape(48,48), 'L')
img.save("dataset/df['Usage']/img.jpg", "JPEG")
The above code shows error:
cannot reshape array of size 35887 into shape (48,48).
In case there are any doubts (because I have been working with the FER dataset):
import pandas as pd
import numpy as np
from PIL import Image
df = pd.read_csv('fer2013.csv')
for image_pixels in df.iloc[1:,1]: #column 2 has the pixels. Row 1 is column name.
image_string = image_pixels.split(' ') #pixels are separated by spaces.
image_data = np.asarray(image_string, dtype=np.uint8).reshape(48,48)
img = Image.fromarray(image_data) #final image
Below is a simple section of code used to access an image using PIL, convert to a numpy array and then print the number of elements in the array.
The image in question is here - - and consists of exactly 100 pixels (10x10). However, the numpy array contains 300 elements (where I would expect 100 elements). What am I doing wrong?
import numpy as np
import PIL
impath = 'C:/Users/Ricky/Desktop/testim.tif'
im = PIL.Image.open(impath)
arr = np.array(im)
print arr.size #300
Every image can be composed by 3 bands (Red-Green-Blue or RGB composition).
Since your image is a black/white image those three bands are the same. You can see the difference using a colored image.
Try this to see what I mean:
import matplotlib.pyplot as pyplot
# this line above import a matplotlib library for plotting image
import numpy as np
import PIL
impath = 'C:/Users/Ricky/Desktop/testim.tif'
im = PIL.Image.open(impath)
arr = np.array(im)
print arr.shape # (10, 10, 3)
print arr[:, : ,0].size # 100
# next lines actually show the image
pyplot.imshow(arr[:, : ,0], cmap='gray')
pyplot.show()