How should I put the dataset folder path in this python code - python

So I'm working on this sign language gesture recognition python project from git hub.
I followed the read me file and saved (in the project's root folder) all the dataset files in two seperate folders named as train_videos and test_videos for machine learning.
Now I'm getting the following error:
usage: video-to-frame.py [-h] gesture_folder target_folder
video-to-frame.py: error: the following arguments are required: gesture_folder, target_folder
Following is the code from "video-to-frame.py" file.
I can't figure out where to put the paths of my data set fodlers.
import cv2
import os
import pickle
from os.path import join, exists
import handsegment as hs
import argparse
from tqdm import tqdm
hc = []
def convert(gesture_folder, target_folder):
rootPath = os.getcwd()
majorData = os.path.abspath(target_folder)
if not exists(majorData):
os.makedirs(majorData)
gesture_folder = os.path.abspath(gesture_folder)
os.chdir(gesture_folder)
gestures = os.listdir(os.getcwd())
print("Source Directory containing gestures: %s" % gesture_folder)
print("Destination Directory containing frames: %s\n" % majorData)
for gesture in tqdm(gestures, unit='actions', ascii=True):
gesture_path = os.path.join(gesture_folder, gesture)
os.chdir(gesture_path)
gesture_frames_path = os.path.join(majorData, gesture)
if not os.path.exists(gesture_frames_path):
os.makedirs(gesture_frames_path)
videos = os.listdir(os.getcwd())
videos = [video for video in videos if(os.path.isfile(video))]
for video in tqdm(videos, unit='videos', ascii=True):
name = os.path.abspath(video)
cap = cv2.VideoCapture(name) # capturing input video
frameCount = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
lastFrame = None
os.chdir(gesture_frames_path)
count = 0
# assumption only first 200 frames are important
while count < 201:
ret, frame = cap.read() # extract frame
if ret is False:
break
framename = os.path.splitext(video)[0]
framename = framename + "_frame_" + str(count) + ".jpeg"
hc.append([join(gesture_frames_path, framename), gesture, frameCount])
if not os.path.exists(framename):
frame = hs.handsegment(frame)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
lastFrame = frame
cv2.imwrite(framename, frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
count += 1
# repeat last frame until we get 200 frames
while count < 201:
framename = os.path.splitext(video)[0]
framename = framename + "_frame_" + str(count) + ".jpeg"
hc.append([join(gesture_frames_path, framename), gesture, frameCount])
if not os.path.exists(framename):
cv2.imwrite(framename, lastFrame)
count += 1
os.chdir(gesture_path)
cap.release()
cv2.destroyAllWindows()
os.chdir(rootPath)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Extract Individual Frames from gesture videos.')
parser.add_argument('gesture_folder', help='Path to folder containing folders of videos of different gestures.')
parser.add_argument('target_folder', help='Path to folder where extracted frames should be kept.')
args = parser.parse_args()
convert(args.gesture_folder, args.target_folder)
This is the link to project's git hub repository.

So I'm relatively new to python but the snippet of code you shared is a function with inputs of gesture_folder and target_folder so with that said you will need to see where the function convert() is called in your overall code and then check what inputs are inside of the function call.
So if it looks like this then replace the paths in the function call
convert("C:\\User\gesturefolder","C:\\User\targetfolder" )
But if it looks like this
convert(gf,tf)
then you will need to work backwards and find where gf and tf are declared and replace the paths there
EDIT:
parser.add_argument('C:\\User\gesturefolder', help='Path to folder containing folders of videos of different gestures.')
parser.add_argument('C:\\User\targetfolder', help='Path to folder where extracted frames should be kept.')
If replacing this with your paths doesnt work then try replacing all backslashes with either \ or /
EDIT2:
So I looked through the Github and it appears the paths are provided when calling the python code
video-to-frame.py [-h] gesture_folder target_folder
Have you tried something like this
gesture_folder="C:\\..." #gesture folder path
target_folder="C:\\..." #target folder path
video-to-frame.py [-h] gesture_folder target_folder
EDIT3:
The last suggestion I can think of is since you are just running it the code directly and not calling it then just define the paths at the beginning of the code between the imports and hc
import cv2
import os
import pickle
from os.path import join, exists
import handsegment as hs
import argparse
from tqdm import tqdm
gesture_folder="C:\\..." #gesture folder path
target_folder="C:\\..." #target folder path
hc = []

Related

Problem with naming a camera captured file in a while-loop

This is my code, It takes a picture via webcam and saves it in a folder I specify. The name is then "day-time_0/1/2/3.jpg".
The problem is I would like to have it without "_0/1/2/3". But these numbers are necessary for the loop I think at least. But if I take out this count it saves a picture and over saves it every time I want to make another picture in the same interface.
Is there a way that if I am in the same interface and take several pictures that I can save them again and again with the new current time?
import cv2
import os
import time
timestr = time.strftime("%Y%m%d-%H%M%S")
def save_frame_camera_key(device_num, dir_path, basename, ext='jpg', delay=1, window_name='frame'):
cap = cv2.VideoCapture(device_num)
if not cap.isOpened():
return
os.makedirs(dir_path, exist_ok=True)
base_path = os.path.join(dir_path, basename)
n = 0
while True:
ret, frame = cap.read()
cv2.imshow(window_name, frame)
key = cv2.waitKey(delay) & 0xFF
if key == ord('c'):
cv2.imwrite('{}_{}.{}'.format(base_path, **n**, ext), frame)
** n += 1**
elif key == ord('q'):
break
cv2.destroyWindow(window_name)
save_frame_camera_key(0, 'data/temp', timestr)
As i said i tried deleting the count. Didnt work. Ive tried it with an different capture Code and it didnt work.

How to manipulate save name of the images

I am saving my video frames with below code but I want to add save_path to file name as well:
cv2.imwrite(f"{save_path}/{idx}.png", frame)
How could I add save_path to file name?
I need it as:
save_path/idxsavepath
since we lack the debugging info, here is a piece of code you should have written to avoid path problems. first, check that the directory is found and only then continue.
import os
import cv2
import numpy as np
def main():
# before continuing, must check if folder exists
save_dir = r'D:\pics'
valid_path = os.path.exists(save_dir)
print('is {} a valid path ? {}'.format(save_dir, valid_path))
if not valid_path:
print('folder {} does not exist - create it and try again'.format(save_dir))
else:
idx = 0
fake_frame = np.zeros(shape=(480, 640, 3))
image_full_path = '{}/{}.png'.format(save_dir, idx)
cv2.imwrite(image_full_path, fake_frame)
print('image saved successfully on {}'.format(image_full_path))
return
if __name__ == '__main__':
main()

Error creating new directories for video frames for different videos

Per title, I'm trying to write code to loop through multiple videos in a folder to extract their frames, then write each video's frames to their own new folder, e.g. video1 to frames_video1, video2 to frames_video2.
This is my code:
subclip_video_path = main_path + "\\subclips"
frames_path = main_path + "\\frames"
#loop through videos in file
for subclips in subclip_video_path:
currentVid = cv2.VideoCapture(subclips)
success, image = currentVid.read()
count = 0
while success:
#create new frames folder for each video
newFrameFolder = ("frames_" + subclips)
os.makedirs(newFrameFolder)
I get this error:
[ERROR:0] global C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-k8sx3e60\opencv\modules\videoio\src\cap.cpp (142) cv::VideoCapture::open VIDEOIO(CV_IMAGES): raised OpenCV exception:
OpenCV(4.4.0) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-k8sx3e60\opencv\modules\videoio\src\cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): P in function 'cv::icvExtractPattern'
What does this mean? How can I fix this?
You can't loop though string: for subclips in subclip_video_path:
You need to get the list of your videos:
from glob import glob
sub_clip_video_path = glob("sub_clip_video_path/*.mp4")
This means get all the .mp4 extension video files and store it in sub_clip_video_path variable.
My Result:
['sub_clip_video_path/output.mp4', 'sub_clip_video_path/result.mp4']
Since I'm sure the directory contains two .mp4 extension files, now I can continue.
You don't need to re-declare VideoCapture for each frame.
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
success, image = currentVid.read()
count = 0
After you declare VideoCapture read all the frames from the current video, then declare VideoCapture for the next video.
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
image_counter = 0
while currentVid.isOpened():
.
.
Don't use while success this will create an infinite loop.
If the first frame grabbed from the video, then the success variable returns True. When you say:
while success:
#create new frames folder for each video
newFrameFolder = ("frames_" + subclips)
os.makedirs(newFrameFolder)
You will create infinite amount of folder for the current frame.
Here my result:
import os
import cv2
from glob import glob
sub_clip_video_path = glob("sub_clip_video_path/*.mp4") # Each image extension is `.mp4`
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
image_counter = 0
while currentVid.isOpened():
success, image = currentVid.read()
if success:
newFrameFolder = "frames_video{}".format(count + 1)
if not os.path.exists(newFrameFolder):
os.makedirs(newFrameFolder)
image_name = os.path.join(newFrameFolder, "frame{}.png".format(image_counter + 1))
cv2.imwrite(image_name, image)
image_counter += 1
else:
break
I gathered all the videos using glob
While the current video is being read:
for count, sub_clips in enumerate(sub_clip_video_path):
currentVid = cv2.VideoCapture(sub_clips)
image_counter = 0
while currentVid.isOpened():
If the current frame successfully grabbed, then declare folder name. If the folder does not exist, create it.
if success:
newFrameFolder = "frames_video{}".format(count + 1)
if not os.path.exists(newFrameFolder):
os.makedirs(newFrameFolder)
Then declare the image name and save it.
image_name = os.path.join(newFrameFolder, "frame{}.png".format(image_counter + 1))
cv2.imwrite(image_name, image)
image_counter += 1

How to create a folder in python?

I am running a code in python where I get images from input file, and create another folder as output and a file csv. The code that I run is as below:
# import the necessary packages
from PIL import Image
import argparse
import random
import shutil
import glob2
import uuid
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", required = True,
help = "input directory of images")
ap.add_argument("-o", "--output", required = True,
help = "output directory")
ap.add_argument("-c", "--csv", required = True,
help = "path to CSV file for image counts")
args = vars(ap.parse_args())
# open the output file for writing
output = open(args["csv"], "w")
# loop over the input images
for imagePath in glob2.iglob(args["input"] + "/*/*.jpg"):
# generate a random filename for the image and copy it to
# the output location
filename = str(uuid.uuid4()) + ".jpg"
shutil.copy(imagePath, args["output"] + "/" + filename)
# there is a 1 in 500 chance that multiple copies of this
# image will be used
if random.randint(0, 500) == 0:
# initialize the number of times the image is being
# duplicated and write it to the output CSV file
numTimes = random.randint(1, 8)
output.write("%s,%d\n" % (filename, numTimes))
# loop over a random number of times for this image to
# be duplicated
for i in range(0, numTimes):
image = Image.open(imagePath)
# randomly resize the image, perserving aspect ratio
factor = random.uniform(0.95, 1.05)
width = int(image.size[0] * factor)
ratio = width / float(image.size[0])
height = int(image.size[1] * ratio)
image = image.resize((width, height), Image.ANTIALIAS)
# generate a random filename for the image and copy
# it to the output directory
adjFilename = str(uuid.uuid4()) + ".jpg"
shutil.copy(imagePath, args["output"] + "/" + adjFilename)
# close the output file
output.close()
After running the code I get only csv file, but I don't get output folder.
The way I run the code is:
python gather.py --input 101_ObjectCategories --output images --csv output.csv
Please can you help me how to solve the problem, because I need the output folder for next steps, running next functions.
I would recommend the following approach:
import os
from pathlib import Path
Path('path').mkdir(parents=True, exist_ok=True)
This works cross-platform and doesn't overwrite the directories if they already exist.
You should try the os module. It has a mkdir method that creates a directory based on the path you give it as a parameter.
import os
os.mkdir("path")
While most answers suggest using os.mkdir() I suggest you rather go for os.makedirs() which would recursively create all the missing folders in your path, which usually is more convinient.
import os
os.makedirs('foo/bar')
Docs: https://docs.python.org/3/library/os.html#os.makedirs

