how can I split a large image into small pieces in python - python

I need to create 30 * 30 px small images from splitting a large image. I need these parts separately saved in separate files after being split up like so:

Here you go:
import cv2
img = cv2.imread('image.png')
for r in range(0,img.shape[0],30):
for c in range(0,img.shape[1],30):
cv2.imwrite(f"img{r}_{c}.png",img[r:r+30, c:c+30,:])

Try use image_slicer. (8 x 8 from your description)
import image_slicer
image_slicer.slice('C:\\files\\cars.png', 64)
This' how the outputs looked like.

Related

How to sort the images using one of the average pixels in python PIL

I'm on the way to sorting several images according to their average pixel values using PIL. In the below code I choose to pick up the average red value as the prameter to sort the images. The images are all in 640 x 480 RBG format. I have 10 images (from GRK_image1 to GRK_image10), instead of typing the code below 10 times, is there any faster way to loop through all the 10 images in one step and get all the average red values for each image? I have been stuck here for many days. Thank you!
from PIL import Image
import glob
# 1. Get the first picture, open it
first_image=Image.open('GRK_imge1.png')
all_pixels = []
for x in range(640):
for y in range(480):
R, G, B = first_image.getpixel((x,y))
all_pixels.append(R)
storeAllImages = []
AverageR = (sum(all_pixels)/len(all_pixels))
print(AverageR)
storeAllImages.append(('GRK_image1.png',AverageR))
print(storeAllImages)
I would use skimage to load all the files at once using some pattern - in my case all the files are cars1.jpg, car2.jpg, etc so I use 'car*.jpg'
This gives a list of 3d arrays, and I can take the mean of the red channel (the first of the 3 dimensions) as a key to sorted with the reverse=True flag to go from most red to least.
You can view some of them to make sure it's working, then save them, using enumerate to label.
import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread_collection, imshow, imsave
images = sorted(imread_collection("car*.jpg", conserve_memory=False),
key=lambda x: np.mean(x[:,:,0]),
reverse=True)
# to view your work
for i in images:
plt.figure()
plt.imshow(i)
# save images starting with most red
for c, i in enumerate(images):
imsave(f'most_red_{c}.jpg', i)

How to convert multiple .jpg to .mp4 with individual duration for each .jpg?

Let's assume I have multiple .jpg files in a directory and want to make an .mp4 file out of them - how can I do that but with an individual duration for each .jpg?
E.g. the first image should be shown for 3 seconds, the second one should be visible for 7 seconds, ...
Is it possible to achieve something like that with exisiting libraries?
Or should I just include the images multiple times into the directory, depending on their duration (which would end up making this inaccurate if I want an image to be shown less than a second)?
Thanks in advance!
Maybe you should try using OpenCV
import cv2
import numpy as np
import glob
img_array = []
for filename in glob.glob('C:/New folder/Images/*.jpg'):
img = cv2.imread(filename)
height, width, layers = img.shape
size = (width,height)
img_array.append(img)
out = cv2.VideoWriter('project.avi',cv2.VideoWriter_fourcc(*'DIVX'), 15, size)
for i in range(len(img_array)):
out.write(img_array[i])
out.release()
source: https://theailearner.com/2018/10/15/creating-video-from-images-using-opencv-python/

How to create an image from a string?

I'm trying to create an image file from a string, but so far I have not had any luck. Using ImageDraw I can print a string on an image file, but this is not what I intend to do. I want to generate just a simple image file from a set of characters.
Edit: Imagine a hypothetical case of creating an ASCII art text of a pic, but instead of creating an output of a text file, generate an image file. My code consists of multiple loops and using Matplotlib will affect my code's performance.
you could try matplotlib:
import matplotlib.pyplot as plt
plt.text(0,0,mystring)
plt.savefig("mysentence.png", dpi=100)
You can use the PIL.Image.frombytes method
import PIL
my_string = b'\xf8\xff\xb0\xbc\xd8]\xba\xdf0\xbd\xdeE\xfb\xff\xd1\xf1\xff\xbf\xb4\xd9p\xad\xd9F\xae\xd7U\xf2\xff\xd6\xdf\xff\xdc\xde\xff\xd2m\xa8L\xe0\xff\xc5\xe0\xff\xe1F\x9a\\I\x9e]E\x9bTD\x9aSK\x9fa1\xadO,\xa7L3\xaeT/\xa9R.\xa8Q'
img = Image.frombytes("RGB", (5,5), my_string)
img.show()
Note, that the length of your string must equals the number of bytes used for a pixel multiplied by the width and height of the image.
In my case my_string holds an RGB image, that makes 3 bytes per pixel and the image is 5 pixels width and 5 pixel high.
Therefore my_string should have a length of 75 bytes (3 * 5 * 5)

