How detect if an image can paste a background? - python-2.7

I'm trying convert images in Pillow==5.4.1 to JPEG. So i use this follow code:
from PIL import Image as PilImage
img = PilImage.open('energy.png')
img.convert('RGB').save('newimage.jpeg', 'jpeg')
Some images works fine, but when i try if this image:
My result is follow:
OK, i have a problem, when a image have transparency, the background turn black. So i research and follow this code:
PIL Convert PNG or GIF with Transparency to JPG without
from PIL import Image
im = Image.open("energy.png")
bg = Image.new("RGB", im.size, (255,255,255))
bg.paste(im,im)
bg.save("newimage.jpeg")
This works fine for this picture:
The background turn white, no problem i can survive with it. But when i use this code for other images:
In [28]: im = Image.open('444.png')
In [29]: bg = Image.new("RGB", im.size, (255,255,255))
In [30]: bg.paste(im,im)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-30-f36dbc2a3949> in <module>()
----> 1 bg.paste(im,im)
/home/developer/.virtualenvs/prisvo/local/lib/python2.7/site-packages/PIL/Image.pyc in paste(self, im, box, mask)
1455 if mask:
1456 mask.load()
-> 1457 self.im.paste(im, box, mask.im)
1458 else:
1459 self.im.paste(im, box)
ValueError: bad transparency mask
This error occur with this two images:
One of this two images is png (with no transparency), and the other is already jpeg, but i need to accept jpg and png. Because i need to do this:
img.convert('RGB').save(smallJpegThumbStr, 'jpeg', quality=75)
I need to compact.
So i use (and i think) a bad implementation:
try:
bg = PilImage.new("RGB", img.size, (255,255,255))
bg.paste(img,mask=img)
bg.convert('RGB').save(mediumJpegThumbStr, 'jpeg', quality=75)
except:
img.convert('RGB').save(mediumJpegThumbStr, 'jpeg', quality=75)
In others words, when occur a error i go to another implementation. I think this is not right. My first idea is use the first implementation (inside expect) to jpeg images, and second implementation to png (inside try). But the error also occur to png (for some images). I dont know if is there a condition for this command bg.paste(im,im), or if exist an way to detect this error: ValueError: bad transparency mask without using try.
This command help. But:
bg.paste(im,mask=im.convert('L'))

Related

Converting a sequence of ppm images to video with python

I'm trying to make a video out of ppm images using IPython (python 2.7).
I wrote this code :
import cv2
import glob
img1 = cv2.imread('C:/Users/Joseph/image0.ppm')
height, width, layers = img1.shape
video1 = cv2.VideoWriter('video1.avi', -1, 1, (width, height))
filenames = glob.glob('C:/Users/Joseph/*.ppm')
for filename in filenames:
print(filename)
img = cv2.imread(filename)
video1.write(img)
cv2.destroyAllWindows()
video1.release()
The video is created but is empty size=0B and it cannot be opened.
There is no error message.
I suspect the problem is the writing of the location, since print(filename) yields :
C:/Users/Joseph\image0.ppm
C:/Users/Joseph\image1.ppm
C:/Users/Joseph\image2.ppm
C:/Users/Joseph\image2.ppm
instead of what I had expected : C:/Users/Joseph/image0.ppm
Could you help me please?
EDIT: The type of file is type: GIMP 2.10.14 (.ppm). Could the issue be connected to this type of ppm ?
EDIT 2: It seems that the issue is not connected directly to .ppm.
Indeed, I tried (taking into account the answer of Rotem) :
import cv2
import glob
i = cv2.imread('C:/Users/Joseph/image0.ppm')
cv2.imwrite('C:/Users/Joseph/image.jpg',i)
img1 = cv2.imread('C:/Users/Joseph/image.jpg')
height, width, layers = img1.shape
# Set FOURCC code to '24BG' - '24BG' is used for creating uncompressed raw video
video1 = cv2.VideoWriter('video1.avi', cv2.VideoWriter_fourcc('D','I','B',' '), 1, (width, height))
filenames = glob.glob('C:/Users/Joseph/*.ppm')
try:
for filename in filenames:
print(filename)
img = cv2.imread(filename)
cv2.imwrite('C:/Users/Joseph/a.jpg',img)
img=cv2.imread('C:/Users/Joseph/a.jpg')
# Display input image for debugging
cv2.imshow('img', img)
cv2.waitKey(1000)
video1.write(img)
except:
print('An error occurred.')
cv2.destroyAllWindows()
video1.release()
And it doesn't work either. And I don't get any image displayed.
so it seems that it's an error in my cv2 for video. The jpg is well created.
EDIT : The solution.
In the spirit of the answer of rotem, I tried : cv2.VideoWriter_fourcc('M','J','P','G') and it worked !
There are multiple reasons for getting an empty video file, but the path looks correct.
In Windows system C:/Users/Joseph\image0.ppm and C:/Users/Joseph/image0.ppm are the same.
Manually delete video1.avi file, just to make sure the file is not locked.
I think the issue involved video codec, but I can't be sure about it.
in the command video1 = cv2.VideoWriter('video1.avi', -1, 1, (width, height)), the second parameter is a FOURCC code that selects the video codec for the video encoder.
When setting the value to -1, a dialog box is opened letting you select the codec.
In older versions of OpenCV it's not always working.
Try setting the FOURCC to 'DIB ', applies "Basic Windows bitmap format".
Use it for creating raw (uncompressed) AVI video file.
Here is the code:
import cv2
import glob
img1 = cv2.imread('C:/Users/Joseph/image0.ppm')
height, width, layers = img1.shape
# Set FOURCC code to '24BG' - '24BG' is used for creating uncompressed raw video
video1 = cv2.VideoWriter('video1.avi', cv2.VideoWriter_fourcc('D','I','B',' '), 1, (width, height))
filenames = glob.glob('*.ppm')
try:
for filename in filenames:
print(filename)
img = cv2.imread(filename)
# Display input image for debugging
cv2.imshow('img', img)
cv2.waitKey(1000)
video1.write(img)
except:
print('An error occurred.')
cv2.destroyAllWindows()
video1.release()
I added cv2.imshow('img', img) to help you debugging the problem, in case it's not a codec issue.
Make sure you are not getting any exceptions.
Please let me no if my answer solves your problem.

