matplotlib.pyplot.imsave backend - image

I'm working in Spyder with matplotlib.pyplot and want to save numpy array to images.
The documentation of imsave() says, that the format to which I can save depends on the backend. So what exactly is the backend? I seem to be able to save .tiff images, but f.e. I want them to be saved as 8-bit tiffs instead of RGB-Tiffs. Any Idea where I can change that?

If you are trying to save an array as a tiff (with no axis markers ect) from mat, you might be better off using PIL.
(this assumes you are using ipython --pylab, so rand is defined)
write:
import PIL.Image as Image
im = Image.new('L',(100,100))
im.putdata(np.floor(rand(100,100) * 256).astype('uint8').ravel())
im.save('test.tif')
The ravel() is important, putdata expects a sequence (ie, 1D) not an array.
read :
im2 = Image.open('test.tif')
figure()
imshow(im2)
and the output file:
$ tiffinfo test.tif
TIFF Directory at offset 0x8 (8)
Image Width: 100 Image Length: 100
Bits/Sample: 8
Compression Scheme: None
Photometric Interpretation: min-is-black
Rows/Strip: 100
Planar Configuration: single image plane

Related

How do you save an array to a PNG image in RAM using Julia?

Saving an image to a PNG file is not a problem, the following code works fine (using Julia 1.5, FileIO 1.4.1 and ImageIO 0.3.0):
using FileIO
image = rand(UInt8, 200, 150, 3)
save("test.png", image)
However, I cannot find how to save the PNG image to a RAM buffer instead. I tried this:
io = IOBuffer()
save(Stream(format"PNG", io), image)
data = take!(io)
There's no error, but the resulting data is much too small: just 809 bytes (instead of about 90kB for the test.png file).
What am I doing wrong?
Your I/O code is correct but you are incorrectly generating the random image.
It should be:
using Images
image = [RGB(rand(N0f8,3)...) for x in 1:200, y in 1:150]
Now both the png file and buffer will have the same size in bytes (since png is compressed the exact number will vary with each randomized run):
julia> save(Stream(format"PNG", io), image)
90415

How to open a raw YCbCr image file in MatLab?

I am trying to open a 1920x1080 YCbCr raw image file in Matlab, however I am having difficulties getting the following code below to work:
fid = fopen(filePath);
image = fread(fid, 1920*1080, 'uint8=>uint8');
fclose(fid);
image = reshape(image, 1080, 1920);
However, when I go to show the image, it does not look as expected.
The actual image should be colour, however I get a strange black and white image, not resembling the expected output at all.
I have also tried loading it into a 3D array, with each dimension representing one of the Y, Cb and Cr channels, however this also produced a similar output as described before.
Any help would be appreciated.
Ignore this bit and look below at the EDIT:
I don't understand why you are using fread? Why not use imread,
which is mean't for reading images? Using this infamous original
image, as a base for my test script, I could display a YCbCr
image, as shown in the little script below.
original = imread("lenna.jpg");
% figure, imshow(original); % if you want to see how the original image looks
YCbCr_version = rgb2ycbcr(original);
% figure, imshow(YCbCr_version); % if you want to see how the YCbCr image looks
imwrite(YCbCr_version, "out.jpg");
YCbCr_fromFile = imread("out.jpg");
figure, imshow(YCbCr_fromFile);
EDIT:
IF however you have a binary version of the file and can only read it using using fread,
then the following script should work,
clc;
clear;
close all;
original = imread("lenna.jpg");
% figure, imshow(original); % if you want to see how the original image looks
YCbCr_version = rgb2ycbcr(original);
% figure, imshow(YCbCr_version); % if you want to see how the YCbCr image looks
fileID = fopen('out.bin','w');
fwrite(fileID, YCbCr_version, 'uint8');
fclose(fileID);
fileID = fopen('out.bin','r');
fromFile = fread(fileID, 512*600*3, 'uint8=>uint8');
fclose(fileID);
image = reshape(fromFile, 512, 600, 3);
imagesc(image)
The point is, in the read operation, you have to give the 3 channels in the multiplier also, as color images have this 3rd dimension, i.e. 512*600*3. If you only give 512*600, as you were doing, you would have no color info. Also the reshape function would need to be changed to take into account the 3rd dimension. Hence, reshape(fromFile, 512,600, 3).
YCbCr version loaded from the file
As you said "Any help would be appreciated", I thought I would mention you can simply convert a raw YCbCr file to PNG, TIFF, JPEG or any other format file with ImageMagick which is installed on most Linux distros and is available for macOS and Windows.
Start a Terminal, (or Command Prompt if under Windows), and convert the YCbCr image.raw to PNG with:
magick -size 1920x1080 -depth 8 YCbCr:image.raw result.png
Or, say a CCIR 601 YUV file to NetPBM PPM format:
magick -size 800x600 -depth 8 YUV:image.raw result.ppm

