OpenCV - Not able to write images to video files - python

I have such a loop to write video files from images:
for a in range(len(events)):
c_videos = []
first = events[a][0]
last = events[a][1]
c_videos = video_ids[numpy.where(numpy.logical_and(timestamps >= first, timestamps <= last))]
video_name = "/export/students/sait/9-may-video-dataset/video-" + str(events[a][2]) + ".avi"
video = cv2.VideoWriter(video_name,-1,1,(width,height))
for b in range(len(c_videos)):
img_file = "/export/students/sait/9-may-results/rgb-" + str(c_videos[b]) + ".ppm"
img = cv2.imread(img_file)
video.write(img)
cv2.destroyAllWindows()
video.release()
But I cannot become successful in creating videos. I don't see any created video file under the destination directory.
How can I fix this problem?

Related

Video created in OpenCv does open, but shows nothing

I've been trying to merge some pictures to create a video, all of this using Opencv. But, the problem here is that Opencv does create the .avi file and it opens, using VLC Media Player, but when I'm trying to watch the video created, it shows nothing and doesn't show how long does the video last. However, the file size is around 6kb. There are 18 images and they have an average size os 252kb. I think that's too weird and incoherent.
Here's a look at my code:
import cv2
import os
frameSize = (500, 500)
with os.scandir('Taylor') as Taylor_Images:
for image in Taylor_Images:
print(image.name)
with os.scandir('Taylor_5') as Taylor5_Images:
for image in Taylor5_Images:
print(image.name)
image_Taylor = []
image_Taylor_5 = []
ext_2 = '.png'
adding = '_5'
path_2 = 'Taylor_5/'
ext = '.png'
path = 'Taylor/'
for i in range(1,10):
img_name = str(i) + ext
img = path + str(i) + ext
image_Taylor.append(img)
img_name_2 = str(i) + ext_2
img_2 = path_2 + str(i) + adding + ext_2
image_Taylor_5.append(img_2)
out = cv2.VideoWriter('output_video2.avi',cv2.VideoWriter_fourcc(*'DIVX'), 60, frameSize)
for i in range(0,9):
img = cv2.imread(image_Taylor[i])
out.write(img)
img_2 = cv2.imread(image_Taylor_5[i])
out.write(img_2)
out.release()
Update 1
As Vatsal suggested, I checked all the sizes of the images and I found that some of them didn't have the same size(Width,Height), so I resized them for having the same size(400,800).
With regard to what Tim said, the images do have that file size, I attach a picture of what I did according to your suggestion of making their file size a multiple of 4.
Checking the size of the images
This is the kind of pictures I'm using
However, the video generated from the script still has a size of 6kB.

Extract frames from video into specific folder