How to read multiple images in python

I want read 100 colour images and use them for further processing. Suppose one image size is 256x 256 by reading it in python openCV its size is (256,256,3). I now want to read 100 images and after reading I have to get the size as (100,256,256,3).
You could do something like this, supposing that your images are named like 0.png to 99.png:
import numpy as np
result=np.empty((100,256,256,3))
for i in range (100):
result[i,:,:,:] = cv2.imread('{}.png'.format(i),1)
## your image names
#fnames = sorted(glob.glob("images/*.png"))
## read and stack
img = np.stack([cv2.imread(fname) for fname in fnames])

Create set of random JPGs

Here's the scenario, I want to create a set of random, small jpg's - anywhere between 50 bytes and 8k in size - the actual visual content of the jpeg is irrelevant as long as they're valid. I need to generate a thousand or so, and they all have to be unique - even if they're only different by a single pixel. Can I just write a jpeg header/footer and some random bytes in there? I'm not able to use existing photos or sets of photos from the web.
The second issue is that the set of images has to be different for each run of the program.
I'd prefer to do this in python, as the wrapping scripts are in Python.
I've looked for python code to generate jpg's from scratch, and didn't find anything, so pointers to libraries are just as good.
If the images can be only random noise, so you could generate an array using numpy.random and save them using PIL's Image.save.
This example might be expanded, including ways to avoid a (very unlikely) repetition of patterns:
import numpy
from PIL import Image
for n in range(10):
a = numpy.random.rand(30,30,3) * 255
im_out = Image.fromarray(a.astype('uint8')).convert('RGB')
im_out.save('out%000d.jpg' % n)
These conditions must be met in order to get jpeg images:
The array needs to be shaped (m, n, 3) - three colors, R G and B;
Each element (each color of each pixel) has to be a byte integer (uint, or unsigned integer with 8 bits), ranging from 0 to 255.
Additionaly, some other way besides pure randomness might be used in order to generate the images in case you don't want pure noise.
If you do not care about the content of a file, you can create valid JPEG using Pillow (PIL.Image.new [0]) this way:
from PIL import Image
width = height = 128
valid_solid_color_jpeg = Image.new(mode='RGB', size=(width, height), color='red')
valid_solid_color_jpeg.save('red_image.jpg')
[0] https://pillow.readthedocs.io/en/latest/reference/Image.html#PIL.Image.new
// EDIT: I thought OP wants to generate valid images and does not care about their content (that's why I suggested solid-color images). Here's a function that generates valid images with random pixels and as a bonus writes random string to the generated image. The only dependency is Pillow, everything else is pure Python.
import random
import uuid
from PIL import Image, ImageDraw
def generate_random_image(width=128, height=128):
rand_pixels = [random.randint(0, 255) for _ in range(width * height * 3)]
rand_pixels_as_bytes = bytes(rand_pixels)
text_and_filename = str(uuid.uuid4())
random_image = Image.frombytes('RGB', (width, height), rand_pixels_as_bytes)
draw_image = ImageDraw.Draw(random_image)
draw_image.text(xy=(0, 0), text=text_and_filename, fill=(255, 255, 255))
random_image.save("{file_name}.jpg".format(file_name=text_and_filename))
# Generate 42 random images:
for _ in range(42):
generate_random_image()
If you are looking for a way to do this without numpy this worked for me
(python 3.6 for bytes, you still need Pillow)
import random as r
from PIL import Image
dat = bytes([r.randint(1,3) for x in range(4500000)])
i = Image.frombytes('1', (200,200), dat)

Categories

Resources