CV2.imread() Python image not loading and no error displayed - python

In my python flask program hosted on Ubuntu using Apache2, the program I wrote usually is able to use imread to compress and process an image. The code now is not being able to access the image even though the file path are correct and it is an existing file and does not return any error message. This seems to occur with any type of image not depending on the type of file and the code sometimes returns a none type is not subscript able if that is related to this issue. Thanks for any help in advance! The code:
img = cv2.imread(file_path)
height, width, _ = img.shape
roi = img[0: height, 0: width]
_, compressedimage = cv2.imencode(".jpg", roi, [1, 90])
file_bytes = io.BytesIO(compressedimage)

code sometimes returns a none type
It looks to me like the file path you are supplying might be incorrect. I am saying this because cv2.imread does not throw an error for a non-existent file path:
img = cv2.imread("/non/existent/image.jpeg")
Rather it returns None:
img is None
(returns True). Your code would then fail on img.shape line. So you could either check that the file path is correct before supplying to cv2.imread:
assert os.path.isfile(file_path)
or you could assert img is not None after doing the imread and before going further.
EDIT:
I see that you are claiming that you have checked that the file path is correct and the file exists. But then you are yourself saying
the code sometimes returns a none type is not subscript able
This is because of img[0: height, 0: width] where you are trying to index/subscript None.
You can check that if you type None[0], you get the same error TypeError: 'NoneType' object is not subscriptable. So I still feel that the image path is not correct or it is not a valid image file (has some other extension than the ones listed here). In both cases you get a None on imread.
Since the code snippet you've provided is a part of a larger app, the problem could be somewhere else such that sometime the file path is valid and sometime it is not? I am only guessing at this point.

You can't expect cv2.imshow() to work inside flask or apache.
When apache starts it generally switches user to a user and group called www so it doesn't have the same environment (PATH, HOME DISPLAY and other variables) as when you run something from your Terminal sitting in front of your screen.
Nor does the www user even have the same Python modules installed if you added them to your own user.
It also doesn't have a tty where it could apply cv2.waitKey() to tell if you had pressed a key - to quit, for example.
It also doesn't have permission to draw on your screen - or even know who you are or which one of the potentially many attached screens/sessions you are sitting at.
Maybe consider looking at the logging module to debug/monitor your script and log the image path and its file size prior to cv2.imread() and its shape and dtype afterwards.

I had the same issue.
The solution was to "clean" the path.
I had spaces and "+" in the filepath, and by replacing both with "_" the files are now properly read by cv2.imread().

Related

Python Pillow Image.show() Path Issue?

Honest warning—I'm a total beginner.
I'm using Python 3.8.2 in IDLE and sometimes in Spyder.
My goal: to open an image (located in a folder) in Preview using Pillow
My code:
from PIL import Image
my_image = Image.open("flower.jpg")
my_image.show(r"/Users/User/Desktop/flower.jpg")
I run this, and it works! But it only works if the jpg is on the Desktop. I want to put the image in a folder. So I changed my last line of code to something like this:
my_image.show(r"/Users/User/Desktop/folder/flower.jpg")
I put the image in the folder, run the program, and get this error:
**FileNotFoundError: [Errno 2] No such file or directory: 'flower.jpg'**
Oddly, if I put the jpg back onto the Desktop and still use the path with "folder" in it, the program runs successfully and shows me the image.
Is this a problem with the path? How can I use Image.show() to open an image that is located somewhere other than the Desktop?
Thank you!
If you want to open and view an image using an absolute path, you'll have to change this line:
my_image = Image.open(path_to_image_dir)
You've incorrectly passed a string to PIL.Image.show. This doesn't throw an error, since PIL.Image.show happens to take an optional string parameter title, which it will use as a title in the image window. Don't pass any parameters to show, and change "flower.jpg" in the line above to the actual path.

How to store image input given by Pi Camera directly into a variable rather than to a file?

