Writing multiple images with OpenCv2 in Python - python

I got a Data set which full of images. My aim is converting this images to gray scale. I can easily do this with one image but I need to do whit multiple images. Here is my code;
import cv2
import glob
path = "/path/*.jpg"
for file in glob.glob(path):
img = cv2.imread(file)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('Gray image', gray)
cv2.imwrite('/path/cat' + '_gray.jpg', gray)
When I run this script, it's only convert a single image but my aim is converting the all images in the path. I'm really beginer on image processing and OpenCv2 module. Thanks already now for your helps.

'/path/cat' + '_gray.jpg' always gives you /path/cat_gray.jpg, regardless of the input filename.
You probably want to use some part of the original file name there, which you can find using the functions in the os.path module.
For example:
import cv2
import glob
import os.path
path = "/path/*.jpg"
for file in glob.glob(path):
img = cv2.imread(file)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('Gray image', gray)
basename = os.path.basename(file) # e.g. MyPhoto.jpg
name = os.path.splitext(basename)[0] # e.g. MyPhoto
cv2.imwrite('/path/' + name + '_gray.jpg', gray)

Related

Converting a TIFF Image saved with a transparency can't be converted to JPEG image in Python

I am trying to solve a problem in Python where I am needing to convert TIFF images to JPEGs. I have tried using Pillow as well as OpenCV to do this but keep getting errors when I try to convert a TIFF image that has the transparency saved on it. If I save the TIFF and remove the transparency it saves the JPEG successfully. The transparency has to remain on the TIFF. Does anyone know of a solution for this issue? If I could find a way to even save the TIFF without the transparency via a Python script, save as a JPEG, and then delete the TIFF without the transparency that would work too. Any help here would be greatly appreciated. Below are examples of code I have tried that have failed:
import os
from PIL import Image
os.chdir('S:/DAM/Test/Approved/')
# for root, dirs, files in os.walk('S:/DAM/Test/Approved'):
for root, dirs, files in os.walk('.'):
for name in files:
if name.endswith('.tif'):
filename = os.path.join(root, name)
print('These are the files: ', filename)
# img = Image.open(filename).convert('RGB')
img = Image.open(filename)
print('image is open', filename)
img = img.convert('RGB')
print('image should be converted: ', filename)
imageResize = img.resize((2500, 2500))
print('image should be resized: ', filename)
imageResize.save(filename[:-4]+'.jpg', 'JPEG')
print('image should be saved as a jpeg: ', filename)
Here is the error I get when Python tries to open the TIFF with transparency using Pillow:
Exception has occurred: UnidentifiedImageError
cannot identify image file '.\\Beauty Images\\XXX.tif'
File "U:\Python files\image_conversion2.py", line 22, in <module>
img = Image.open(filename)
When I run this code using OpenCV it fails on the same image as well:
img = cv2.imread('S:/DAM/Test/Approved/Beauty Images/XXX.tif')
cv2.imwrite('S:/DAM/Test/Approved/Beauty Images/XXX.jpg', img)
Here is the error I get with this code:
OpenCV(4.2.0) C:\projects\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp:715: error: (-215:Assertion failed) !_img.empty() in function 'cv::imwrite'
File "U:\Python files\img_convert_new.py", line 19, in <module>
cv2.imwrite('S:/DAM/Test/Approved/Beauty Images/XXX.tif', img)
Here is how to read a CMYKA TIFF with Python Wand, remove the alpha channel, save it to JPG and also convert the image to OpenCV format.
Input:
from wand.image import Image
from wand.display import display
import numpy as np
import cv2
with Image(filename='guinea_pig.tiff') as img:
display(img)
with img.clone() as img_copy:
# remove alpha channel and save as JPG
img_copy.alpha_channel='off'
img_copy.format = 'jpeg'
img_copy.save(filename='guinea_pig.jpg')
display(img_copy)
# convert to opencv/numpy array format and reverse channels from RGB to BGR for opencv
img_copy.transform_colorspace('srgb')
img_opencv = np.array(img_copy)
img_opencv = cv2.cvtColor(img_opencv, cv2.COLOR_RGB2BGR)
# display result with opencv
cv2.imshow("img_opencv", img_opencv)
cv2.waitKey(0)
Resulting JPG:
Thanks to #cgohlke the solution was found! The solution is as follows using imagecodecs. The fullpath variable is the root + '/' + file of the source path.
for root, subdirs, files in os.walk(src):
for file in files:
fullpath = (root + '/' + file)
from imagecodecs import imread, imwrite
from PIL import Image
imwrite(fullpath[:-4] + '.jpg', imread(fullpath)[:,:,:3].copy()) # <-- using the imagecodecs library function of imread, make a copy in memory of the TIFF File.
# The :3 on the end of the numpy array is stripping the alpha channel from the TIFF file if it has one so it can be easily converted to a JPEG file.
# Once the copy is made the imwrite function is creating a JPEG file from the TIFF file.
# The [:-4] is stripping off the .tif extension from the file and the + '.jpg' is adding the .jpg extension to the newly created JPEG file.
img = Image.open(fullpath[:-4] + '.jpg') # <-- Using the Image.open function from the Pillow library, we are getting the newly created JPEG file and opening it.
img = img.convert('RGB') # <-- Using the convert function we are making sure to convert the JPEG file to RGB color mode.
imageResize = img.resize((2500, 2500)) # <-- Using the resize function we are resizing the JPEG to 2500 x 2500
imageResize.save(fullpath[:-4] + '.jpg') # <-- Using the save function, we are saving the newly sized JPEG file over the original JPEG file initially created.

