Displaying a Text from a Video but avoiding the same text - python

i am trying to do a program where it detects the video and capture every 100th frame then display the output. the problem that i faced here is that there will be duplication for example, the current pattern for the output is (1,1,1,2,2,3,3,2,1) but the result that i want to show is (1,2,3,2,1). To sum up, not displaying the same text continuously but allowed to be displayed when the previous image is different with the current ones. I have tried coming up with an idea of removing duplicate images but it will not give the expected result as it will delete all the images.
from PIL import Image
import pytesseract
from wand.image import Image as Img
import nltk
from nltk.tokenize import word_tokenize
from nltk.tag import pos_tag
import numpy as np
import os
import cv2
image_frames = 'image_frames'
def files():
#auto create image frames file
try:
os.remove(image_frames)
except OSError:
pass
if not os.path.exists(image_frames):
os.makedirs(image_frames)
# specify the source video path
src_vid = cv2.VideoCapture('15sec.mp4')
return(src_vid)
def process(src_vid):
# Use an index to integer-name the files
index = 0
while (src_vid.isOpened()):
ret, frame = src_vid.read()
if not ret:
break
# name each frame and save as png / jpeg
name = './image_frames/frame' + str(index) + '.jpeg'
if index % 100 == 0:
print('Extracting frames...' + name)
cv2.imwrite(name, frame)
index = index + 1
if cv2.waitKey(10) & 0xFF == ord('q'):
break
src_vid.release()
cv2.destroyAllWindows()
# do image to text on each png
def get_text():
for i in os.listdir(image_frames):
print(str(i))
my_image = Image.open(image_frames + "/" + i)
pytesseract.pytesseract.tesseract_cmd = r'C:\Users\USERS\AppData\Local\Tesseract-OCR\tesseract.exe'
text = pytesseract.image_to_string(my_image, lang='eng')
print(text)
# main driver
if __name__ == '__main__':
vid = files()
process(vid)
get_text()

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 could I pass my file name through this method?