I want to store the input given by my pi camera directly into a variable, rather than storing it in a file. I want to do this so that it takes less processing power of the pi, as I am working on a autonomus car project and it takes alot of processing. When I try to store the image to a variable it gives me the following error -
AttributeError: 'int' object has no attribute 'name'
During handling of the above exception, another exception occurred:
'Format must be specified when output has no filename')
picamera.exc.PiCameraValueError: Format must be specified when output has no filename
My code -
img = 1
camera = picamera.PiCamera()
camera.capture(img)
time.sleep(0.0001)
img = cv2.imread(img)
cv2.imshow('img', img)
cv2.waitKey(1)
I have made img as a variable to store the captured image, but it is not working. If there is any library that can do this for me please do let me know.
Thanks in advance for your kind response.
Came across the same issue but the answers proposed around the web were not clear enough for my issue. Also, this is the first result that came up during my research, and yet there are no answers to it. Hopefully my summary helps answer this problem properly. Here is how I figured it out:
camera.capture(output, 'jpeg', use_video_port=True)
this statement takes an output, an optional output type (must be specified if the format cannot be figured out from the output name), and whether or not you will use the video port for the output.
output must be a bytes-like object. So this means that we should feed it a BytesIO object. By doing this, we get a stream of the desired output.
However, if you try to process this stream immediately, you will notice that there seems to be no data. This is because the internal pointer is pointing at the end of the stream. We must first move it to the start with myStream.seek(0).
After doing this, we have a file on which we can do proper work. You can send it to a server, use PIL features on it or whatever you want.
Summary of the above:
my_stream = BytesIO() #create a bytes object so the capture can output to it
camera.capture(my_stream, 'jpeg', use_video_port=True) #output the camera feed to my_stream
my_stream.seek(0) #go to the start of the stream in order to do work on it
for example, in my case, I could just send this to my websocket server directly with await websocket.send(my_stream)

Renaming image files if statement is false

So explained briefly I have a folder where I put some images into. The name of the images are integers, so for example I could have 5 images with the names 567.jpg, 568.jpg, 569.jpg, 570.jpg, and 571.jpg. The integer numbers are random, however, they always come in a sequence like above, i.e. increasing by one for every image.
So what I want to do is to go through the images in this folder and look at the image size. If the width of an image is under 600px (as an example) I want to delete this image and move on to the next image. Now, if this image is then above 600px it should be renamed such as it follows the sequence.
So in principle what should happen is:
345.jpg --> Over 600px --> Nothing happens
346-jpg --> Under 600px --> Gets deleted
347.jph --> Over 600px --> Gets renamed to 346.jpg (to follow the 1 step sequence)
And so on...
I have tried with the following code:
import os
from PIL import Image
img_dir_path = "\"
pic_list = range(567,572,1)
for image in pic_list:
img = Image.open("{}/{}.jpg".format(img_dir_path, image))
if img.size[0] < 600:
os.remove("{}/{}.jpg".format(img_dir_path, image))
else:
if os.path.isfile("{}/{}.jpg".format(img_dir_path, int(image)-1)) == False:
os.rename('{}/{}.jpg'.format(img_dir_path, int(image)), '{}/{}.jpg'.format(img_dir_path, int(image)-1))
else:
print "No worries"
However, when doing so I get the follow error:
WindowsError: [Error 32] The process cannot access the file because it is being used by another process
For the rename process that it...
I know this is some sloppy code, but I'm not a Python expert yet, so I usually just make it work first, and then tweak.
In addition, another problem that arises is that when checking if the entry before the true first entry exists / is false, it always is false now since there of course is nothing before the first image. Therefore, the image with the first name in the list should of course not be renamed. However, since I couldn't even get this to work, I wasn't going to try to fix that.
Do close the image which is opened before renaming img = Image.open("{}/{}.jpg".format(img_dir_path, image))
Image.close()
before rename

OpenCV NoneType object has no attribute shape

