I am trying to read a raw image in .CR2 format ("Canon Raw format"). I wanted to do it with opencv initially but could not get it to work so I tried doing it with a numpy function:
img = np.fromfile('IMG.CR2', "uint16")
The camera is a canon EOS t5 18MP DSLR.
If I run img.size it return 10105415 which seems too small for an 18 MP camera.
My first question, is using np.fromfile() a valid approach?
Secondly, would you recommend any other python libraries to do the same process in an easier way/more efficient? I have openCV installed so if it could be done there, that would be great (I still want to store it as a numpy array).
Canon RAW format is not just a blob of data, it has some metadata which you need to parse. Luckily, others have already implemented some python parsers.
RAW Image processing in Python
After using one of the suggested solutions you can load the data into numpy array.
Related
I am expanding my limited Python knowledge by converting some MATLAB image analysis code to Python. I am following Image manipulation and processing using Numpy and Scipy. The code in Section 2.6.1 saves an image using both imageio.imsave and face.tofile, where type(face)=<class 'imageio.core.util.Array>'.
I am trying to understand why there are two ways to export an image. I tried web-searching tofile, but got numpy.ndarray.tofile. It's very sparse, and doesn't seem to be specific to images. I also looked for imageio.core.util.Array.tofile, but wasn't able to find anything.
Why are there two ways to export files? And why does imageio.core.util.Array.tofile seem to be un-findable online?
The difference is in what the two functions write in the file.
imageio.imsave() saves a conventional image, like a picture or photo, in JPEG/PNG format that can be viewed with an image viewer like GIMP, feh, eog, Photoshop or MSxPaint.
tofile() saves in a Numpy-compatible format that only Numpy (and a small number of other Python tools) use.
I wrote the following code:
from moviepy.editor import *
from PIL import Image
clip= VideoFileClip("video.mp4")
video= CompositeVideoClip([clip])
video.write_videofile("video_new.mp4",fps=clip.fps)
then to check whether the frames have changed or not and if changed, which function changed them, i retrieved the first frame of 'clip', 'video' and 'video_new.mp4' and compared them:
clip1= VideoFileClip("video_new.mp4")
img1= clip.get_frame(0)
img2= video.get_frame(0)
img3= clip1.get_frame(0)
a=img1[0,0,0]
b=img2[0,0,0]
c=img3[0,0,0]
I found that a=24, b=24, but c=26....infact on running a array compare loop i found that 'img1' and 'img2' were identical but 'img3' was different.
I suspect that the function video.write_videofile is responsible for the change in array. But i dont know why...Can anybody explain this to me and also suggest a way to write clips without changing their frames?
PS: i read the docs of 'VideoFileClip', 'FFMPEG_VideoWriter', 'FFMPEG_VideoReader' but could not find anything useful...I need to read the exact frame as it was before writing in a code I'm working on. Please, suggest me a way.
Like JPEG, MPEG-4 uses lossy compression, so it's not surprising that the frames read from "video_new.mp4" are not perfectly identical to those in "video.mp4". And as well as the variations caused purely by the lossy compression there are also variations that arise due to the wide variety of encoding options that can be used by programs that write MPEG data.
If you really need to be able to read back the exact same frame data that you write then you will have to use a different file format, but be warned: your files will be huge!
The choice of video format partly depends on what the image data is like and on what you want to do with it. If the data uses 256 colours or less, and you don't intend to perform transformations on it that will modify the colours, a simple GIF anim is a good choice. But bear in mind that even something like non-integer scaling modifies colours.
If you want to analyze the image data and transform it in various ways, it makes sense to use a format with better colour support than GIF, eg a stream of PNG images, which I assume is what Zulko mentions in his answer. FWIW, there's an anim format related to PNG called MNG, but it is not well supported or widely known.
Another option is to use a stream of PPM images, or maybe even a stream of YUV data, which is useful for certain kinds of analysis and convenient if you do intend to encode as MPEG for final consumption. The PPM format is very simple and easy to work with; YUV is slightly messy since it's a raw format with no header data, so you have to keep track of the image size and resolution data yourself.
The file size of PPM or YUV streams is large, since they incorporate no compression at all, but of course they can be compressed using standard compression techniques, if you want to save a little space when saving them to disk. OTOH, typical video processing workflows that use such streams often don't bother writing them to disk: they are sent in pipelines (perhaps using named pipes), so the file size is (mostly) irrelevant.
Although such formats take up a lot of space compared to MPEG-based files, they are far superior for use as intermediate formats while performing image data analysis and transformation, since every time you write & read back MPEG you are losing a little bit of quality.
I assume that you intend to do your image data analysis and transformations using PIL/Pillow. But you can also work with PPM & YUV streams using the ffmpeg / avconv command line programs; and the ffmpeg family happily work with sets of individual image files and GIF anims, too.
You can have lossless compression with the 'png' codec:
clip.write_videoclip('clip_new.avi', codec='png')
EDIT #PM 2Ring: when you write the line above, it makes a video that is compressed using the png algortihm (I'm not sure whether each frame is a png or if it's more subtle).
We got 50TB of 16bit uncompressed TIF images from a industrial sensor in our server, and we want to compress them all with lossless zip compression using python. Using python because it's easier to use Python to communicate our database.
However after hours of search and documentation reading, I found that there's not even a matured python library that can convert 16bit TIF into zip compressed tif. The latest PIL cannot write compressed tif, OpenCV hardcoded output file into LZW tif not zip(deflate). And there is no sufficient documentation in smc.freeimage, PythonImageMagick so I don't know if they can do it. I also found this tifffile.py, there seems something about compression in its source code, but there is no example code that let me understand how to config compression option for output.
Of course I can use an external executable, but I just don't want to use python as scripting language here.
So that I really appreciate if anyone give me an efficient example here, thanks.
Update:
cgohlke's code works, here I provide another light weight solution.
Checkout the patched pythontifflib code from here https://github.com/delmic/pylibtiff.
The original PythonTiffLib from google code doesn't handle RGB information well and it didn't work on my data, this patched version works, however because the code is very old, it implies PythonTiffLib may be not maintained very well.
Use the code like this:
from libtiff import TIFF
tif = TIFF.open('Image.tiff', mode='r')
image = tif.read_image()
tifw = TIFF.open('testpylibtiff.tiff', mode='w')
tifw.write_image(image, compression='deflate', write_rgb=True)
PythonMagick works for me on Windows:
from PythonMagick import Image, CompressionType
im = Image('tiger-rgb-strip-contig-16.tif')
im.compressType(CompressionType.ZipCompression)
im.write("tiger-rgb-strip-contig-16-zip.tif")
Scikit-image includes a wrapper for the FreeImage library:
import skimage.io._plugins.freeimage_plugin as fi
im = fi.read('tiger-rgb-strip-contig-16.tif')
fi.write(im, 'tiger-rgb-strip-contig-16-zip.tif',
fi.IO_FLAGS.TIFF_ADOBE_DEFLATE)
Or via tifffile.py, 2013.11.03 or later:
from tifffile import imread, imsave
im = imread('tiger-rgb-strip-contig-16.tif')
imsave("tiger-rgb-strip-contig-16-zip.tif", im, compress=6)
These might not preserve all other TIFF tags or properties but that wasn't specified in the question.
I want grab each video frames from libvlc in a (2D) numpy array using python.
I expect to use vlc.MediaPlayer.video_set_callbacks(...)
with [callbacks][1] managing an numpy array but there is no documentation about using callback with python.
Any Idea or alternative ways ?
[1]: decorated with vlc.cb.VideoLockCb and its friends
Maybe have a look at PyFFmpeg ? I do not use this python module, thus I don't know how well it works but it does adevertize the feature you require.
Edit
OpenCV is also worth a try. It is probably more stable.
OpenCV offers no less than two python bindings. The later, better one being cv2 is integrated with numpy. It is much easier to use than the older cv module. As an example, you can read video frames with the following code:
import cv2
filename = 'myfile.mpg'
capture = cv2.VideoCapture(filename)
retval, im = capture.read()
Each call to .read will output a new frame of the video.
What is the most efficient way in terms of speed to access the pixel data of a PIL image from a C extension? I only need read-only access to it, if that makes a difference.
C-level bindings for PIL are available, but there is very little documentation for them. You will need to consult the source for usage information.
Besides C extension, you can try numpy. It takes a bit to learn though. To get started, check Convert RGBA PNG to RGB with PIL , and http://effbot.org/zone/pil-numpy.htm .
In my experience, numpy performance is great if the code is properly written. Processing image data can still be slow using C extension. But numpy uses SIMD instructions such as SSE2, which dramatically improves operation such as histogram elevating or alpha blending.