Hi i've a script to run image process on a image. But i'm trying to get a loop or another way to read multiple images from a file
e.g
C:\Users\student\Desktop\Don\program (opencv version)\Images\move1
move1 contains images named as frame1.jpg , frame2.jpg , frame3.jpg...
The script i'm using to run the image process is something like
img = cv2.imread('frame1.jpg')
mimg = cv2.medianBlur(img,15)
gimg = cv2.cvtColor(mimg,cv2.COLOR_RGB2GRAY)
ret,th1 = cv2.threshold(gimg, 160,255,cv2.THRESH_BINARY)
ret,th2 = cv2.threshold(th1, 160,255,cv2.THRESH_BINARY_INV)
cv2.imwrite('threshbinaryinv.jpg', th2)
My script above could only read images that i manually keyed in e.g 'frame1.jg'. Sorry i'm very new to python. Thanks!
EDIT
This the code i edited with you guys help.. still getting error as "Traceback (most recent call last):
File "C:\Users\student\Desktop\Don\program (opencv version)\prog.py", line 32, in
gimg = cv2.cvtColor(mimg,cv2.COLOR_RGB2GRAY) #convert RBG to Grayscale
cv2.error: D:\Build\OpenCV\opencv-3.3.1\modules\imgproc\src\color.cpp:11048: error: (-215) scn == 3 || scn == 4 in function cv::cvtColor"
CODE
path_of_images = 'C:/Users/student/Desktop/Don/program (opencv version)/Images'
list_of_images = os.listdir(path_of_images)
for image in list_of_images:
img = cv2.imread(os.path.join(path_of_images, image))
mimg = cv2.medianBlur(img,15)
gimg = cv2.cvtColor(mimg,cv2.COLOR_RGB2GRAY)
ret,th1 = cv2.threshold(gimg, 160,255,cv2.THRESH_BINARY)
ret,th2 = cv2.threshold(th1, 160,255,cv2.THRESH_BINARY_INV)
cv2.imwrite('threshbinaryinv.jpg', th2)
You can use os.listdir() to get the names of all images in your specified path which is "C:\Users\student\Desktop\Don\program (opencv version)\Images". Then you can loop over the names of images like :
import os
import cv2
path_of_images = r"C:\Users\student\Desktop\Don\program (opencv version)\Images"
list_of_images = os.listdir(path_of_images)
for image in list_of_images:
img = cv2.imread(os.path.join(path_of_images, image))
"""Your code here"""
It can be done using a for loop and generating a new str file name and then processing it as:
IMG_FOLDER_PREFIX = "absolute/path/to/frame"
IMG_EXTENSION = ".jpg"
NUM_IMAGES = 10
for i in xrange(NUM_IMAGES):
image_path = IMG_FOLDER_PREFIX + str(i) + IMG_EXTENSION
img = cv2.imread(image_path)
# Other Image Processing.
A better way to iterate images would be os.listdir, glob, etc. but in that case you may have lesser control over the order of files traversed.
Related
i am making a face recognition program but i am facing NotADirectoryError error whenever i run it
i tried coping the full directory as well as using os.join.path and nothing worked
i am using pycharm.
import face_recognition
import cv2
import os
import numpy
os.chdir('C:/Users/a/Desktop/ftp')
KNOWN_FACE_DIR = "known_faces"
print(KNOWN_FACE_DIR)
#UNKNOWN_FACES_DIR = r"unknown_faces"
TOLERANCE = 0.6
FRANE_THICKNESS = 3
FONT_THICKNESS = 2
MODEL = "cnn"
video = cv2.VideoCapture(0)
print("loading known faces ")
known_faces = []
known_names = []
for name in os.listdir(KNOWN_FACE_DIR):
for filename in os.listdir(f"{KNOWN_FACE_DIR}/{name}"):
image = face_recognition.load_image_file(f"{KNOWN_FACE_DIR}/{name}/{filename}")
print("processing unknown faces")
while True :
#print(filename)
#image = face_recognition.load_image_file(f"{UNKNOWN_FACES_DIR}/{filename}")
ret ,image = video.read()
locations = face_recognition.face_locations(image, model=MODEL)
encodings = face_recognition.face_encodings(image, locations)
#image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
for face_encoding, face_location in zip(encodings, locations):
results = face_recognition.compare_faces(known_faces, face_encoding, TOLERANCE)
match = None
if True in results:
match = known_names[results.index(True)]
print(f"Match found:{match}")
top_left = (face_location[3], face_location[0])
bottom_right = (face_location[1], face_location[2])
color = [0,255,0]
cv2.rectangle(image, top_left, bottom_right, color, FRANE_THICKNESS)
top_left = (face_location[3], face_location[2])
bottom_right = (face_location[1], face_location[2]+22)
cv2.rectangle(image, top_left, bottom_right, color, cv2.FILLED)
cv2.putText(image, match, (face_location[3]+10,face_location[2]+15).cv2.FONT_HERSHEY_SIMPLEX,0.5,(200,200,200),FONT_THICKNESS)
cv2.imshow(filename,image)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cv2.destroyWindow(filename)
the error
Traceback (most recent call last):
File "C:\Users\a\Desktop\ftp\face recognition.py", line 27, in <module>
for filename in os.listdir(f"{KNOWN_FACE_DIR}/{name}"):
NotADirectoryError: [WinError 267] The directory name is invalid: 'known_faces/Majd.jpg'
i tried coping the whole directory
and using os.join.path although i am now sure i used it correctly
The os.listdir function requires a directory name, and something called Madj.jpg is most likely to be a JPEG file rather than a directory.
It looks like your assumption that everything in C:/Users/a/Desktop/ftp/known_faces is a directory containing files that you want to process may not be correct.
I am trying to create a face recognition software using OpenCV, but the code I found in the library is made in Python 2. Is there a Python 3 version of this?
Here's the link: https://github.com/thecodacus/Face-Recognition
I already have a folder for dataset and trainer.
import cv2
import numpy as np
from PIL import Image
import os
# Path for face image database
path = 'dataset'
recognizer = cv2.face.LBPHFaceRecognizer_create()
detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml");
# function to get the images and label data
def getImagesAndLabels(path):
imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
faceSamples=[]
ids = []
for imagePath in imagePaths:
PIL_img = Image.open(imagePath).convert('L') # convert it to grayscale
img_numpy = np.array(PIL_img,'uint8')
id = int(os.path.split(imagePath)[-1].split('.')[1])
faces = detector.detectMultiScale(img_numpy)
for (x,y,w,h) in faces:
faceSamples.append(img_numpy[y:y+h,x:x+w])
ids.append(id)
return faceSamples,ids
print ("\n [INFO] Training faces. It will take a few seconds. Wait ...")
faces,ids = getImagesAndLabels(path)
recognizer.train(faces, np.array(ids))
# Save the model into trainer/trainer.yml
recognizer.write('trainer/trainer.yml') # recognizer.save() worked on Mac, but not on Pi
# Print the numer of faces trained and end program
print("\n [INFO] {0} faces trained. Exiting Program".format(len(np.unique(ids))))
Error:
Traceback (most recent call last):
File "/Users/user/Desktop/FacialRecognition/02_face_training.py", line 46, in <module>
faces,ids = getImagesAndLabels(path)
File "/Users/user/Desktop/FacialRecognition/02_face_training.py", line 36, in getImagesAndLabels
id = int(os.path.split(imagePath)[-1].split('.')[1])
ValueError: invalid literal for int() with base 10: 'User'
On that repository there's a dataSet directory, with a file named like:
In [665]: name='Face-Recognition/dataSet/face-1.1.jpg'
Applied to that name, your code sample does:
In [668]: os.path.split(name)
Out[668]: ('Face-Recognition/dataSet', 'face-1.1.jpg')
In [669]: os.path.split(name)[-1]
Out[669]: 'face-1.1.jpg'
In [670]: os.path.split(name)[-1].split('.')
Out[670]: ['face-1', '1', 'jpg']
In [671]: os.path.split(name)[-1].split('.')[1]
Out[671]: '1'
In [672]: int(os.path.split(name)[-1].split('.')[1])
Out[672]: 1
Apparently your file has a different name format, one that includes 'User' in a slot where this code expects a number.
You need to correct the file name, or change this parsing code.
The image name which you got in the dataset are as User.*somename*, so remove User from all the image names.
try to change format images is 'face.1.1.jpg'
then you can split the dot with this code
faceID = int(os.path.split(imagePath)[-1].split(".")[2])
This did the job for me:
Id=int(os.path.split(imagePath)[-1].split(".")[0])
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.
I am trying to read the images and resize the image in my home directory file but didn't work please help how to read images and resize it.
import cv2
from PIL import Image
img = cv2.resize(cv2.read('C://Users//NanduCn//jupter1//train-scene classification//train"', (28, 28)))
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-103-dab0f11a9e2d> in <module>()
1 import cv2
2 from PIL import Image
----> 3 img = cv2.resize(cv2.read('C://Users//NanduCn//jupter1//train-scene classification//train"', (28, 28)))
AttributeError: module 'cv2.cv2' has no attribute 'read'
To read all images of particular extension, e.g. "*.png", one can use cv::glob function
void loadImages(const std::string& ext, const std::string& path, std::vector<cv::Mat>& imgs, const int& mode)
{
std::vector<cv::String> strBuffer;
cv::glob(cv::String{path} + cv::String{"/*."} + cv::String{ext}, strBuffer, false);
for (auto& it : strBuffer)
{
imgs.push_back(cv::imread(it, mode));
}
}
std::vector<cv::Mat> imgs;
loadImages("*.png", "/home/img", imgs, cv::IMREAD_COLOR);
And then resize each image in buffer
for (auto& it : imgs)
{
cv::resize(it, it, cv::Size{WIDTH, HEIGHT});
}
It should be easy to rewrite to python since almost all functions / data types have equivalents in python.
filenames = glob("/home/img/*.png").sort()
images = [cv2.imread(img) for img in filenames]
for img in images:
cv2.resize(img, (WIDTH, HEIGHT))
The code is divided to parts instead of one-liner because it is more readable, at least for me.
Using glob module:
dpath = "C:/your_path/"
fmt = "png"
size = (28, 28)
imgs = [cv2.resize(cv2.imread(fpath), size) for fpath in glob.glob("{}/*.{}".format(dpath, fmt))]
the error here is that you are giving a directory to cv2.imread but it only accepts image-path as input else it throws the error.
so we can do is parse all the files in a folder using os module and then read the images one by one and than resize and do other operations on them.
import os
import cv2
from PIL import Image
size = (28, 28)
imagesPath = "C://Users//NanduCn//jupter1//train-scene classification//train"
for imageName in os.listdir(imagesPath):
imageFullPath = os.path.join(imagesPath,imageName)
img = cv2.resize(cv2.imread(imageFullPath), size)
#do your processing here
also i here consider that you only have images in that folder. if you have other types of files or other folders inside it you can put a check before the os.path.join line.
Hope this helps.
I'm learning Python and Django.
An image is provided by the user using forms.ImageField(). Then I have to process it in order to create two different sized images.
When I submit the form, Django returns the following error:
IOError at /add_event/
cannot identify image file
I call the resize function:
def create_event(owner_id, name, image):
image_thumb = image_resizer(image, name, '_t', 'events', 180, 120)
image_medium = image_resizer(image, name, '_m', 'events', 300, 200)
I get en error when image_resizer is called for the second time:
def image_resizer(image, name, size, app_name, length, height):
im = Image.open(image)
if im.mode != "RGB":
im = im.convert("RGB")
im = create_thumb(im, length, height)
posit = str(MEDIA_ROOT)+'/'+app_name+'/'
image_2 = im
image_name = name + size +'.jpg'
imageurl = posit + image_name
image_2.save(imageurl,'JPEG',quality=80)
url_image='/'+app_name+'/'+image_name
return url_image
Versions:
Django 1.3.1
Python 2.7.1
PIL 1.1.7
I'm trying to find the problem, but i don't know what to do. Thank you in advanced!
EDIT
I solved rewriting the function; now it creates the different images in batch:
I call the resize function:
url_array = image_resizer.resize_batch(image, image_name, [[180,120,'_t'], [300,200,'_m']], '/events/')
so:
image_thumb = url_array[0]
image_medium = url_array[1]
and the resize function:
def resize_batch(image, name, size_array, position):
im = Image.open(image)
if im.mode != "RGB":
im = im.convert("RGB")
url_array = []
for size in size_array:
new_im = create_thumb(im, size[0], size[1])
posit = str(MEDIA_ROOT) + position
image_name = name + size[2] +'.jpg'
imageurl = posit + image_name
new_im.save(imageurl,'JPEG',quality=90)
new_url_array = position + image_name
url_array.append(new_url_array)
return url_array
Thanks to all!
As ilvar asks in the comments, what kind of object is image? I'm going to assume for the purposes of this answer that it's the file property of a Django ImageField that comes from a file uploaded by a remote user.
After a file upload, the object you get in the ImageField.file property is a TemporaryUploadedFile object that might represent a file on disk or in memory, depending on how large the upload was. This object behaves much like a normal Python file object, so after you have read it once (to make the first thumbnail), you have reached the end of the file, so that when you try to read it again (to make the second thumbnail), there's nothing there, hence the IOError. To make a second thumbnail, you need to seek back to the beginning of the file. So you could add the line
image.seek(0)
to the start of your image_resizer function.
But this is unnecessary! You have this problem because you are asking the Python Imaging Library to re-read the image for each new thumbnail you want to create. This is a waste of time: better to read the image just once and then create all the thumbnails you want.
I'm guessing that is a TemporaryUploadedFile ... find this with type(image).
import cStringIO
if isinstance(image, TemporaryUploadedFile):
temp_file = open(image.temporary_file_path(), 'rb+')
content = cStringIO.StringIO(temp_file.read())
image = Image.open(content)
temp_file.close()
I'm not 100% sure of the code above ... comes from 2 classes I've got for image manipulation ... but give it a try.
If is a InMemoryUploadedFile your code should work!