I want to extract frames from 3 videos into 3 different folder. Each folder has the frames of their corresponding video file. I am able to access my objective for only the 3rd video. How can I extract the frames for the first 2 videos as well
I have made the folders having names as per the video files till now. Developed the code for frame extraction but can extract only from the last video. Below is my code
import cv2
import glob
from glob import glob
import os
import shutil
def extractFrames(m,n):
if not os.path.exists:
os.makedirs(n)
vid_files=glob(m)
print(vid_files)
for v_f in range(len(vid_files)):
v1=os.path.basename(vid_files[v_f])
print(v1)
vid_name = os.path.splitext(v1)[0]
print(vid_name)
output = n +'\\video_' + vid_name
os.makedirs(output)
print(output)
vidcap = cv2.VideoCapture(vid_files[v_f])
print(vidcap)
success,image = vidcap.read()
seconds = 2
fps = vidcap.get(cv2.CAP_PROP_FPS) # Gets the frames per second
multiplier = fps * seconds
count=0
while success:
img_name = vid_name + '_f' + str(count) + ".jpg"
image_path = output + "/" + img_name
frameId = int(round(vidcap.get(1)))
success,image = vidcap.read()
if frameId % multiplier == 0:
cv2.imwrite(filename = image_path, img = image)
count+=1
vidcap.release()
cv2.destroyAllWindows()
print('finished processing video {0} with frames {1}'.format(vid_files[v_f], count))
return output
x=("C:\\Python36\\videos\\*.mp4")
y=("C:\\Python36\\videos\\videos_new")
z=extractFrames(x,y)
If there are 3 videos namely video1,video2,video3. I want to extract the corresponding frames into their specific folders i.e video1 folder,video2 folder, video3 folder. Currently I am able to extract the frames for only the 3rd video into folder video3. How can I do it for video1 and video2 as well
Your indentation on the part from vidcap = ... down is off. Therefor only the last file in the for-loop is used.
import cv2
import glob
from glob import glob
import os
import shutil
def extractFrames(m,n):
if not os.path.exists:
os.makedirs(n)
vid_files=glob(m)
print(vid_files)
for v_f in range(len(vid_files)):
v1=os.path.basename(vid_files[v_f])
print(v1)
vid_name = os.path.splitext(v1)[0]
print(vid_name)
output = n +'\\video_' + vid_name
os.makedirs(output)
print(output)
vidcap = cv2.VideoCapture(vid_files[v_f])
print(vidcap)
success,image = vidcap.read()
seconds = 2
fps = vidcap.get(cv2.CAP_PROP_FPS) # Gets the frames per second
multiplier = fps * seconds
count=0
while success:
img_name = vid_name + '_f' + str(count) + ".jpg"
image_path = output + "/" + img_name
frameId = int(round(vidcap.get(1)))
success,image = vidcap.read()
if frameId % multiplier == 0:
cv2.imwrite(filename = image_path, img = image)
count+=1
vidcap.release()
cv2.destroyAllWindows()
print('finished processing video {0} with frames {1}'.format(vid_files[v_f], count))
return output # indent this less
x=("C:\\Python36\\videos\\*.mp4")
y=("C:\\Python36\\videos\\videos_new")
z=extractFrames(x,y)

OpenCV Python VideoWriter wrong fps rate for some codecs

I'm trying to read Videos, resize them and write them with a different codec, using OpenCV for Python3. The original frame rate should stay the same.
This works fine if I'm using MJPG as codec, but for other codecs the frame rate of the output is set to 600 fps. (I tried XVID, DIVX, WMV1, WMV2)
Is it possible to write Videos with those codecs with the original frame rate?
import os
import numpy as np
import cv2
codec = 'XVID'
new_size = (256, 256)
for root, dirs, files in os.walk("UCF-101"):
new_root = root.replace('UCF-101', 'UCF-101_resized_' + codec)
if not os.path.exists(new_root):
os.makedirs(new_root)
for file in files:
cap = cv2.VideoCapture(root + '/' + file)
fps = cap.get(cv2.CAP_PROP_FPS)
fourcc = cv2.VideoWriter_fourcc(*codec)
out = cv2.VideoWriter(new_root + '/' + file, fourcc, fps, new_size, isColor=True)
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
frame = cv2.resize(src=frame, dst=frame, dsize=new_size)
out.write(frame)
else:
break
cap.release()
out.release()
print('wrote ' + new_root + '/' + file)
Try changing your file extension to output file name with .mp4, not avi
codec = 'x264'
Replace if ret == True: with if frame is not None:

Difficulty in writing crops of images using OpenCV and Python