Image frames to video

I've tried using all the approaches already mentioned here but none of them are working for whatever reason.
import cv2
import os
import glob
path = '.../Desktop/Plot/'
os.chdir(path)
# video_name = 'video.avi'
width=640
height=400
size = (width,height)
img_array = []
for filename in sorted(glob.glob(path+'*.png')):
img = cv2.imread(path+filename+'.png')
img_array.append(img)
out = cv2.VideoWriter('project.avi',cv2.VideoWriter_fourcc(*'DIVX'), 15, size)
for i in range(len(img_array)):
out.write(img_array[i])
out.release()
I don't see any thing particularly wrong with this code but all it does is put a 6 kb file in the folder that doesn't play.
I see many instakes in code.
1) most systems doesn't know path ... which you have in '.../Desktop/Plot/' and it may need to be .. or ../.. instead of ...
2) you use relative path - '.../Desktop/Plot/' and when you use os.chdir() to change directory then relative path with current folder will create path
../Desktop/Plot/../Desktop/Plot/
and it is not correct path.
3) glob.glob(path+'*.png') will create filenames with path and .png but you add path and .png to read image in imread() - so you get filename with double path and dougle extension
../Desktop/Plot/../Desktop/Plot/filename.png.png
use print(path+filename+'.png') to see what you try to read.
BTW: cv2 doesn't raise error when it can't read image but it return empty frame/image and you can get error when it try to modify empty image.
4) if images have size different than 640x400 then it will create empty video because it doesn't resize images when you save in video. You have to manually resize images before save in file
img = cv2.resize(img, (width, height))
BTW some decoders don't work with some file extensions - for example 'DIVX' will not save in file with textension .mov
BTW you can do all with one for-loop and without img_array
My version
import cv2
import os
import glob
path = '../Desktop/Plot/'
#print(os.getcwd())
width = 640
height = 400
out = cv2.VideoWriter('project.avi', cv2.VideoWriter_fourcc(*'DIVX'), 15, (width,height))
for filename in sorted(glob.glob(path + '*.png')):
print(filename)
img = cv2.imread(filename)
img = cv2.resize(img, (width, height))
out.write(img)
out.release()

Relative path for imread in python

I cant set the relative path for the DSC_1902.JPG image(in the "Res" directory) in imread. Following is my project structure:
BasicAI Server/Res/DSC_1902.JPG
BasicAI Server/Computer_Vision/FD.py
The following code is in FD.py
import cv2
def detect():
img = cv2.imread('\BasicAI Server\Res\DSC_1902.JPG')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
detect()
It is better to avoid slashes in the paths by using the os.path.join function to build the platform independent path string.
Relative path can be converted to absolute path using the functions path.join and getcwd from the os module as follows:
import cv2
import os
def detect():
absolute_path = os.path.join(os.getcwd(), 'BasicAI Server', 'Res', 'DSC_1902.JPG');
img = cv2.imread(absolute_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
detect()
This will work provided the code is executed from the parent directory of BasicAI Server directory.

Image.open() cannot identify image file in python script file

I am trying to execute this script
from PIL import Image
im = Image.open("image.jpg")
nx, ny = im.size
It is working fine when I run it in python shell
pytesser_v0.0.1]#env python
>>> from PIL import Image
>>> im = Image.open("image.jpg")
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=46x24 at 0x7FA4688F16D0>
but when I put it in a some test.py file and run it like python test.py
I am getting this error
File "test1.py", line 17, in <module>
im = Image.open("image.jpg")
File "/usr/local/python.2.7.11/lib/python2.7/site-packages/PIL/Image.py", line 2309, in open
% (filename if filename else fp))
IOError: cannot identify image file 'image.jpg'
please help me with this issue, Thanks
PS: Earlier I installed PIL from Imaging-1.1.7 setup.py, later I installed Pillow, I think the problem was in the mutual presence of the PIL and Pillow library on the machine.
Seems like PIL library haven't fixed this bug yet.
Here is my solution:
Open image using OpenCV library, then convert it to PIL image
from PIL import Image
import cv2
image_path = 'Folder/My_picture.jpg'
# read image using cv2 as numpy array
cv_img = cv2.imread(image_path)
# convert the color (necessary)
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
# read as PIL image in RGB
pil_img = Image.fromarray(cv_img).convert('RGBA')
Then you can operate with it as with a regular PIL image object.
Make sure that "image.jpg" is in the same directory as "test1.py".
If it isn't then you could either move it, or put the correct directory inside of Image.open().
I have the same issue.
This is because the test.py does not have the same pathname. If you are working in the same folder it will work.
However, the solution i found was to put in the full path + file name so that it is unambiguous.
"c:\...fullpath...\image.jpg"
You can do it like this:
from PIL import Image
import os
curDir = os.getcwd()
fileName = "image.jpg"
fn = curDir + "\\" + fileName
print(fn)
image = Image.open(fn)
image.show()
This works. Please let me know if you find better.