(imageio or celery) Error closing: 'Image' object has no attribute 'fp'

I am using imageio to write png images to file.
import numpy as np
import matplotlib.cm as cm
import imageio # for saving the image
import matplotlib as mpl
hm_colors = ['blue', 'white','red']
cmap = mpl.colors.LinearSegmentedColormap.from_list('bwr', hm_colors)
data = np.array([[1,2,3],[5,6,7]])
norm = mpl.colors.Normalize(vmin=-3, vmax=3)
colormap = cm.ScalarMappable(norm=norm, cmap=cmap)
im = colormap.to_rgba(data)
# scale the data to a width of w pixels
im = np.repeat(im, w, axis=1)
im = np.repeat(im, h, axis=0)
# save the picture
imageio.imwrite("my_img.png", im)
This process is performed automatically and I noticed some Error messages saying:
Error closing: 'Image' object has no attribute 'fp'.
Before this message I get warning:
/usr/local/lib/python2.7/dist-packages/imageio/core/util.py:78: UserWarning: Lossy conversion from float64 to uint8, range [0, 1] dtype_str, out_type.__name__))
However, the images seem to be generated and saved just fine.
I can't find data to recreate this message.
Any idea why I get this error and why it doesn't noticeably affect the results? I don't use PIL.
One possible reason could come from using this in Celery.
Thanks!
L.
I encountered the same issue using imageio.imwrite in Python 3.5. It's a fairly harmless except for the fact that that it's stopping garbage collection and leading to excessive memory usage when writing thousands of images. The solution was to use the PIL module, which is a dependency of imageio. The last line of your code should read:
from PIL import Image
image = Image.fromarray(im)
image.save('my_img.png')

Can not Read or Play a Video in OpenCV+Python using VideoCapture

import cv2
import numpy as np
cap = cv2.VideoCapture('traffic.avi')
retval, frame = cap.read()
print retval
================ RESTART: J:\Python For DIP\traffic_video.py ================
False
>>>
The Value of retval is always False, which means the video is not read by the command. It must be True to read frames. I don't know what to do. However when I use my default webcam it turns to be True. I tried many videos and the same problem appears. Note: I have installed the ffmpeg correctly.
Note: This is not the full code, in this step I am only validating cap.read() either True or False
This method is guaranteed 100%
first of all check your version of OpenCV, say for instance 2.4.11. you can check it by typing the following commands in your Python Shell:
>>> from cv2 import __version__
>>> __version__
'2.4.11'
>>>
Then go to C:\opencv\build\x86\vc12\bin and copy opencv_ffmpeg2411.dll.
Finally go to root directory of Python ex: C:\Python27 and paste opencv_ffmpeg2411.dll in it
check the name of the file opencv_ffmpeg2411.dll, whether the version
of opencv is written or not, if not do the following
opencv_ffmpeg(version of your opencv without dots).dll
After that create a new Python file and copy this code and paste it loading your own video
import numpy as np
import cv2
# Capture video from file
cap = cv2.VideoCapture('your video')
while True:
ret, frame = cap.read()
if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',gray)
if cv2.waitKey(30) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
you will have an output video for example like this:
Result
Finding the root directory of Python can be a little tricky. I am using an Enthought distribution and, at first, pasted the opencv_ffmpeg file into the wrong Python directory.
WRONG:
C:\Users\USERNAME\AppData\Local\Programs\Python\Python35-32
RIGHT:
C:\Users\USERNAME\AppData\Local\Enthought\Canopy\User
Long story short, make sure you find the right Python directory.

Why is pytesseract causing AttributeError: 'NoneType' object has no attribute 'bands'?