I am using the following code to read multiple images from a folder and to take a specific crop from all of them and also write them at the end. The cropping part does not seem to work meaning the cropped parts are not getting written.
# import the necessary packages
import cv2
import os, os.path
#image path and valid extensions
imageDir = "C:\\Users\\Sayak\\Desktop\\Training\\eye\\1" #specify your path here
image_path_list = []
valid_image_extensions = [".jpg", ".jpeg", ".png", ".tif", ".tiff"] #specify your vald extensions here
valid_image_extensions = [item.lower() for item in valid_image_extensions]
#create a list all files in directory and
#append files with a vaild extention to image_path_list
for file in os.listdir(imageDir):
extension = os.path.splitext(file)[1]
if extension.lower() not in valid_image_extensions:
continue
image_path_list.append(os.path.join(imageDir, file))
#loop through image_path_list to open each image
for imagePath in image_path_list:
image = cv2.imread(imagePath)
# display the image on screen with imshow()
# after checking that it loaded
if image is not None:
cv2.imshow(imagePath, image)
elif image is None:
print ("Error loading: " + imagePath)
#end this loop iteration and move on to next image
continue
crop_img = image[200:400, 100:300]
cv2.imwrite('pic{:>05}.jpg'.format(imagePath), crop_img)
# wait time in milliseconds
# this is required to show the image
# 0 = wait indefinitely
# exit when escape key is pressed
key = cv2.waitKey(0)
if key == 27: # escape
break
# close any open windows
cv2.destroyAllWindows()
I have modified your code posted above. The problem lies with your string formatting used in cv2.imwrite(). The first argument must be an absolute path to where the file should be saved, but your code is passing in something like this.
pic{:>05}.jpg => pic/home/ubuntu/Downloads/10_page.png.jpg. When I used a valid file name there is no problem saving the cropped image at all.
#loop through image_path_list to open each image
for i,imagePath in enumerate(image_path_list):
image = cv2.imread(imagePath)
# display the image on screen with imshow()
# after checking that it loaded
if image is not None:
cv2.imshow(imagePath, image)
elif image is None:
print ("Error loading: " + imagePath)
#end this loop iteration and move on to next image
continue
# Please check if the size of original image is larger than the pixels you are trying to crop.
(height, width, channels) = image.shape
if height >= 400 and width >= 300:
plt.imshow(image)
plt.title('Original')
plt.show()
crop_img = image[100:400, 100:400]
# Problem lies with this path. Ambiguous like pic/home/ubuntu/Downloads/10_page.png.jpg
print('pic{:>05}.jpg'.format(imagePath))
# Try a proper path. A dirname + file_name.extension as below, you will have no problem saving.
new_image = os.path.join(imageDir,'{}.png'.format(str(i)))
cv2.imwrite(new_image, crop_img)
plt.imshow(crop_img)
plt.title('Cropped')
plt.show()

upload PIL image to azure blob

I have a Django app that allows users to upload images that are saved in Azure blob storage. When a user uploads an image, I want to both store the original image and create a thumbnail (100x100).
Currently, the site uploads the original from request.FILES perfectly, but for creating the thumbnail I can't figure out how to upload to Azure without first saving the edited image to a holding folder, reading that saved image, and then deleting it. That doesn't seem like the most efficient way to save a thumbnail.
Here is the current upload script:
# original upload
f = request.FILES['pic']
extension = f.name.split('.')[-1]
new_name, thumb_name = rename_file(extension)
upload(blob_service, 'pic-container', new_name, f)
# create thumbnail
f.seek(0)
im = Image.open(f)
width = im.size[0]
height = im.size[1]
if width > height:
left_crop = (width - height)/2
right_crop = (width + height)/2
cropped = im.crop((left_crop, 0, right_crop, height))
else:
upper_crop = (height - width)/2
lower_crop = (height + width)/2
cropped = im.crop((0, upper_crop, width, lower_crop))
std_size = 100, 100
cropped.thumbnail(std_size, Image.ANTIALIAS)
# save to holder, upload thumbnail, then delete from holder
cropped.save('path/to/holder/' + thumb_name)
upload(blob_service, 'media-pic', thumb_name, open('path/to/holder/' + thumb_name))
os.unlink('path/to/holder/' + thumb_name)
# upload script slightly modified from http://www.windowsazure.com/en-us/documentation/articles/storage-python-how-to-use-blob-storage/#_large-blobs
def upload(blob_service, container_name, blob_name, file_path):
blob_service.put_blob(container_name, blob_name, '', 'BlockBlob')
block_ids = []
index = 0
with file_path as f:
while True:
data = f.read(chunk_size)
if data:
length = len(data)
block_id = base64.b64encode(str(index))
blob_service.put_block(container_name, blob_name, data, block_id)
block_ids.append(block_id)
index += 1
else:
break
blob_service.put_block_list(container_name, blob_name, block_ids)
If I don't save the thumbnail first and just run upload(blob_service, 'pic-container', thumb_name, cropped) I get a pretty uninformative error that just says __exit__ and points to the line with file_path as f in def upload.
Is there any way to upload the file directly from cropped without having to save the file, either by revising the upload function or by changing cropped somehow.

Categories

Resources