error: (-215) !empty() in function detectMultiScale

I'm trying to learn cv2 in python 2.7, but when I run my code, in the specific part of it:
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
img = cv2.imread('2015-05-27-191152.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
it returns this:
File "face_detection.py", line 11, in <module>
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
cv2.error: /home/arthurckl/Desktop/opencv-3.0.0-rc1/modules/objdetect/src/cascadedetect.cpp:1595: error: (-215) !empty() in function detectMultiScale
I tried to search the answer here but the best i could find is that I must be loading the face_cascade the wrong way... Any help?
I had the same issue.
I didn't need to download anything else to solve this. CV2 had everything I needed.
Instead of trying to figure out where the .xml files are and hard coding the values, I used a property given by cv2.
From OP
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
Becomes
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml')
The XML or file is missing or the path to it is incorrect or the create_capture path is incorrect.
The paths in the opencv sample look like this:
cascade_fn = args.get('--cascade', "../../data/haarcascades/haarcascade_frontalface_alt.xml")
nested_fn = args.get('--nested-cascade', "../../data/haarcascades/haarcascade_eye.xml")
cam = create_capture(video_src, fallback='synth:bg=../data/lena.jpg:noise=0.05')
I ran the same code. There are two things to note here.
1. Give the entire path of the .xml files.
2. Give a key press event instruction at the end.
Add this block of code at the end and run your file, worked for me:
k = cv2.waitKey(0)
if k == 27: # wait for ESC key to exit
cv2.destroyAllWindows()
elif k == ord('s'): # wait for 's' key to save and exit
cv2.imwrite('messigray.png',img)
cv2.destroyAllWindows()
For example, my code looked like
import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('C:\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('C:\\opencv\\build\\etc\\haarcascades\\haarcascade_eye.xml')
img = cv2.imread('lena.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
#faces = face_cascade.detectMultiScale(gray)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
cv2.imshow('img',img)
k = cv2.waitKey(0)
if k == 27: # wait for ESC key to exit
cv2.destroyAllWindows()
elif k == ord('s'): # wait for 's' key to save and exit
cv2.imwrite('messigray.png',img)
cv2.destroyAllWindows()
My output looked like this:
You just need to add proper path of the haarcascade_frontalface_default.xml file i.e. you only have to add prefix (cv2.data.haarcascades)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml')
The XML file is missing, you can get the file from the GitHub repository and place it in the same directory as your project. Link to the folder on GitHub is here. Just download the file named haarcascade_frontalface_default.xml.
Actually, the file exists on your system. Just go to the site-packages folder of your python installation folder and check the cv2/data folder for the file
Use the entire file path and use "\\" instead of "\" in the xml file path.
The file path should be as follows:
face_cascade = cv2.CascadeClassifier('C:\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_default.xml')
instead of:
cascade_fn = args.get('--cascade', "..\..\data\haarcascades\haarcascade_frontalface_alt.xml")
no need to change the code
download that .xml file , then put the path of that file
it will solve the error (100%)
If you are using Anaconda you should add the Anaconda path.
new_path = 'C:/Users/.../Anaconda/Library/etc/haarcascades/'
face_cascade = cv2.CascadeClassifier(new_path + 'haarcascade_frontalface_default.xml')
This error means that the XML file could not be found. The library needs you to pass it the full path, even though you’re probably just using a file that came with the OpenCV library.
You can use the built-in pkg_resources module to automatically determine this for you. The following code looks up the full path to a file inside wherever the cv2 module was loaded from:
import pkg_resources
haar_xml = pkg_resources.resource_filename(
'cv2', 'data/haarcascade_frontalface_default.xml')
For me this was '/Users/andrew/.local/share/virtualenvs/foo-_b9W43ee/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_default.xml'; yours is guaranteed to be different. Just let python’s pkg_resources library figure it out.
classifier = cv2.CascadeClassifier(haar_xml)
faces = classifier.detectMultiScale(frame)
Success!
On OSX with a homebrew install the full path to the opencv folder should work:
face_cascade = cv2.CascadeClassifier('/usr/local/Cellar/opencv/3.4.0_1/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('/usr/local/Cellar/opencv/3.4.0_1/share/OpenCV/haarcascades/haarcascade_eye.xml')
Take care of the version number in the path.
Probably the face_cascade is empty. You can check if the variable is empty or not by typing following command:
face_cascade.empty()
If it is empty you will get True and this means your file is not available in the path you mentioned.
Try to add complete path of xml file as follows:
r'D:\folder Name\haarcascade_frontalface_default.xml'
"\Anaconda3\Lib\site-packages\cv2\data\" I found the xml file in this path for Anaconda
You can solve this problem by placing XML in the same directory in which your main python file (from where you tried to include this file) was placed. Now the next step is to use full path. For example
This will not work
front_cascade = cv2.CascadeClassifier('./haarcascade_eye.xml')
Use full path, now it will work fine
front_cascade = cv2.CascadeClassifier('/Users/xyz/Documents/project/haarcascade_eye.xml')
I found this in some other answer but eventually worked for me when I added the two answers.
import cv2
from matplotlib import pyplot as plt
import numpy as np
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_eye.xml")
img = cv2.imread('image1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
You may find such kind of errors when you did not define the complete path of your XML file.
Try this one if you are using opencv3.1.0 in raspberrypi 3:
faceCascade = cv2.CascadeClassifier('/home/pi/opencv-3.1.0/data/haarcascades/haarcascade_frontalface_default.xml')
Your XML file was not found. Try using absolute paths like:
/path/to/my/file (Mac, Linux)
C:\\path\\to\\my\\file (Windows)
the error may be due to, the required xml files has not been loaded properly. Search for the file haarcascade_frontalface_default.xml by using the search engine of ur OS get the full path and put it as the argument to cv2.CascadeClassifier as string
Please do not copy paste the content of xml file, because once you paste it to notepad it will be saved a s text file. So directly download the file from the given source.
I ran into the same problem. but wrote the correct location.
face_cascade = cv2.CascadeClassifier('./model/haarcascade_frontalface_default.xml')
I figured out that i need to declare the full path to remove the error.
face_cascade = cv2.CascadeClassifier('C:/pythonScript/Facial-Emotion-Detection/model/haarcascade_frontalface_default.xml')
The error occurs due to missing of xml files or incorrect path of xml file.
Please try the following code,
import numpy as np
import cv2
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
cap = cv2.VideoCapture(0)
while 1:
ret, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
cv2.imshow('img',img)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
I had the same problem with opencv-python and I used a virtual environment.
If it's your case, you should find the xml files at:
/home/username/virtual_environment/lib/python3.5/site-packages/cv2/data/haarcascade_frontalface_default.xml
/home/username/virtual_environment/lib/python3.5/site-packages/cv2/data/haarcascade_eye.xml
Please be sure that you're using the absolute path. Otherwise, it won't work.
The main idea of the solution as above mentioned: find the right path of the .xml file and use it to access the file correctly.
In my case, I installed the opencv in anoconda env, first direct to path of Anoconda, then
find the path of .xml file by using:
$ find . -name 'haarcascade_eye.xml' (for example search the haarcascade_eye.xml file in current dir (.))
Then use the return path:
eye_cascade = cv2.CascadeClassifier(path + 'haarcascade_eye.xml')
I faced a similar issue. It seems correcting the path to XML makes this error to go away.
It seems to be file path issue. I changed code like this and it worked.
haar_face_filename = "D:\Sandbox\Github\Faces\haar_face.xml"
haar_cascade = cv.CascadeClassifier(haar_face_filename)
I had the same issue and was trying to use open cv in a springboot application where my xml files and images are in resources folder.
Trying to give path starting from src or a absolute path like C:\a\b.xml did not work.
Creating the file path dynamically with project root path worked.
String classifierPath = System.getProperty("user.dir") + "/src/main/resources/haarcascades/haarcascade_frontalface.xml";
// similarly for image paths
Path needs to start with /, eg. /file.xml.

Categories

Resources