How to open a CR2 file in python OpenCV - python

I've managed to come very far on a program I'm writing. I don't know how to load CR2 files into an OpenCV Image. I've tried the following:
raw = rawpy.imread(sys.argv[1])
rgb = raw.postprocess()
PILrgb = scipy.misc.toimage(rgb)
image = cv2.imdecode(PILrgb, 1)
It was an attempt at converting the numpyarray returned by Postprocess the currently loaded RAW image and return the new resulting image as numpy array. Then calling spicy.misc.toimage to Takes a numpy array and returns a PIL image..
I get the following msg though TypeError: buf is not a numpy array, neither a scalar

It may be easier if you only rawpy
import rawpy
import cv2
raw = rawpy.imread(sys.argv[1]) # access to the RAW image
rgb = raw.postprocess() # a numpy RGB array
image = cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR) # the OpenCV image

Related

Converting PIL.Image to skimage

I have 2 modules in my project: first works with image in bytes format, second requires skimage object. I need to combine them.
I have this code:
import io
from PIL import Image
import skimage.io
area = (...)
image = Image.open(io.BytesIO(image_bytes))
image = Image.crop(area)
image = skimage.io.imread(image)
But i get this error:
How can i convert an image (object/variable) to skimage? I don't necessarily need PIL Image, this is just one way to work with bytes image, cause i need to crop my image
Thanks!
Scikit-image works with images stored as Numpy arrays - same as OpenCV and wand. So, if you have a PIL Image, you can make a Numpy array for scikit-image like this:
# Make Numpy array for scikit-image from "PIL Image"
na = np.array(YourPILImage)
Just in case you want to go the other way, and make a PIL Image from a Numpy array, you can do:
# Make "PIL Image" from Numpy array
pi = Image.fromarray(na)

Problems Converting Images from 8-bit to 10-bit