gray levels are changed after using imsave function

I used these codes to produce an RGB image with gray levels between 50 and 170.
a='C:\Users\sepideh\Desktop\IP_abadpour\S45C-113050518040.jpg';
b=imread(a);
b=b+50;
b(b>170)=170;
and you'll see when I call functions max and min, it is proved that the gray levels are between 50 and 170.
max(max(max(b)))
ans =
170
min(min(min(b)))
ans =
50
then I used imshow and imsave functions to save the image with the name "50to170"
c=imshow(b);
d=imsave(c);
Now I read the written image in this way:
a='C:\Users\sepideh\Desktop\IP_abadpour\50to170.jpg';
b=imread(a);
This time when I call max and min functions,I see:
max(max(max(b)))
ans =
235
min(min(min(b)))
ans =
16
I mean it seems that gray levels have been changed after using imshow and imsave functions!
Why does it happen?
Is it because of the format (.jpg) that I'm using when employing imsave function?
Instead of using imsave, use imwrite
b=imread(a);
b=b+50;
b(b>170)=170;
imwrite(b,'50to170.png','png')
Notice that I am saving it as a png file instead of a jpg to prevent compression. Bitmap also saves it without compression.
This method is a more direct way to save raw image matrices than using imshow and imsave.
If you want the same functionality of imsave (selecting where the file goes) check out "uiputfile" to get file name and location.
I tested it.
1.First of all you can't use imsave(b) because the function imsave expects its first input argument to be a valid handle to a single graphics object.So first you should show the image in form c=imshow(b) and then use c as an input for function imsave.
2.If you want to save the image without showing it first use function "imwrite" and pass b as the first input argument to it.
Note that if you don't want gray levels be changed after saving, you should use 'bmp' as the save format not 'jpg'.
Because 'jpg' does not support indexed images and "imwrite" converts indexed images to RGB before writing data to JPEG files so the gray levels might be changed.It's not related to the contrast stretching when showing the image in matlab.It's related to the format used to save the image.

How to read image from in memory buffer (StringIO) or from url with opencv python library

Just share a way to create opencv image object from in memory buffer or from url to improve performance.
Sometimes we get image binary from url, to avoid additional file IO, we want to imread this image from in memory buffer or from url, but imread only supports read image from file system with path.
To create an OpenCV image object with in memory buffer(StringIO), we can use OpenCV API imdecode, see code below:
import cv2
import numpy as np
from urllib2 import urlopen
from cStringIO import StringIO
def create_opencv_image_from_stringio(img_stream, cv2_img_flag=0):
img_stream.seek(0)
img_array = np.asarray(bytearray(img_stream.read()), dtype=np.uint8)
return cv2.imdecode(img_array, cv2_img_flag)
def create_opencv_image_from_url(url, cv2_img_flag=0):
request = urlopen(url)
img_array = np.asarray(bytearray(request.read()), dtype=np.uint8)
return cv2.imdecode(img_array, cv2_img_flag)
As pointed out in the comments to the accepted answer, it is outdated and no longer functional.
Luckily, I had to solve this very problem using Python 3.7 with OpenCV 4.0 recently.
To handle image loading from an URL or an in-memory buffer, I defined the following two functions:
import urllib.request
import cv2
import numpy as np
def get_opencv_img_from_buffer(buffer, flags):
bytes_as_np_array = np.frombuffer(buffer.read(), dtype=np.uint8)
return cv2.imdecode(bytes_as_np_array, flags)
def get_opencv_img_from_url(url, flags):
req = urllib.request.Request(url)
return get_opencv_img_from_buffer(urllib.request.urlopen(req), flags)
As you can see one depends on the other.
The first one, get_opencv_img_from_buffer, can be used to get an image object from an in-memory buffer. It assumes that the buffer has a read method and that it returns an instance of an object that implements the buffer protocol
The second one, get_opencv_img_from_url, generates an image directly from an URL.
The flags argument is passed on to cv2.imdecode,
which has the following constants predefined in cv2:
cv2.IMREAD_ANYCOLOR - If set, the image is read in any possible color format.
cv2.IMREAD_ANYDEPTH - If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
cv2.IMREAD_COLOR - If set, always convert image to the 3 channel BGR color image.
cv2.IMREAD_GRAYSCALE - If set, always convert image to the single channel grayscale image (codec internal conversion).
cv2.IMREAD_IGNORE_ORIENTATION - If set, do not rotate the image according to EXIF's orientation flag.
cv2.IMREAD_LOAD_GDAL - If set, use the gdal driver for loading the image.
cv2.IMREAD_REDUCED_COLOR_2 - If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.
cv2.IMREAD_REDUCED_COLOR_4 - If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
cv2.IMREAD_REDUCED_COLOR_8 - If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
cv2.IMREAD_REDUCED_GRAYSCALE_2 - If set, always convert image to the single channel grayscale image and the image size reduced 1/2.
cv2.IMREAD_REDUCED_GRAYSCALE_4 - If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
cv2.IMREAD_REDUCED_GRAYSCALE_8 - If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
cv2.IMREAD_UNCHANGED - If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).