Hello I'm working on Raspberry Pi with OpenCV. I want to try a tutorial which is ball tracking in link
http://www.pyimagesearch.com/2015/09/14/ball-tracking-with-opencv/
But when I compile it, i get an error: 'NoneType' object has no attribute 'shape'.
What should I do?
It means that somewhere a function which should return a image just returned None and therefore has no shape attribute. Try
"print img"
to check if your image is None or an actual numpy object.
I faced the same problem today, please check for the path of the image as mentioned by cybseccrypt. After imread, try printing the image and see. If you get a value, it means the file is open.
Code:
img_src = cv2.imread('/home/deepak/python-workout/box2.jpg',0)
print img_src
Hope this helps!
You probably get the error because your video path may be wrong in a way. Be sure your path is completely correct.
Hope this helps anyone facing same issue
To know exactly where has occurred, since the running program doesn't mention it as a error with line number
'NoneType' object has no attribute 'shape'
Make sure to add assert after loading the image/frame
For image
image = cv2.imread('myimage.png')
assert not isinstance(image,type(None)), 'image not found'
For video
cap = cv2.VideoCapture(0)
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret:
assert not isinstance(frame,type(None)), 'frame not found'
Helped me solve a similar issue, in a long script
I have also met this issue and wasted a lot of time debugging it.
First, make sure that the path you provide is valid, i.e., there is an image in that path.
Next, you should be aware that Opencv doesn't support image paths which contain unicode characters (see ref). If your image path contains Unicode characters, you can use the following code to read the image:
import numpy as np
import cv2
# img is in BGR format if the underlying image is a color image
img = cv2.imdecode(np.fromfile(im_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
try to handle the error, its an attribute error given by OpenCV
try:
img.shape
print("checked for shape".format(img.shape))
except AttributeError:
print("shape not found")
#code to move to next frame
This is because the path of image is wrong or the name of image you write is incorrect .
how to check?
first try to print the image using
print(img)
if it prints 'None' that means you have given wrong image path correct that path and try again.
I just meet a same problem. I solve it by updating the newest version of OpenCV. It works well with me. Hope it is also ok with you.
I work with artificially created images,i.e. I create them by myself and then train a neural network on them to perform a certain task.
So, I created these images, saved them, but when I tried to open them ( with cv2.imread(...)), I got this error.It turned out that when saving artificially created images you need to add dtype=np.uint8. That resolved the issue for me!
I also face the same issue "OpenCV NoneType object has no attribute shape" and i solve this by changing the image location. I also use the PyCharm IDE. Currently my image location and class file in the same folder.
I had the same problem. I had another program open that was using my laptop's camera. So I closed that program, and then everything worked. I found this answer by checking https://howto.streamlabs.com/streamlabs-obs-9/black-screen-when-using-video-capture-device-elgato-hd-60s-9508.
I had this issue with cap = cv2.VideoCapture(0). I changed this to cap = cv2.VideoCapture(1) and then it worked. Since it wasn't linked to the right webcam it was returning nothing. Maybe this will help good luck.
I was getting this error when trying to find the size of a photo.
Exception has occurred: AttributeError 'NoneType' object has no attribute 'shape'
After googling for like 10 mins I came across this link OpenCV: Resolving NoneType errors by Adrian Rosebrock. In that article he mentioned
An invalid image path passed to cv2.imread
While this did fix my issue I hope it fixes yours. If not I hope you can find something of use on that page as well
Try to give a correct path to the image/video like this below. Also Opencv doesn't support image paths which contain unicode characters so try this code below
cv2.imread(r'path_to_image/video_with_file_extension', flag)
I have faced same error once i worked on my simple object tracking project. The Python AttributeError: 'NoneType' object has no attribute 'shape' occurs after passing an incorrect path to cv2.imread() because the path of image/video file is wrong or the name of image/video you passed is incorrect. To solve the error, make sure to specify the correct path.
To check path exists or not try below code
import os
print(os.path.exists('your-file-path'))
I hope this may helpful to fix your code issue.
Kindly Click here for more details.

PIL "IOError: image file truncated" with big images

I think this problem is not Zope-related. Nonetheless I'll explain what I'm trying to do:
I'm using a PUT_factory in Zope to upload images to the ZODB per FTP. The uploaded image is saved as a Zope Image inside a newly created container object. This works fine, but I want to resize the image if it exceeds a certain size (width and height). So I'm using the thumbnail function of PIL to resize them i.e. to 200x200. This works fine as long as the uploaded images are relatively small. I didn't check out the exact limit, but 976x1296px is still ok.
With bigger pictures I get:
Module PIL.Image, line 1559, in thumbnail
Module PIL.ImageFile, line 201, in load
IOError: image file is truncated (nn bytes not processed).
I tested a lot of jpegs from my camera. I don't think they are all truncated.
Here is my code:
if img and img.meta_type == 'Image':
pilImg = PIL.Image.open( StringIO(str(img.data)) )
elif imgData:
pilImg = PIL.Image.open( StringIO(imgData) )
pilImg.thumbnail((width, height), PIL.Image.ANTIALIAS)
As I'm using a PUT_factory, I don't have a file object, I'm using either the raw data from the factory or a previously created (Zope) Image object.
I've heard that PIL handles image data differently when a certain size is exceeded, but I don't know how to adjust my code. Or is it related to PIL's lazy loading?
I'm a little late to reply here, but I ran into a similar problem and I wanted to share my solution. First, here's a pretty typical stack trace for this problem:
Traceback (most recent call last):
...
File ..., line 2064, in ...
im.thumbnail(DEFAULT_THUMBNAIL_SIZE, Image.ANTIALIAS)
File "/Library/Python/2.7/site-packages/PIL/Image.py", line 1572, in thumbnail
self.load()
File "/Library/Python/2.7/site-packages/PIL/ImageFile.py", line 220, in load
raise IOError("image file is truncated (%d bytes not processed)" % len(b))
IOError: image file is truncated (57 bytes not processed)
If we look around line 220 (in your case line 201—perhaps you are running a slightly different version), we see that PIL is reading in blocks of the file and that it expects that the blocks are going to be of a certain size. It turns out that you can ask PIL to be tolerant of files that are truncated (missing some file from the block) by changing a setting.
Somewhere before your code block, simply add the following:
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
...and you should be good.
EDIT: It looks like this helps for the version of PIL bundled with Pillow ("pip install pillow"), but may not work for default installations of PIL
Here is what I did:
Edit LOAD_TRUNCATED_IMAGES = False line from /usr/lib/python3/dist-packages/PIL/ImageFile.py:40 to LOAD_TRUNCATED_IMAGES = True.
Editing the file requires root access though.
I encountered this error while running some pytorch which was maybe using the PIL library.
Do this fix only if you encounter this error, without directly using PIL.
Else please do
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
Best thing is that you can:
if img and img.meta_type == 'Image':
pilImg = PIL.Image.open( StringIO(str(img.data)) )
elif imgData:
pilImg = PIL.Image.open( StringIO(imgData) )
try:
pilImg.load()
except IOError:
pass # You can always log it to logger
pilImg.thumbnail((width, height), PIL.Image.ANTIALIAS)
As dumb as it seems - it will work like a miracle. If your image has missing data, it will be filled with gray (check the bottom of your image).
Note: usage of camel case in Python is discouraged and is used only in class names.
This might not be a PIL issue. It might be related to your HTTP Server setting. HTTP servers put a limit on the size of the entity body that will be accepted.
For eg, in Apache FCGI, the option FcgidMaxRequestLen determines the maximum size of file that can be uploaded.
Check that for your server - it might be the one that is limiting the upload size.
I was trapped with the same problem. However, setting ImageFile.LOAD_TRUNCATED_IMAGES = True is not suitable in my case, and I have checked that all my image files were unbroken, but big.
I read the images using cv2, and then converted it to PIL.Image to get round the problem.
img = cv2.imread(imgfile, cv2.IMREAD_GRAYSCALE)
img = Image.fromarray(img)
I had to change the tds version to 7.2 to prevent this from happening. Also works with tds version 8.0, however I had some other issues with 8.0.
When image was partly broken, OSError will be caused.
I use below code for check and save the wrong image list.
try:
img = Image.open(file_path)
img.load()
## do the work with the loaded image
except OSError as error:
print(f"{error} ({file_path})")
with open("./error_file_list.txt", "a") as error_log:
log.write(str(file_path))

Categories