Sequence of images to video in OpenCV + range of reading - python

Already fighting with this problem for a whole day, maybe anyone can help? Have a basic knowledge at Mathlab, python and openCV
I am use python for make a video from images. And, as usually, found a problem with it. There is no sequence in reading image's for writing video. For example i have img_01,img_02,.....img_n. Each img - frame of video. And at final video it's looks like:
./img_155.jpg
./img_476.jpg
./img_282.jpg
and etc.
So, it's totally chaotic at the final video, as result...
Is anyone can help, please, with this problem? I found a lot of hints, but all of them with c++ only. There is code, what i am using now:
import cv2
import argparse
import os
# Construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-ext", "--extension", required=False, default='jpg', help="extension name. default is 'png'.")
ap.add_argument("-o", "--output", required=False, default='output.mp4', help="output video file")
args = vars(ap.parse_args())
# Arguments
dir_path = '.'
ext = args['extension']
output = args['output']
images = []
for f in os.listdir(dir_path):
if f.endswith(ext):
images.append(f)
# Determine the width and height from the first image
image_path = os.path.join(dir_path, images[0])
frame = cv2.imread(image_path)
cv2.imshow('video',frame)
height, width, channels = frame.shape
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # Be sure to use lower case
out = cv2.VideoWriter(output, fourcc, 30.0, (width, height))
for image in images:
image_path = os.path.join(dir_path, image)
frame = cv2.imread(image_path)
out.write(frame) # Write out frame to video
cv2.imshow('video',frame)
if (cv2.waitKey(1) & 0xFF) == ord('q'): # Hit `q` to exit
break
# Release everything if job is finished
out.release()
cv2.destroyAllWindows()
print("The output video is {}".format(output))

I think your problem is : for f in os.listdir(dir_path): return file name in random sequence.
You should add follow line before '# Determine the width and height from the first image'
def name2num(name):
m = re.search('img_(\d+)\.?.*', name)
return int(m.group(1),10)
images.sort(key=name2num)

Related

video to images then images to video in python