I am trying to get started using pytesseract but as you can see below I am having problems.
I have found people getting what seems to be the same error and they say that it is a bug in PIL 1.1.7. Others say the problem is caused by PIL being lazy and one needs to force PIL to load the image with im.load() after opening it, but that didn't seem to help. Any suggestions gratefully received.
K:\Glamdring\Projects\Images\OCR>python
Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from PIL import Image
>>> import pytesseract
>>> pytesseract.image_to_string(Image.open('foo.png'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "build\bdist.win32\egg\pytesseract\pytesseract.py", line 143, in image_to_string
File "c:\Python27_32\lib\site-packages\PIL\Image.py", line 1497, in split
if self.im.bands == 1:
AttributeError: 'NoneType' object has no attribute 'bands'
Try to use objects from Image and pytesseract module separately.
It solved my problem:
try:
import Image
except ImportError:
from PIL import Image
import pytesseract
img = Image.open('myImage.jpg')
img.load()
i = pytesseract.image_to_string(img)
print i
I have no prior experience with PIL but I was bored so I tried to look into it and, from what I can tell, it is probably a bug.
This isn't a fault of pytesseract if we look at the execution steps.
Initially your Image.open('foo.png') works perfectly fine with no errors relating to your stack-trace.
pytesseract.image_to_string(img) comes in afterwards and does the following:
# Omitting the rest of the method.
# calls method split() of your image object.
if len(image.split()) == 4:
This is the first statement acting on image so we know we have to look back into PIL to find the root of the problem.
Your stacktrace has the specific message AttributeError: 'NoneType' object has no attribute 'bands' with regard to the if self.im.bands statement. This means that im is the object = None.
Lets look into the image.split() method:
"""
Split this image into individual bands. This method returns a
tuple of individual image bands from an image. For example,
splitting an "RGB" image creates three new images each
containing a copy of one of the original bands (red, green,
blue).
:returns: A tuple containing bands.
"""
self.load() # This is the culprit since..
if self.im.bands == 1: # .. here the im attribute of the image = None
ims = [self.copy()]
# Omitting the rest ---
Obviously self.load() sets, among others, the im value. I verified this with a test Image and it seemed to work with no issues [I suggest you try the same with your image]:
In [7]: print img.im
None
In [8]: img.load()
Out[8]: <PixelAccess at 0x7fe03ab6a210>
In [9]: print img.im
<ImagingCore object at 0x7fe03ab6a1d0>
Let's now take a look in load():
I don't generally have the knowledge to know the internals here but I did observe something iffy: many FIXME comments before the assignment of im, specifically:
# -- Omitting rest --
# FIXME: on Unix, use PROT_READ etc
self.map = mmap.mmap(file.fileno(), size)
self.im = Image.core.map_buffer(
self.map, self.size, d, e, o, a
)
# -- Omitting rest --
if hasattr(self, "tile_post_rotate"):
# FIXME: This is a hack to handle rotated PCD's
self.im = self.im.rotate(self.tile_post_rotate)
self.size = self.im.size
This might be an indication that there might be some issues needing attention here. I can't be 100% certain though.
Of course, this might be caused by your image for some reason. The load() method worked fine with an image I supplied (and pytesseract just gave me a different error :P). You're better off probably creating a new issue for this. If any PIL experts happen to see this, enlighten us if you can.
im.load() worked for me on running program in administrator mode and also add this line if you don't have tesseract executable in your PATH
pytesseract.pytesseract.tesseract_cmd = 'C:/Program Files (x86)/Tesseract-OCR/tesseract.exe'
If you have already read an image(not using im.load() but with imread()) or frame from video and did some image processing stuff(may be not) on that variable(image) then you need to give the following command
pytesseract.image_to_string(Image.fromarray(image))
As #J_Mascis said,using objects worked here too-
import pytesseract
from PIL import Image
img = Image.open('im.jpg')
img.load()
print(pytesseract.image_to_string(img, lang='eng'))#'eng' for english

Python - fetching image from urllib and then reading EXIF data from PIL Image not working

I use the following code to fetch an image from a url in python :
import urllib
from PIL import Image
urllib.urlretrieve("http://www.gunnerkrigg.com//comics/00000001.jpg", "00000001.jpg")
filename = '00000001.jpg'
img = Image.open(filename)
exif = img._getexif()
However, this way the exif data is always "None". But when I download the image by hand and then read the EXIF data in python, the image data is not None.
I have also tried the following approach (from Downloading a picture via urllib and python):
import urllib
f = open('00000001.jpg','wb')
f.write(urllib.urlopen('http://www.gunnerkrigg.com//comics/00000001.jpg').read())
f.close()
filename = '00000001.jpg'
img = Image.open(filename)
exif = img._getexif()
But this gives me 'None' for 'exif' again. Could someone please point out what I may do to solve this problem?
Thank you!
The .jpg you are using contains no exif information. If you try the same python with an exif example from http://www.exif.org/samples/ , I think you will find it works.