I need to save an image with x and y dimensions, I am using pillow to do so, the problem is that it is saving in default dimension, in my case 16x16, I tried using resize like this:
new_image = image.resize((40, 40))
but still the same result, the only difference is that in the preview of the image it gets smaller, but it stays 16x16, Does anyone have ideas?
image_byte = b"image_bytes"
b = base64.b64decode(image_byte)
image = Image.open(io.BytesIO(b))
new_image = image.resize((40, 40))
new_image.save(icon_path)
Based on the discussion in the comments:
When saving ICO files, you will need to specify the sizes to save as (since ICOs can contain multiple sizes and formats of the same (or different!) image):
new_image.save('icon.ico', sizes=[(256, 256), (128, 128)])
If you don't need an ICO file, just use e.g. PNG (which contains a single format and size):
new_image.save('icon.png')
Related
I'm looking for a library that enables to "create pictures" (or even videos) with the following functions:
Accepting picture inputs
Resizing said inputs to fit given template / scheme
Positioning the pictures in pre-set up layers or coordinates
A rather schematic approach to look at this:
whereas the red spots are supposed to represent e.g. text, picture (or if possible video) elements.
The end goal would be to give the .py script multiple input pictures and the .py creating a finished version like mentioned above.
Solutions I tried were looking into Python PIL, but I wasn't able to find what I was looking for.
Yes, it is possible to do this with Python.
The library you are looking for is OpenCV([https://opencv.org][1]/).
Some basic OpenCV python tutorials (https://docs.opencv.org/master/d9/df8/tutorial_root.html).
1) You can use imread() function to read images from files.
2) You can use resize() function to resize the images.
3) You can create a empty master numpy array matching the size and depth(color depth) of the black rectangle in the figure you have shown, resize your image and copy the contents into the empty array starting from the position you want.
Below is a sample code which does something close to what you might need, you can modify this to suit your actual needs. (Since your requirements are not clear I have written the code like this so that it can at least guide you.)
import numpy as np
import cv2
import matplotlib.pyplot as plt
# You can store most of these values in another file and load them.
# You can modify this to set the dimensions of the background image.
BG_IMAGE_WIDTH = 100
BG_IMAGE_HEIGHT = 100
BG_IMAGE_COLOR_DEPTH = 3
# This will act as the black bounding box you have shown in your figure.
# You can also load another image instead of creating empty background image.
empty_background_image = np.zeros(
(BG_IMAGE_HEIGHT, BG_IMAGE_WIDTH, BG_IMAGE_COLOR_DEPTH),
dtype=np.int
)
# Loading an image.
# This will be copied later into one of those red boxes you have shown.
IMAGE_PATH = "./image1.jpg"
foreground_image = cv2.imread(IMAGE_PATH)
# Setting the resize target and top left position with respect to bg image.
X_POS = 4
Y_POS = 10
RESIZE_TARGET_WIDTH = 30
RESIZE_TARGET_HEIGHT = 30
# Resizing
foreground_image= cv2.resize(
src=foreground_image,
dsize=(RESIZE_TARGET_WIDTH, RESIZE_TARGET_HEIGHT),
)
# Copying this into background image
empty_background_image[
Y_POS: Y_POS + RESIZE_TARGET_HEIGHT,
X_POS: X_POS + RESIZE_TARGET_WIDTH
] = foreground_image
plt.imshow(empty_background_image)
plt.show()
In my Qt application I have image data as a numpy.ndarray. Usually that comes from cv2.imread(), which I then convert to a QImage as follows:
height, width, channel = cvImg.shape
bytesPerLine = 3 * width
qImg = QImage(cvImg.data, width, height, bytesPerLine, QImage.Format_RGB888)
This works fine, the QImage can be converted to a pixmap and painted to a label. Now in some cases I don't get the image data from a file via imread(), but instead directly from a camera. This data is also a numpy.ndarray, I can save it via cv2.imwrite() (and then open it in an image viewer). However, using the code above I cannot convert that image data directly to a QImage, the result is a red-ish image without any details, just some vertical lines.
Now since I can save that camera image data it seems to be valid, I just need to find the correct image format when calling the QImage constructor (I guess). I tried several of them, but none worked. So how can I determine in which format this image data is?
I have grayscale images of different dimensions so I need to convert them to same dimension (say, 28*28) for my experiments. I tried to do it using different methods and I was able to do it but I observed that resizing of image lead to increase in number of channels. I am new to python and image processing so please help.
from PIL import Image
image = Image.open('6.tif')
image = image.resize((28, 28), Image.ANTIALIAS)
image.save('6.png', 'PNG', quality=100)
And then following code shows different dimensions:
import imageio
image_data = imageio.imread("6.tif").astype(float)
print(image_data.shape)
image_data = imageio.imread("6.png").astype(float)
print(image_data.shape)
and result is:
(65, 74)
(28, 28, 4)
I don't need the last dimension. How is this coming? I get the similar results even with "from resizeimage import resizeimage".
There are a number of issues with your code...
If you are expecting a greyscale image, make sure that is what you get. So, change this:
image = Image.open('6.tif')
to:
image = Image.open('6.tif').convert('L')
When you resize an image, you need to use one of the correct resampling methods:
PIL.Image.NEAREST
PIL.Image.BOX
PIL.Image.BILINEAR
PIL.Image.HAMMING
PIL.Image.BICUBIC
PIL.Image.LANCZOS
So, you need to replace the ANTI_ALIAS with something from the above list on this line:
image = image.resize((28, 28), Image.ANTIALIAS)
When you save as PNG, it is always loss-less. The quality factor does not work the same as for JPEG images, so you should omit it unless you have a good understanding of how it affects the PNG encoder.
If you make these changes, specifically the first, I think your problem will go away. Bear in mind though that the PNG encoder may take an RGB image and save it as a palletised image, or it may take a greyscale image and encode it as RGB, or RGB alpha.
I have a list called w (size: 784), which I outputted to a png greyscale image:
import matplotlib.pyplot as plt
tmp = 1/(1+np.exp(-10*w/w.max()))
plt.imshow(tmp.reshape(28,28),cmap="gray")
plt.draw()
plt.savefig("final_weight_vector")
Now I want to read the png image back to be a vector.
The solutions I found so far:
First:
import matplotlib.image as mpimg
img=mpimg.imread('final_weight_vector.png')
but img appears to not be greyscale, because its dimensions turend out to be (600, 800, 4).
Second:
reading the file as RGB and converting to greyscale:
im = Image.open('final_weight_vector.png').convert('LA')
However, I couldn't find how to iterate over im so I have no idea as to what's inside. Further, I am not sure the output of im will have the exact same values as the original w.
Help please?
The problem is that what you saved is probably a plot of the 28x28 image, not the image itself.
To be sure, please preview the image. I bet it is 600x800, not 28x28. I also suppose it contains many additional elements, like axes and padding.
If you want to store your array in a loadable format, you may use numpy.save() (and numpy.load() to load it).
You may also use PIL to save your array as image (e.g. using something similar to: http://code.activestate.com/recipes/577591-conversion-of-pil-image-and-numpy-array/)
I want to crop an image by selecting a subregion of it to turn into a new image file.
Based on what I see in the PIL docs, I am trying to decide between 2 approaches.
For both approaches:
# assume I already have a PIL-opened image called original_image
# assume I have a crop_box tuple for the area to crop, e.g. (0, 0, 100, 100)
Approaches
Cropping the original image directly, and then transforming the returned crop area into a new file. It seems that I'm giving up all the mode data / other metadata about the original image, which would then have to be re-loaded?
cropped_image = original_image.crop(crop_box)
# process cropped version as needed
Do an image.transform() in which I select a sub-region
# assume I have an output size of (100, 100)
cropped_image = original_image.transform(size, Image.EXTENT, crop_box)
# process cropped version as needed
Is one approach preferable to the other in terms of speed, data preservation, or another important factor that I'm missing?
The following is from the PIL.Image documentation under the transform function:
It is slightly slower than crop
Plus crop is simpler and shows your intent. That's what I'd use.