I'm trying to convert the following video to images
https://www.signingsavvy.com/media/mp4-ld/24/24851.mp4
however, I have done it by using OpenCV
# Importing all necessary libraries
import cv2
import os
# Read the video from specified path
cam = cv2.VideoCapture("C:\Users\ahmad\Hi_ASL.mp4")
print(cam.get(cv2.CAP_PROP_FPS))
try:
# creating a folder named data
if not os.path.exists('data'):
os.makedirs('data')
# if not created then raise error
except OSError:
print ('Error: Creating directory of data')
# frame
currentframe = 0
while(True):
# reading from frame
ret,frame = cam.read()
if ret:
# if video is still left continue creating images
name = './data/frame' + str(currentframe) + '.jpg'
# print ('Creating...' + name)
# writing the extracted images
cv2.imwrite(name, frame)
# increasing counter so that it will
# show how many frames are created
currentframe += 1
else:
break
# ret,frame = cam.read()
# Release all space and windows once done
cam.release()
cv2.destroyAllWindows()
After I have done it. I want to convert those images to video to be like the one above and I wrote this code
img = [img for img in os.listdir('data')]
frame = cv2.imread('data\' + img[0])
h , w , l = frame.shape
vid = cv2.VideoWriter('hiV.mp4' , 0 ,1 ,(w,h))
for imgg in img:
vid.write(cv2.imread('data\' + imgg))
cv2.destroyAllWindows()
vid.release()
The problem is the result of combining the images to a video using OpenCV is not the same as the original video. So, what is the problem? I want it to be the same as the original one.
The result of the code above is this video https://drive.google.com/file/d/16vwT35wzc95tBleK5VCpZJQkaLxSiKVd/view?usp=sharing
And thanks.
You should change cv2.VideoWriter('hiV.mp4' , 0 ,1 ,(w,h)) to cv2.VideoWriter('hiV.mp4' , 0 ,30 ,(w,h)) As the 1 sets the fps and that means that you write 1 frame every second and not 30 or 29.97(NTSC) as the original video.

Trying to encrypt video frames with RSA; getting garbage instead of original data after decrypting

I am writing a script to encrypt and decrypt video using RSA algo in python. Now I have extracted the frames from the video and encrypt each image individually and then combining the images to create a video. Then I am reading the frames of the encrypted video again and when I am applying the decryption key I am not getting back the original image. But when I am applying the same key on any image with which the video is made I am getting back the original image. let us say we have image1 which is encrypted and will be used to make the encrypted video when I am applying the key on this image I am getting back the original image. now I have image2 which is read from the encrypted video and if the keys are applied then it is giving a more encrypted image. Heres the code :
import cv2
import numpy
import os
import imageio
import time
from tkinter.filedialog import askopenfilename
from tkinter.ttk import *
from tkinter import *
from tkinter import filedialog
from tqdm import tqdm
from tkinter import messagebox
import subprocess
def load_image_decrypt(folder):
videofile = 'envid.avi'
try:
if not os.path.exists('Dedata'):
os.makedirs('Dedata')
except OSError:
messagebox.showinfo('Error Occured', 'Error: Creating directory of decrypted data')
vid_to_image(videofile)
for filename1 in tqdm(os.listdir(folder)):
imgV = imageio.imread(os.path.join(folder, filename1), format='PNG-FI')
if imgV is not None:
RGBdecryption(imgV, filename1)
else:
break
vidname = 'devid.avi'
image_to_vid(dedata2, vidname)
messagebox.showinfo('Finish!', 'Decryption Done succesfully!')
def RGBdecryption(img, filename):
img1 = img
img = img.astype(numpy.uint16)
img1= img1.tolist()
for i1 in tqdm(range(len(img1))):
for j1 in (range(len(img1[i1]))):
for k1 in (range(len(img1[i1][j1]))):
x1 = img1[i1][j1][k1]
x1 = pow(x1,16971,25777)
img1[i1][j1][k1] = x1
img1 = numpy.array(img1).astype(numpy.uint16)
name = './Dedata/'+str(filename)
imageio.imwrite(name, img1, format='PNG-FI')
def vid_to_image(filename):
# Playing video from file:
cap = cv2.VideoCapture(filename)
try:
if not os.path.exists('data'):
os.makedirs('data')
messagebox.showinfo('Info!', 'Data directory is created where the frames are stored')
except OSError:
print ('Error: Creating directory of data')
currentFrame = 0
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
if not ret:
break
# Saves image of the current frame in jpg file
name = './data/frame' + str(currentFrame) + '.png'
print ('Creating...' + name)
imageio.imwrite(name, frame,format='PNG-FI')
# To stop duplicate images
currentFrame += 1
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
def image_to_vid(folder, vidname): #the code which is creating a video out of images stored in the folder
image_folder = folder
video_name = vidname
sort_image = []
images = [img for img in os.listdir(image_folder) if img.endswith(".png")]
print(images)
print('\n\n')
for i in range(0,1000):
for j in range(len(images)):
name = 'frame' + str(i) + '.png'
if ((str(images[j])) == str(name)):
sort_image.append(images[j])
print(sort_image)
frame = cv2.imread(os.path.join(image_folder, sort_image[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 29, (width,height)) #29 is the fs of the original video and I don't know what the 0 is for
for image in sort_image:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
data = './data'
load_image_decrypt(data)
I do not know where I am getting it wrong. I am new to opencv and video processing. Any help will be appreciated. Thank you.
Video frames are subject to lossy compression. So you cannot feed a codec some binary data under the guise of images, encode it and expect to get exactly the same binary data back when playing the resulting video.
Your best bet is to encrypt the video file as a whole as per Encryption of video files? or How can I Encrypt Video in Real Time?. It will need to be decrypted to be playable; this is apparently what OSX's "content protection" does, encrypting and decrypting data transparently.
A (paywalled) IEEE article Video Encryption Based on OpenCV - IEEE Conference Publication says they applied an Arnold Transform to image data. It is a transposition cipher and as such, can be broken. Its main strength seems to rather be that it makes content unintelligible in regular playback, and it preserves image characteristics critical for video codecs (lighting, frame differences) and doesn't require the exact ciphertext for decryption, so it's not damaged beyond repair by the lossy compression.

OpenCV 3 VideoWriter Inserting an Extra Frames

I'm trying to write a video in OpenCV3 (Python 3.6). I found this code posted somewhere. The code works but when I play the video, it seems that every few seconds seconds or so it inserts the wrong frame. It looks like it's the first frame of the sequence. Here is how the video looks. (Link to video in case the embed code doesn't run)
<iframe width="560" height="315" src="https://www.youtube.com/embed/J3HKaQlzS8Y" frameborder="0" gesture="media" allowfullscreen></iframe>
Here is the code i'm using on my Windows 10 (64bit)
#!/usr/local/bin/python3
import cv2
import argparse
import os
# Construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-ext", "--extension", required=False, default='jpg',
help="extension name. default is 'jpg'.")
ap.add_argument("-o", "--output", required=False, default='output.mp4',
help="output video file")
args = vars(ap.parse_args())
# Arguments
dir_path = '.'
ext = args['extension']
output = args['output']
images = []
for f in os.listdir(dir_path):
if f.endswith(ext):
images.append(f)
# Determine the width and height from the first image
image_path = os.path.join(dir_path, images[0])
frame = cv2.imread(image_path)
cv2.imshow('video',frame)
height, width, channels = frame.shape
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # Be sure to use lower case
out = cv2.VideoWriter(output, fourcc, 20.0, (width, height))
for image in images:
image_path = os.path.join(dir_path, image)
frame = cv2.imread(image_path)
out.write(frame) # Write out frame to video
cv2.imshow('video',frame)
if (cv2.waitKey(1) & 0xFF) == ord('q'): # Hit `q` to exit
break
# Release everything if job is finished
out.release()
cv2.destroyAllWindows()
print("The output video is {}".format(output))
Any pointers would be apprecited
In your code, after this code:
images = []
for f in os.listdir(dir_path):
if f.endswith(ext):
images.append(f)
just add:
images = sorted(images, key=lambda x: (int(re.sub('\D','',x)),x))
so that we will get a sorted data. Hence the video frames will be all set in there positions. Don't forget to import re as header file.

object(car) detection in opencv python

I am working on one of my college project i.e object(car) detection in opencv python ,i am using opencv 3 and python 3.4. I have a code for it but when i run the code the output is not displayed. It shows that the code is error free but still unable to get the output. I am new to image processing ,so it will be a great help if someone tries to sort out my problem. The code is given below`
import cv2
import numpy as np
import argparse
ap = argparse.ArgumentParser()
ap.add_agrument("-v","--video",
help = "path to the (optional) video file")
args = vars(ap.parse_agrs())
camera = cv2.VideoCapture(agrs["video"])
car_cascade = cv2.CascadeClassifier("cars.xml")
while true:
ret,frames = camera.read(),cv2.rectangle()
gray = cv2.cvtColor(frames, cv2.COLOR_BGR2GRAY)
cars = car_cascade.detectionMultiScale(gray, 1.1,1)
for (x,y,w,h) in cars:
cv2.rectangular()frames,(x,y),(x+w,y+h), (0,0,255),2)
cv2.imshow ('video',frames)
cv2.waitkey(0)
I just remove the argparse command and edited the code little bit and it is working quit well.To see the output click here : https://www.youtube.com/watch?v=phG9inHoAKg
And the code files are uploaded to my github account https://github.com/Juzer2012/Car-detection
You write: "It shows that the code is error free" ...
It isn't (and this multiple times) as for example here:
ap.add_agrument(...
where it should be
ap.add_argument(...
Just check again for more of such syntax errors. Happy coding :) .
Here the by you requested code example which uses argparse for image processing - it works both with python2.x and python3.x showing a video stream for processing in a for this purpose opened window. If you can see the video stream output, just mark this as a valid answer to your question. Thanks in advance (y). Happy coding :) .
import cv2
def showVideoStream_fromWebCam(argsVideo, webCamID=0, showVideoStream=True):
cv2_VideoCaptureObj_webCam = cv2.VideoCapture(webCamID)
while True:
retVal, imshowImgObj = cv2_VideoCaptureObj_webCam.read()
if showVideoStream:
imshowImgObj = cv2.flip(imshowImgObj, 1)
cv2.imshow('webCamVideoStream', imshowImgObj)
#:if
if cv2.waitKey(1) == 27:
break # [Esc] to quit
#:if
#:while
cv2.destroyAllWindows()
#:def
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-v","--video", help = "webCamID (= 0)")
args = vars(ap.parse_args())
showVideoStream_fromWebCam(args["video"])
Let's make the code even a bit more perfect by running the video at approximately it's original speed (25 frames/second), taking out what is not necessary and drawing all the rectangles first, then showing the frame:
import cv2
camera = cv2.VideoCapture("video.avi")
car_cascade = cv2.CascadeClassifier('cars.xml')
# Get frames per second from video file. Syntax depends on OpenCV version:
(major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')
if int(major_ver) < 3 :
fps = camera.get(cv2.cv.CV_CAP_PROP_FPS)
else :
fps = camera.get(cv2.CAP_PROP_FPS)
#:if
intTimeToNextFrame=int(1000.0/fps)-12 # '-12' estimation of time for processing
while True:
(grabbed,frame) = camera.read()
grayvideo = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cars = car_cascade.detectMultiScale(grayvideo, 1.1, 1)
for (x,y,w,h) in cars:
cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,255),1)
cv2.imshow("video",frame)
if cv2.waitKey(intTimeToNextFrame)== ord('q'):
break
camera.release()
cv2.destroyAllWindows()

OpenCV - Save video segments based on certion condition

Aim : Detect the motion and save only the motion periods in files with names of the starting time.
Now I met the issue about how to save the video to the files with video starting time.
What I tested :
I tested my program part by part. It seems that each part works well except the saving part.
Running status: No error. But in the saving folder, there is no video. If I use a static saving path instead, the video will be saved successfully, but the video will be override by the next video. My codes are below:
import cv2
import numpy as np
import time
cap = cv2.VideoCapture( 0 )
bgst = cv2.createBackgroundSubtractorMOG2()
fourcc=cv2.VideoWriter_fourcc(*'DIVX')
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
n = "start_time"
while True:
ret, frame = cap.read()
dst = bgst.apply(frame)
dst = np.array(dst, np.int8)
if np.count_nonzero(dst)>3000: # use this value to adjust the "Sensitivity“
print('something is moving %s' %(time.ctime()))
path = r'E:\OpenCV\Motion_Detection\%s.avi' %n
out = cv2.VideoWriter( path, fourcc, 50, size )
out.write(frame)
key = cv2.waitKey(3)
if key == 32:
break
else:
out.release()
n = time.ctime()
print("No motion Detected %s" %n)
What I meant is:
import cv2
import numpy as np
import time
cap = cv2.VideoCapture( 0 )
bgst = cv2.createBackgroundSubtractorMOG2()
fourcc=cv2.VideoWriter_fourcc(*'DIVX')
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
path = r'E:\OpenCV\Motion_Detection\%s.avi' %(time.ctime())
out = cv2.VideoWriter( path, fourcc, 16, size )
while True:
ret, frame = cap.read()
dst = bgst.apply(frame)
dst = np.array(dst, np.int8)
for i in range(number of frames in the video):
if np.count_nonzero(dst)<3000: # use this value to adjust the "Sensitivity“
print("No Motion Detected")
out.release()
else:
print('something is moving %s' %(time.ctime()))
#label each frame you want to output here
out.write(frame(i))
key = cv2.waitKey(1)
if key == 32:
break
cap.release()
cv2.destroyAllWindows()
If you see the code there will be a for loop, within which the process of saving is done.
I do not know the exact syntax involving for loop with frames, but I hope you have the gist of it. You have to find the number of frames present in the video and set that as the range in the for loop.
Each frame gets saved uniquely (see the else condition.) As I said I do not know the syntax. Please refer and follow this procedure.
Cheers!

Categories

Resources