How do I extract the frames from a folder of mp4 videos and transfer them to another folder?

I have a folder full of mp4 clips (over 200). I want to take all those clips, extract their frames and send them to another folder to store all the frames in. This is what I have so far (part of the code) but it's only working when I have one mp4 file in the same folder:
import cv2 # for capturing videos
import math # for mathematical operations
import matplotlib.pyplot as plt # for plotting the images
import pandas as pd
from keras.preprocessing import image # for preprocessing the images
import numpy as np # for mathematical operations
from keras.utils import np_utils
from skimage.transform import resize # for resizing images
count = 0
videoFile = "sample_vid.mp4"
cap = cv2.VideoCapture(videoFile) # capturing the video from the given path
frameRate = cap.get(5) #frame rate
x=1
while(cap.isOpened()):
frameId = cap.get(1) #current frame number
ret, frame = cap.read()
if (ret != True):
break
if (frameId % math.floor(frameRate) == 0):
filename ="frame%d.jpg" % count;count+=1
cv2.imwrite(filename, frame)
cap.release()
print ("Done!")
Again, i'm having some trouble dealing with the file directories in python and looping it so that it goes through all the files in another folder and send the frames extracted into another folder.
Use glob lib to find all mp4 files in your folder. Then run video2frames method against all videos.
import cv2
import math
import glob
def video2frames(video_file_path):
count = 0
cap = cv2.VideoCapture(video_file_path)
frame_rate = cap.get(5)
while cap.isOpened():
frame_id = cap.get(1)
ret, frame = cap.read()
if not ret:
break
if frame_id % math.floor(frame_rate) == 0:
filename = '{}_frame_{}.jpg'.format(video_file_path, count)
count += 1
cv2.imwrite(filename, frame)
cap.release()
videos = glob.glob('/home/adam/*.mp4')
for i, video in enumerate(videos):
print('{}/{} - {}'.format(i+1, len(videos), video))
video2frames(video)
Tested on two videos. Here is what I've got:
You can use os.walk to fetch all mp4 names and iterate over them. There are other ways detailed in Find all files in a directory with extension .txt in Python (replace txt with mp4).
Create some files to find:
import os
with open("tata.mp4","w") as f: f.write(" ")
with open("tata1.mp4","w") as f: f.write(" ")
with open("tata2.mp4","w") as f: f.write(" ")
os.makedirs("./1/2/3")
with open("./1/subtata.mp4","w") as f: f.write(" ")
with open("./1/2/subtata1.mp4","w") as f: f.write(" ")
with open("./1/2/3/subtata2.mp4","w") as f: f.write(" ")
Find files:
startdir = "./"
all_files = []
for root,dirs,files in os.walk(startdir):
for file in files:
if file.endswith(".mp4"):
all_files.append(os.path.join(root,file))
print(all_files)
for f in all_files:
# do your thing
Output:
['./tata2.mp4', './tata1.mp4', './tata.mp4',
'./1/subtata.mp4',
'./1/2/subtata1.mp4',
'./1/2/3/subtata2.mp4']

Categories