Simple way to add an image in postscript

I am trying to write a document in postscript.
Thus far I've been able to write simple text, and work with lines and shapes.
I'm now trying to add some images to the document. After searching on-line I can't seem to find any clear way to do this.
the snip it below is a hello world:
%!PS
/Times
20 selectfont
20 800 moveto
(Hello World!) show
showpage
All I want to do is simply insert an image (eg PNG, JPG, GIF) by specifying the x and y, co-ordinates.
Any help would be much appreciated.
There is a simple method and Postscript does support the jpeg format. If you are using ghostscript you may have to use the -dNOSAFER option to open files. Here is an example:
gsave
360 72 translate % set lower left of image at (360, 72)
175 47 scale % size of rendered image is 175 points by 47 points
500 % number of columns per row
133 % number of rows
8 % bits per color channel (1, 2, 4, or 8)
[500 0 0 -133 0 133] % transform array... maps unit square to pixel
(myJPEG500x133.jpg) (r) file /DCTDecode filter % opens the file and filters the image data
false % pull channels from separate sources
3 % 3 color channels (RGB)
colorimage
grestore
Use a program like convert and then remove any extra code it generated.
You can download the PostScript Language Reference, third edition from adobe (this is the "bible book" for postscript). Chapter 4.10 Images would be a good starting point.
Is this a late answer! The problem with -dNOSAFER prevented me from using the other solutions, so I did the following:
Use Python to read the JPG file as binary and make it a string, compatible with /ASCIIHexDecode:
''.join(["%02x" % ord(c) for c in open(filename, "rb").read()])
Then instead of reading and decoding the image file from the postscript file, paste the above computed string in the postscript file, and filter it, first through /ASCIIHexDecode then /DCTDecode:
(ffd8ffe000104a46494600010102002700270000ffdb004300030202020202030202020303030304060404040404080606050609080a0a090809090a0c0f0c0a0b0e0b09090d110d0e0f101011100a0c12131210130f101010ffdb00430103030304030408040408100b090b1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010ffc00011080010001003011100021101031101ffc400160001010100000000000000000000000000060507ffc40026100002020201030207000000000000000001020304051106071221001315163132414252ffc400160101010100000000000000000000000000070403ffc4002911000201030105090100000000000000000102030004210711123151531314324142617381d1d3ffda000c03010002110311003f00de311d00e0478be19acddc79b0f8ba734aef8aa8a59a4af1c9bdc96159beef275e4efd1ccfa5f2aceea2f8e09f41e7f252a47ab4c4093ba71ceced387b7828b724e87705b588c8478ecac114e28d89e36f83d65d7643ee7eb60b03a23f1f5dff002daaacf4ae479954df1e3d33fd2b593599628d89b0071d5fae9d3bc5750b8a3f1ae3cc9cd3031b4789c689236ce568de374af543ab21b51b2b03138208076a3cef4c8b935acaf3bb05c12685036e285e550b3bccf8a41c7b2327ce78c9a6188b917b2995ab20676a8102af6dc76624c680011f9d8f0005095da5b491ccaec303f0d4f292ebba01cecf23cc57ffd9>)
/ASCIIHexDecode
filter % ascii to bytes
0 dict
/DCTDecode % jpg to explicit
filter
the above snippet replaces (myJPEG500x133.jpg) (r) file /DCTDecode filter in the otherwise very helpful #Hath995 answer.
if you want something else than JPEG but still RGB (i.e.: you want something for which postscript has no decoder), and you can use Python to prepare your postscript file, you can use PIL, like this (it ignores the transparency byte, which is a on/off operation in postscript):
import PIL.Image
i = PIL.Image.open("/tmp/from-template.png")
import itertools
''.join(["%02x" % g
for g in itertools.chain.from_iterable(
k[:3] for k in i.getdata())])
for indexed files I would not know, but it can't be difficult to work it out.

Resources