I am working on a python script to get images from a microscope camera and then combine them to have an avi file.(15fps for 3sec).
I wrote a program but the final result is too dark.
I am looking for a solution to make it brighter.
When I add enhancer I get this error
ValueError: image has wrong mode
The camera gives 45 dat files .I converted them to tiff and then concatenated then to have an avi file.
The camera is Andor Neo 5.5 sCMOS
Here is a part of my code:
with tifffile.TiffWriter('datfiles.tif', bigtiff=False) as tif:
for datfile in datfiles:
data = numpy.fromfile(
datfile,
count=width * height * 3 // 2, # 12 bit packed
offset=4, # 4 byte integer header
dtype=numpy.uint8,
).astype(numpy.uint16)
image = numpy.zeros(width * height, numpy.uint16)
image[0::2] = (data[1::3] & 15) | (data[0::3] << 4)
image[1::2] = (data[1::3] >> 4) | (data[2::3] << 4)
image.shape = height, width
#img = increase_brightness(image)
tif.write(
image, photometric='minisblack', compression=None,
metadata=None)
img = Image.open('datfiles.tif')
enhancer = ImageEnhance.Brightness(img)
img=enhancer.enhance(4)
for i in range(45):
try:
img.seek(i)
img.save('page_%s.tif'%(i,))
except EOFError:
break
os.remove("datfiles.tif")
'''
------------------------------------------
Concatenate the tif files ----> .avi of 3 sec
'''
image_folder =os.getcwd() #to be modified
print(image_folder) #testing
video_name = "ConcatenatedVideo.avi"
images = [img for img in os.listdir(image_folder) if img.endswith(".tif")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 15, (width,height))
for image in images:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
for f in os.listdir(image_folder): #delete allthe tiff files
if(f.endswith(".tif")):
os.remove(os.path.join(image_folder, f))
print('finished')
os.chdir(path)
Related
In my code i'm looping over frames of a video, and trying to generate another mp4 video.
This is my code:
cap = cv2.VideoCapture(args.video)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (frame_width, frame_height))
while cap.isOpened():
ret, img = cap.read()
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
out.release()
break
#<code>...
#<code>...
print(type(my_image))
out.write(my_image)
The output of print(type(my_image)) is numpy.ndarray for each frame. When I ran the code, i got output_video.mp4 file, but weights only 300 kb (it needs to be about 50 mb).
I tried to save each frame as an image, and to see if it will work, and it did. This is the code:
img = Image.fromarray(my_image, 'RGB')
img.save('frameeeee-%s.png'%i)
I coded this function to solve a similiar problem, you need to save the images singularly into a folder and then you can use frames2video to convert it into a video.
def frames2video( path_in = "/content/original_frames" , path_out = "/content/outputvideo",
frame_rate = 30 , video_name="output_video" ):
"""
Given an input path to a folder that contains a set of frames, this function
convert them into a video and then save it in the path_out.
You need to know the fps of the original video, are 30 by default.
"""
img_path_list = natsorted(os.listdir(path_in))
assert(len(img_path_list)>0)
img_array = []
print("[F2V] Frames to video...", end="\n\n")
with tqdm(total=len(img_path_list)) as pbar:
for count,filename in enumerate(img_path_list):
img = cv2.imread(path_in+"/"+filename)
if(img is None):break
height, width, layers = img.shape
img_array.append(img)
size = (width,height)
pbar.update()
if os.path.exists(path_out): shutil.rmtree(path_out)
os.mkdir(path_out)
out = cv2.VideoWriter(path_out+"/"+str(video_name)+'.mp4', cv2.VideoWriter_fourcc(*'DIVX'), frame_rate, size)
for i in range(len(img_array)):
out.write(img_array[i])
out.release()
print("\n[F2V] Video made from "+str(count+1)+" frames", end="\n\n")
For completeness, i post also the viceversa, a function that given a video extract the frames.
def n_frames(video):
"""
Given an input video returns the EXACT number of frames(CV2 was not precise)
"""
success = True
count = 0
while success:
success,image = video.read()
if success == False: break
count+=1
return count
def video2frames( path_in = "/content/video.mp4" , path_out = "/content/original_frames",
n_of_frames_to_save = 999999, rotate=True, frames_name = "OrigFrame" ):
"""
Given a video from path_in saves all the frames inside path_out.
The number of frames(in case of long videos) can be truncated with
the n_of_frames_to_save parameter. Rotate is used to save rotated
frames by 90 degree. All the frames are named frames_name with an
index
"""
blur_threshold = 0
if os.path.exists(path_out): shutil.rmtree(path_out)
os.mkdir(path_out)
count = 0
success = True
vidcap = cv2.VideoCapture(path_in)
v2 = cv2.VideoCapture(path_in)
fps = vidcap.get(cv2.CAP_PROP_FPS)
if(fps>120):
print("CAP_PROP_FPS > 120, probabily you are using a webcam. Setting fps manually")
fps = 25
n_of_frames = n_frames(v2) # #int(video.get(cv2.CAP_PROP_FRAME_COUNT)) is not accurate, https://stackoverflow.com/questions/31472155/python-opencv-cv2-cv-cv-cap-prop-frame-count-get-wrong-numbers
if(n_of_frames_to_save < n_of_frames): n_of_frames = n_of_frames_to_save
print("[V2F] Dividing the video in " + str(n_of_frames) + " frames", end="\n\n")
for count in trange(n_of_frames):
success,image = vidcap.read()
if not success: break
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
if(rotate): image = cv2.rotate(image,cv2.ROTATE_90_CLOCKWISE)
plt.imsave("%s/%s%d.png" % (path_out,frames_name+"_", count), image)
count+=1
print("\n[V2F] "+str(count)+" frames saved",end="\n\n")
return fps
Ok, I found a solution. I noticed that I had resize function in my code:
my_image = cv2.resize(image_before, (1280, 720))
So I changed
out = cv2.VideoWriter('output_video.mp4', fourcc, fps, (frame_width, frame_height))
to
out = cv2.VideoWriter('outputttttt.mp4', fourcc, fps, (1280, 720))
And it works (:
I have the following code that uses PIL to paste an image on top on another.
I want to repeat this process to do it automatically with 1000+ images. Is there a way to loop it by choosing 1000+ images from a folder and pasting them on top of another 1000+ images from another folder?
from PIL import Image, ImageOps
img = Image.open('image1.png', 'r')
img_w, img_h = img.size
background = Image.open('image2.png', 'r')
bg_w, bg_h = background.size
offset = ((bg_w - img_w) // 1, (bg_h - img_h) // 6)
background.paste(img, offset)
background.save('out.png')
My interpretation is that you want all images in one folder to go over all images in another folder.
You need to itr over all the file in your directories and except IOError in case that there isn't it supported image file you've itr'd over.
You will need to import os, and filename the image is saved as is the iteration number.
This is what your code would look like:
from PIL import Image, ImageOps
import os
dir = "C:/Users/User/Pictures/"
dir2 = "C:/Users/User/Pictures/"
images = os.listdir(dir)
images2 = os.listdir(dir2)
itr = 1
for image in images:
for image2 in images2:
try:
img = Image.open(dir + image, 'r')
img_w, img_h = img.size
background = Image.open(dir + image2, 'r')
print("Image = " + image + " background = " + image2 + " at itr "+ str(itr))
print("")
bg_w, bg_h = background.size
offset = ((bg_w - img_w) // 1, (bg_h - img_h) // 6)
background.paste(img, offset)
background.save('./How do I loop this Python PIL code/' + str(itr)+ ".png")
itr += 1
except IOError:
pass
I am using OpenCV-python for creating video file using images.
When I run the code then no errors are shown and after 11 or 14 seconds the code executes.
But when I try to open the video file which was saved by the code. It raised an error in opening the file.
In VLC it's showing only a blank screen and in windows media player it's showing this:-
And the size of the video is 8.00 Kb always.
Here is the code:-
import cv2
import os
from os.path import isfile, join
def imgToVid(imgPath, vidSavePath, fps):
'''This function will convert images to video'''
frames = []
files = [f for f in os.listdir(imgPath) if isfile(join(imgPath, f)) ]
for i in range(len(files)):
fileName = imgPath + files[i]
'''reading images'''
img = cv2.imread(fileName)
# height, width, layers = img.shape
# size = (width, height)
out = cv2.VideoWriter(vidSavePath, cv2.VideoWriter_fourcc(*'XVID'), fps, (1280, 720))
for j in range(len(frames)):
out.write(frames[j])
out.release()
imgPath = 'C:/Users/yash/Desktop/videocap/'
vidSavePath = 'C:/Users/yash/Desktop/testvideo.mp4'
fps = 14
imgToVid(imgPath, vidSavePath, fps)
append img in frames
frames = []
files = [f for f in os.listdir(imgPath) if isfile(join(imgPath, f)) ]
for i in range(len(files)):
fileName = imgPath + files[i]
'''reading images'''
img = cv2.imread(fileName)
frames.append(img)
I'm trying to resize & reduce quality of image before upload in project. Here's what I tried,
def save(self):
im = Image.open(self.image)
output = BytesIO()
im = im.resize(240, 240)
im.save(output, format='JPEG', quality=95)
output.seek(0)
self.image = InMemoryUploadedFile(output, 'ImageField', "%s.jpg" % self.image.name.split('.')[0], 'image/jpeg', sys.getsizeof(output), None)
super(Model, self).save()
It's working fine if I upload a jpg image but if I upload a png or any other image type, it's not working it's raising errors like cannot write mode RGBA as JPEG & cannot write mode P as JPEG etc.
How can we fix that? Thank You!
If your image.mode is "P" or "RGBA" and you want to convert it to jpeg then you need to first convert the image.mode because the previous modes aren't supported for jpeg
if im.mode in ("RGBA", "P"):
im = im.convert("RGB")
https://github.com/python-pillow/Pillow/issues/2609
Summary timop and 2:
backgroud
JPG not support alpha = transparency
RGBA, P has alpha = transparency
RGBA= Red Green Blue Alpha
result
cannot write mode RGBA as JPEG
cannot write mode P as JPEG
solution
before save to JPG, discard alpha = transparency
such as: convert Image to RGB
then save to JPG
your code
if im.mode == "JPEG":
im.save(output, format='JPEG', quality=95)
elif im.mode in ["RGBA", "P"]:
im = im.convert("RGB")
im.save(output, format='JPEG', quality=95)
More for you:
about resize & reduce quality of image, I have implement a function, for you (and others) to refer:
from PIL import Image, ImageDraw
cfgDefaultImageResample = Image.BICUBIC # Image.LANCZOS
def resizeImage(inputImage,
newSize,
resample=cfgDefaultImageResample,
outputFormat=None,
outputImageFile=None
):
"""
resize input image
resize normally means become smaller, reduce size
:param inputImage: image file object(fp) / filename / binary bytes
:param newSize: (width, height)
:param resample: PIL.Image.NEAREST, PIL.Image.BILINEAR, PIL.Image.BICUBIC, or PIL.Image.LANCZOS
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.thumbnail
:param outputFormat: PNG/JPEG/BMP/GIF/TIFF/WebP/..., more refer:
https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html
if input image is filename with suffix, can omit this -> will infer from filename suffix
:param outputImageFile: output image file filename
:return:
input image file filename: output resized image to outputImageFile
input image binary bytes: resized image binary bytes
"""
openableImage = None
if isinstance(inputImage, str):
openableImage = inputImage
elif CommonUtils.isFileObject(inputImage):
openableImage = inputImage
elif isinstance(inputImage, bytes):
inputImageLen = len(inputImage)
openableImage = io.BytesIO(inputImage)
if openableImage:
imageFile = Image.open(openableImage)
elif isinstance(inputImage, Image.Image):
imageFile = inputImage
# <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=3543x3543 at 0x1065F7A20>
imageFile.thumbnail(newSize, resample)
if outputImageFile:
# save to file
imageFile.save(outputImageFile)
imageFile.close()
else:
# save and return binary byte
imageOutput = io.BytesIO()
# imageFile.save(imageOutput)
outputImageFormat = None
if outputFormat:
outputImageFormat = outputFormat
elif imageFile.format:
outputImageFormat = imageFile.format
imageFile.save(imageOutput, outputImageFormat)
imageFile.close()
compressedImageBytes = imageOutput.getvalue()
compressedImageLen = len(compressedImageBytes)
compressRatio = float(compressedImageLen)/float(inputImageLen)
print("%s -> %s, resize ratio: %d%%" % (inputImageLen, compressedImageLen, int(compressRatio * 100)))
return compressedImageBytes
latest code can found here:
https://github.com/crifan/crifanLibPython/blob/master/crifanLib/crifanMultimedia.py
Hello to all senior programmer! I have an error on eigenfaces image training part.
The error is : OpenCV Error: Unsupported format or combination of formats (In the Eigenfaces method all input samples (training images) must be of equal size! Expected 27889 pixels, but was 27556 pixels.) in cv::face::Eigenfaces::train, file C:\projects\opencv-python\opencv_contrib\modules\face\src\eigen_faces.cpp, line 68
Which mean my pictures don't be in equal size. I try cv2.rezise() when I capture picture from camera but it still doesn't work.
here is my capture code :
import cv2
cam = cv2.VideoCapture(0)
detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
Id = input('enter your id: ')
sampleNum = 0
while(True):
ret, img = cam.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = detector.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)
sampleNum = sampleNum+1
cv2.imwrite("dataSet/user."+Id+'.'+str(sampleNum)+".jpg",cv2.resize
(gray[y:y+h,x:x+w],(70,70)))
cv2.imshow('frame',img)
if cv2.waitKey(100) & 0xFF == ord('q'):#waitKey is for delay in video capture
break
elif sampleNum >= 50:#how many picture capture?
break
cam.release()
cv2.destroyAllWindows()
and here is training part:
import cv2,os
import numpy as np
recognizer = cv2.face.EigenFaceRecognizer_create()
detector= cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
def getImagesAndLabels(path):
imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
faceSamples=[]
Ids=[]
for imagePath in imagePaths:
pilImage = Image.open(imagePath).convert('L')
imageNp = np.array(pilImage,'uint8')
Id = int(os.path.split(imagePath)[-1].split(".")[1])
faces = detector.detectMultiScale(imageNp)
for (x,y,w,h) in faces:
faceSamples.append(imageNp[y:y+h,x:x+w])
Ids.append(Id)
return faceSamples,Ids
faces,Ids = getImagesAndLabels('dataSet')
recognizer.train(faces, np.array(Ids))
recognizer.write('trainner/trainnerEi.yml')
PS. I adapt this code from LBPHFaceRecognizer
Thank you!*3
Okay, so EigenFaces only works if the dimension of all the images is same in pixel space
Which means if one image used in training is of size 28x28 then every other image in the training as well as in testing has to be of size 28x28
If the image size is not same then opencv will throw you that error
The error simply says that one of the image was of 27889 dimensions in pixel space and other was 27556 dimensions pixel space.
I would recommend you to use cv2.resize() function to make all images of the same size
Use the below code as a reference for you training part:
import cv2,os
import numpy as np
recognizer = cv2.face.EigenFaceRecognizer_create()
detector= cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
def getImagesAndLabels(path):
width_d, height_d = 280, 280 # Declare your own width and height
imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
faceSamples=[]
Ids=[]
for imagePath in imagePaths:
pilImage = Image.open(imagePath).convert('L')
imageNp = np.array(pilImage,'uint8')
Id = int(os.path.split(imagePath)[-1].split(".")[1])
faces = detector.detectMultiScale(imageNp)
for (x,y,w,h) in faces:
########################################
# The line to be changed by cv2.resize()
########################################
faceSamples.append(cv2.resize(imageNp[y:y+h,x:x+w], (width_d, height_d))
Ids.append(Id)
return faceSamples,Ids
faces,Ids = getImagesAndLabels('dataSet')
recognizer.train(faces, np.array(Ids))
recognizer.write('trainner/trainnerEi.yml')
Keep in mind even the test images has to be of same size