I am trying to convert 8 bit images to 10 bit. I thought it would be as easy as changing the bin values. I've tried to pillow and cv-python:
from PIL import Image
from numpy import asarray
import cv2
path = 'path/to/image'
img = Image.open(path)
data = asarray(img)
newdata = (data/255)*1023 #2^10 is 1024
img2 = Image.fromarray(newdata) #this fails
cv2.imwrite('path/newimage.png, newdata)
While cv2.imwrite successfully writes the new file, it is still encoded as an 8bit image even though bin goes up to 1023.
$ file newimage.png
newimage.png: PNG Image data, 640 x 480, 8-bit/color RGB, non-interlaced
Is there another way in either python or linux that can convert 8-bit to 10-bit?
Lots of things going wrong here.
You are mixing OpenCV (cv2.imwrite) with PIL (Image.open) for no good reason. Don't do that, you will confuse yourself as they use different RGB/BGR orderings and conventions,
You are trying to store 10-bit numbers in 8-bit vectors,
You are trying to hold 3 16-bit RGB pixels in a PIL Image which will not work as RGB images must be 8-bit in PIL.
I would suggest:
import cv2
import numpy as np
# Load image
im = cv2.imread(IMAGE, cv2.IMREAD_COLOR)
res = im.astype(np.uint16) * 4
cv2.imwrite('result.png', res)
I found a solution using pgmagick wrapper for python
import pgmagick as pgm
imagePath = 'path/to/image.png'
saveDir = '/path/to/save'
img = pgm.Image(imagePath)
img.depth(10) #sets to 10 bit
save_path = os.path.join(saveDir,'.'.join([filename,'dpx']))
img.write(save_path)

PIL image in grayscale to OpenCV format

I found the previous answer related to a more general conversion from RGB image here: Convert image from PIL to openCV format
I would like to know the difference when an image has to be read as a grayscale format.
images = [None, None]
images[0] = Image.open('image1')
images[1] = Image.open('image2')
print(type(images[0]))
a = np.array(images[0])
b = np.array(images[1])
print(type(a))
im_template = cv2.imread(a, 0)
im_source = cv2.imread(b, 0)
I get the following output:
<class 'PIL.JpegImagePlugin.JpegImageFile'>
<class 'numpy.ndarray'>
Even though I am able to convert the image to ndarray, cv2 says: "bad argument type for built-in operation". I do not need an RGB to BGR conversion. What else should I consider while passing a cv2 read argument?
You are making life unnecessarily difficult for yourself. If you want to load an image as greyscale, and use it with OpenCV, you should just do:
im = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
and that's all. No need to use PIL (which is slower), no need to use cvtColor() because you have already wasted all the memory reading it in BGR anyway.
If you absolutely want to read it using PIL (for some odd reason), use:
import numpy as np
from PIL import Image
# Read in and make greyscale
PILim = Image.open('image.jpg').convert('L')
# Make Numpy/OpenCV-compatible version
openCVim = np.array(PILim)
By the way, if you want to go back to a PIL image from an OpenCV/Numpy image, use:
PILim = Image.fromarray(openCVim)
Since you already have loaded the image, you should use an image conversion function:
im_template = cv2.cvtColor(a, cv2.COLOR_RGB2GRAY)
im_source = cv2.cvtColor(b, cv2.COLOR_RGB2GRAY)

convert ndarray object to Image

I have a gray scale image of type uint16, size = (256,256) ndarray object
I want to use PIL to resize it to (75,75) but it requires the input to be of Image type.
How can I convert image of ndarray object into Image type to use image.resize((75,75), Image.ANTIALIAS)
NOTE:
I know I can read image using Image.open if it is saved, but my image is obtained after some image processing steps and is not read from disk
UPDATE:
I am trying to provide image that I have :
import scipy.misc
scipy.misc.imsave('image.png', box_img)
# read this similar format image of type ndarray
image = scipy.ndimage.imread('image.png')
# convert it to Image type
The image attached when read of similar type as I need.
I need to convert this image into Image type
Thanks,
Gopi
from PIL import Image
import numpy as np
# An array of ones for example
img_array = np.ones((256,256), dtype='uint16')
img = Image.fromarray(img_array)
img = img.resize((75,75))

Python: How to write a single channel png file from numpy array?

I want to write a single channel png image from a numpy array in python?
In Matlab that would be
A = randi(100,100,255)
imwrite(uint8(A),'myFilename.png','png');
I saw exampels using from PIL import Image and Image.fromarray() but they are for jpeg and 3-channel pngs only it appears...
I already found the solution using opencv, I will post it here. Hopefully it will shorten someone else's searching...
Here is a solution using opencv / cv2
import cv2
myImg = np.random.randint(255, size=(200, 400)) # create a random image
cv2.imwrite('myImage.png',myImg)
PIL's Image.fromarray() automatically determines the mode to use from the datatype of the passed numpy array, for example for an 8-bit greyscale image you can use:
from PIL import Image
import numpy as np
data = np.random.randint(256, size=(100, 100), dtype=np.uint8)
img = Image.fromarray(data) # uses mode='L'
This however only works if your array uses a compatible datatype, if you simply use data = np.random.randint(256, size=(100, 100)) that can result in a int64 array (typestr <i8), which PIL can't handle.
You can also specify a different mode, e.g. to interpret a 32bit array as an RGB image:
data = np.random.randint(2**32, size=(100, 100), dtype=np.uint32)
img = Image.fromarray(data, mode='RGB')
Internally Image.fromarray() simply tries to guess the correct mode and size and then invokes Image.frombuffer().
The image can then be saved as any format PIL can handle e.g: img.save('filename.png')
You might want not to utilise OpenCV for simple image manipulation. As suggested, use PIL:
im = Image.fromarray(arr)
im.save("output.png", "PNG")
Have you tried this? What has failed here that led you to concluding that this is JPEG-only?

Categories

Resources