I am taking a screenshot, and then I need to reference the shot I just took so I can translate what's inside it.
When I directly pass a file location, e.g "filex.png", to readtext, it works, but I just need it to pass the written file into it.
import easyocr
import pyautogui
import time
import cv2
import numpy as np
reader = easyocr.Reader(['en'])
tag = 1
for i in range(2):
time.sleep(4)
image = pyautogui.screenshot(region=(630,400,650,130))
image = cv2.cvtColor(np.array(image),
cv2.COLOR_RGB2BGR)
tag+=1
img = cv2.imwrite(f"image{tag}.png", image)
results = reader.readtext(img)
text=""
for result in results:
text += result[1] + " "
print(text)
In answer to your specific question, I think you're looking for something like:
import easyocr
import pyautogui
import time
import cv2
import numpy as np
reader = easyocr.Reader(['en'])
tag = 1
for i in range(2):
time.sleep(4)
image = pyautogui.screenshot(region=(630, 400, 650, 130))
image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
tag += 1
f_name = f"image{tag}.png"
cv2.imwrite(f_name, image)
results = reader.readtext(f_name)
text = ""
for result in results:
text += result[1] + " "
print(text)
You can just store your file name in a variable in pass it to both imwrite and readtext
There are other options as well, depending on what information you need access to within the program, and how quickly you need to process your data.
Option: Pass the np.array directly to readtext
image = pyautogui.screenshot(region=(630, 400, 650, 130))
image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
results = reader.readtext(image)
Option: Pass the data from the written file to the readtext function.
f_name = f"image{tag}.png"
cv2.imwrite(f_name, image)
with open(f_name, 'rb') as f:
results = reader.readtext(f.read())
import pyautogui
import easyocr
import numpy as np
reader = easyocr.Reader(['en'],gpu=False)
im = pyautogui.screenshot(region=(630,400,650,130)
result = reader.readtext(np.array(im),detail = 0)
just pass the pyautogui image as np.array

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']

How to save a movie made from pictures by OpenCV in Python

I wrote a Python program with OpenCV that:
scans the folder with images
does some operations on them with respect to their order
returns a list IMGs of processed images
Now what I want to do, is to save the list IMGs of new pictures as a e.g. .avi movie. How to do such operation? I intentionally want to save pictures from a list after whole process of filtration etc.
import os
import cv2
import numpy as np
folder_name = 'trial1'
extension = '.bmp'
path = os.getcwd()
GB_kernel = (13,13)
""" List all .bmp images names from a folder """
def folder_content(folder_name, extension):
dir_content = os.listdir(folder_name)
folder_content_ext = []
for file in dir_content:
if file.endswith(extension):
folder_content_ext.append(file)
return folder_content_ext
IMG_names = folder_content(folder_name, extension)
""" Some OpenCV operations on images """
""" Loop over all images. Iterator i is important in the future """
IMGs = []
for i in range(len(IMG_names)):
""" Define path to basic image """
img = path + '\\' + folder_name + '\\' + IMG_names[i]
""" read this image """
image = cv2.imread(img, cv2.IMREAD_GRAYSCALE)
""" some operation - gaussian blur """
pre_filt = cv2.GaussianBlur(image, GB_kernel, 0)
""" contain blurred img in a list """
IMGs.append(pre_filt)
cv2.imshow('Gaussian Blur', pre_filt)
WKey = 1
if cv2.waitKey(WKey) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
""" HOW?? """
save_list_of_matrix_as_movie(IMGs)
Thanks for any help and hints.
You can try the code below.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Create video from images in a list.
Idea from:
http://tsaith.github.io/combine-images-into-a-video-with-python-3-and-opencv-3.html
"""
import os
import time
import cv2
folder_name = 'trial1'
extension = '.bmp'
video_file = 'out.avi'
path = os.getcwd()
GB_kernel = (13, 13)
# %%
def folder_content():
"""
List all images names with given extension from a folder.
"""
dir_content = os.listdir(folder_name)
folder_content_ext = []
for file in dir_content:
if file.endswith(extension):
folder_content_ext.append(file)
return folder_content_ext
# %%
def img_2_matrix(img_names):
"""
Some OpenCV operations on images
Loop over all images. Iterator i is important in the future
"""
imgs = []
for i in range(len(img_names)):
# Define path to basic image
img = os.path.join(path, folder_name, img_names[i])
# read this image
image = cv2.imread(img, cv2.IMREAD_GRAYSCALE)
# some operation - gaussian blur
pre_filt = cv2.GaussianBlur(image, GB_kernel, 0)
# contain blurred img in a list
imgs.append(pre_filt)
cv2.imshow('Gaussian Blur', pre_filt)
wkey = 1
if cv2.waitKey(wkey) & 0xFF == ord('q'):
break
return imgs
# %%
def save_list_of_matrix_as_movie(imgs):
"""
"""
shape = (imgs[0].shape[1], imgs[0].shape[0])
fourcc = cv2.VideoWriter_fourcc(*"XVID") # XVID for avi, mp4v for mp4
out = cv2.VideoWriter(video_file, fourcc, 20.0, shape, 0)
print("\nHit 'q' to exit")
for frame in imgs:
pre_filt = cv2.GaussianBlur(frame, GB_kernel, 0)
out.write(pre_filt) # Write out frame to video
cv2.imshow("video", pre_filt)
if(cv2.waitKey(1) & 0xFF) == ord("q"): # Hit `q` to exit
break
return out
# %%
def release(out):
"""
Release everything if job is finished
"""
cv2.destroyAllWindows()
out.release()
# %%
if __name__ == "__main__":
# %%
TIC = time.time()
# %%
img_names = folder_content()
imgs = img_2_matrix(img_names)
out = save_list_of_matrix_as_movie(imgs)
release(out)
# %%
print("Time elapsed: %0.2f s" % (time.time() - TIC))

How to print 1 in every thousand frames using opencv and python?

I am trying to save one frame in every thousand frames of a video. Below is the code I am currently using:
import cv2
import numpy as np
import os
# Playing video from file:
cap = cv2.VideoCapture('D:/01 Projects/AMAZON CATALYST PROJECT/Surgery1.mpg')
try:
if not os.path.exists('D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1'):
os.makedirs('D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1')
except OSError:
print ('Error: Creating directory of data_surg1')
currentFrame = 0
while(True):
# Capture frame-by-frame
if currentFrame > 0:
cap.set(cv2.CAP_PROP_POS_MSEC,currentFrame)
ret, frame = cap.read()
# Saves image of the current frame in jpg file
name = 'D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1/frame' + str(currentFrame/1000) + '.jpg'
print ('Creating...' + name)
cv2.imwrite(name, frame)
# To stop duplicate images
currentFrame += 1000
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
However, I am not sure if this is saving it correctly. When I look at the frames in the file explorer, the numbers are initially very high and then reduce to form a sequential frame number compared to the previous image. I am using Python 2.7 and OpenCV3.3.
For storing from certain frames instead of a time-based save, the following script works:
import cv2
import numpy as np
import os
# Playing video from file:
cap = cv2.VideoCapture('D:/01 Projects/AMAZON CATALYST PROJECT/Surgery1.mpg')
try:
if not os.path.exists('D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1'):
os.makedirs('D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1')
except OSError:
print ('Error: Creating directory of data_surg1')
currentFrame = 0
while(True):
# Capture frame-by-frame
if currentFrame > 0:
cap.set(cv2.CAP_PROP_POS_FRAMES,currentFrame)
ret, frame = cap.read()
# Saves image of the current frame in jpg file
name = 'D:/01 Projects/AMAZON CATALYST PROJECT/data_surg1/frame' + str(currentFrame/1000) + '.jpg'
print ('Creating...' + name)
cv2.imwrite(name, frame)
# To stop duplicate images
currentFrame += 1
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

Categories