I have a small script which checks if my object is present in image or not. If present then it writes the image to a folder.There are multiple sub-folders inside.On writing, the data for 1st folder works fine but when data is written to the 2nd sub-folder then the data of 1st folder is also appended along-with the data of 2nd folder
The code works perfectly fine except the problem that while writing the data to disk the data of 1st sub-folder is also appended to the data of 2nd sub-folder. Below is my code
def target_non_target(input_frames_folder,model_file,output):
if not os.path.exists(output):
os.makedirs(output,exist_ok=True)
count=0
folders = glob(input_frames_folder)
img_list = []
for folder in folders:
folder_name=os.path.basename(folder)
#print(folder_name)
out_path = output +"\\" + folder_name
print(out_path)
os.makedirs(out_path,exist_ok=True)
for f in glob(folder+"/*.jpg"):
img_list.append(f)
for i in range(len(img_list)):
v1=os.path.basename(img_list[i])
img_name = os.path.splitext(v1)[0]
image = cv2.imread(img_list[i])
orig = image.copy()
image = cv2.resize(image, (28, 28))
image = image.astype("float") / 255.0
image = img_to_array(image)
image = np.expand_dims(image, axis=0)
print("[INFO] loading network...")
model = load_model(model_file)
(non_target, target) = model.predict(image)[0]
if target > non_target:
label = "Target"
else:
label = "Non Target"
probab = target if target > non_target else non_target
label = "{}: {:.2f}%".format(label, probab * 100)
op = imutils.resize(orig, width=400)
cv2.putText(op, label, (10, 25), cv2.FONT_HERSHEY_SIMPLEX,0.7, (0, 255, 0), 2)
if target > non_target:
cv2.imwrite(out_path+"/"+"\\{}.jpg".format(img_name),orig)
cv2.waitKey(0)
#return target_op
frames_folder = ("C:\\Python36\\videos\\videos_new\\*")
model = ("C:\\Python35\\target_non_target\\target_non_target.model")
output_folder = ("C:\\Python35\\target_non_target\\Target_images_new\\")
target_check = target_non_target(frames_folder,model,output_folder)
Suppose there are 2 sub-folders A and B inside a main folder X.There will be many more sub-folders.While writing output to disk the data of A is written perfectly but while writing data for B the data of folder A and folder B both are getting appended into B folder. I want the data to be in their respective folders. Any idea what changes could be made in my script for getting the desired output
You are using the img_list = [] to initiate but you need to repeat this at the end of each folder loop to reset it back to empty. Right now you are keeping all of your results and then when you move to the next folder you are keeping your previous results and adding on.
The very end of your for folder in folders loop needs to have img_list = []
Updated full code:
def target_non_target(input_frames_folder,model_file,output):
if not os.path.exists(output):
os.makedirs(output,exist_ok=True)
count=0
folders = glob(input_frames_folder)
img_list = []
for folder in folders:
folder_name=os.path.basename(folder)
#print(folder_name)
out_path = output +"\\" + folder_name
print(out_path)
os.makedirs(out_path,exist_ok=True)
for f in glob(folder+"/*.jpg"):
img_list.append(f)
for i in range(len(img_list)):
v1=os.path.basename(img_list[i])
img_name = os.path.splitext(v1)[0]
image = cv2.imread(img_list[i])
orig = image.copy()
image = cv2.resize(image, (28, 28))
image = image.astype("float") / 255.0
image = img_to_array(image)
image = np.expand_dims(image, axis=0)
print("[INFO] loading network...")
model = load_model(model_file)
(non_target, target) = model.predict(image)[0]
if target > non_target:
label = "Target"
else:
label = "Non Target"
probab = target if target > non_target else non_target
label = "{}: {:.2f}%".format(label, probab * 100)
op = imutils.resize(orig, width=400)
cv2.putText(op, label, (10, 25), cv2.FONT_HERSHEY_SIMPLEX,0.7, (0, 255, 0), 2)
if target > non_target:
cv2.imwrite(out_path+"/"+"\\{}.jpg".format(img_name),orig)
cv2.waitKey(0)
img_list = [] # this is the end of for folder in folders, reset list
#return target_op
frames_folder = ("C:\\Python36\\videos\\videos_new\\*")
model = ("C:\\Python35\\target_non_target\\target_non_target.model")
output_folder = ("C:\\Python35\\target_non_target\\Target_images_new\\")
target_check = target_non_target(frames_folder,model,output_folder)
Related
I am trying to read images from one directory and read their correspondant txt files containing the label and bounding box coordinates from another directory, then create a mask and store all these mask for each image in another dataframe.
The problem is only the first loop is executed in my code. (i.e in the mask_images dataset only the first image is stored)
here is my code:
mask_images = [] # DATASET FOR GRAYSCALE IMAGES
RGB_images = [] # DATASET FOR RGB IMAGES
for root, dirnames, filenames in os.walk("dataset/test/images"):
for imgname in filenames:
if re.search("\.(jpg|jpeg|JPEG|png|bmp|tiff)$", imgname):
imgpath = os.path.join(root, imgname)
name = os.path.splitext(imgname)
name = name[0] + ".txt"
img = cv2.imread(imgpath)
rgb_image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
RGB_images.append(rgb_image)
mask = np.zeros((img.shape[0], img.shape[1]), dtype = np.uint8)
#plt.imshow(mask, cmap = 'gray')
#print(imgname)
#print(imgpath)
for root, dirnames, filenames in os.walk("dataset/test/detection_labels"):
for txtname in filenames:
if name == txtname:
#print(txtname)
txtpath = os.path.join(root, txtname)
#print(txtpath)
with open(txtpath,'r') as f:
lines = f.readlines()
print(lines)
for line in lines:
#print(line)
coords = [float(coords) for coords in re.findall(r'-?\d+\.?\d*', line)]
coords[1] = np.int_(coords[1] * 2000)
coords[2] = np.int_(coords[2] * 2000)
coords[3] = np.int_(coords[3] * 2000)
coords[4] = np.int_(coords[4] * 2000)
print(coords)
mask = cv2.rectangle(mask, pt1 = (coords[1], coords[2]), pt2 = (coords[1] + coords[3], coords[2] + coords[4]), color = (255,255,255), thickness = -1)
f.close()
mask_images.append(mask)
I'm using this tutorial to get started with TensorFlow -
TensorFlow for poets.
After training the model using the retrain.py script, I want to use the
retrained_graph.pb in order to classify a video and see the results live while the video is running.
What I did is to use opencv to read the video which I want to classify frame by frame. i.e read a frame, save it, open it, classify it and show it on screen together with the classification result using cv2.imshow().
It works, but due to the reading and writing of the frames from/to the disk, the resulting video is laggy.
Can I use the graph obtained from the training process and classify a video without reading and saving it frame by frame?
This is the code I'm using -
with tf.Session(graph=graph) as sess:
video_capture = cv2.VideoCapture(video_path)
i = 0
while True:
frame = video_capture.read()[1] # get current frame
frameId = video_capture.get(1) #current frame number
i = i + 1
cv2.imwrite(filename="C:\\video_images\\"+ str(i) +".jpg", img=frame) # write frame image to file
image_data = "C:\\video_images\\" + str(i) + ".jpg"
t = read_tensor_from_image_file(image_data,
input_height=input_height,
input_width=input_width,
input_mean=input_mean,
input_std=input_std)
predictions = sess.run(output_operation.outputs[0], {input_operation.outputs[0]: t})
top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]
scores = []
for node_id in top_k:
human_string = label_lines[node_id]
score = predictions[0][node_id]
scores.append([score, human_string])
#print('%s (score = %.5f)' % (human_string, score))
#print("\n\n")
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame, scores[0][1] + " - " + repr(round(scores[0][0], 2)), (10, 50), font, 1, (0, 0, 255), 2, cv2.LINE_AA)
cv2.putText(frame, scores[1][1] + " - " + repr(round(scores[1][0], 2)), (10, 100), font, 1, (0, 0, 255), 2, cv2.LINE_AA)
cv2.imshow("image", frame)
cv2.waitKey(1)
os.remove("C:\\video_images\\" + str(i) + ".jpg")
video_capture.release()
cv2.destroyAllWindows()
Thanks.
frame = video_capture.read()[1] # get current frame
float_caster = frame.astype(np.float32)
dims_expander = np.expand_dims(float_caster, axis=0)
resized = cv2.resize(dims_expander,(int(input_width),int(input_height)))
normalized = (resized - input_mean) / input_std
predictions = sess.run(output_operation.outputs[0], {input_operation.outputs[0]: normalized})
Instead of using imwrite just to call read_tensor_from_image_file, get the frame itself. Resize and normalize it. Then, pass the normalized into session. Get rid of disk unnecessary write/read operations this way.
Managed to solve it.
Edited read_tensor_from_image_file to the following and just fed it with the frame instead of image_data.
def read_tensor_from_image_file(file_name,
input_height=299,
input_width=299,
input_mean=0,
input_std=255):
input_name = "file_reader"
output_name = "normalized"
if type(file_name) is str:
file_reader = tf.read_file(file_name, input_name)
if file_name.endswith(".png"):
image_reader = tf.image.decode_png(file_reader, channels = 3,
name='png_reader')
elif file_name.endswith(".gif"):
image_reader = tf.squeeze(tf.image.decode_gif(file_reader,
name='gif_reader'))
elif file_name.endswith(".bmp"):
image_reader = tf.image.decode_bmp(file_reader, name='bmp_reader')
else:
image_reader = tf.image.decode_jpeg(file_reader, channels = 3,
name='jpeg_reader')
float_caster = tf.cast(image_reader, tf.float32)
dims_expander = tf.expand_dims(float_caster, 0);
resized = tf.image.resize_bilinear(dims_expander, [input_height,
input_width])
normalized = tf.divide(tf.subtract(resized, [input_mean]),
[input_std])
sess = tf.Session()
result = sess.run(normalized)
elif type(file_name) is np.ndarray:
resized = cv2.resize(file_name, (input_width, input_height),
interpolation=cv2.INTER_LINEAR)
normalized = (resized - input_mean) / input_std
result = normalized
result = array(result).reshape(1, 224, 224, 3)
return result
I need to run a python script inside a folder.
the script count files ( image ) number create an image for
every 64 images.
example: if the folder containing 640 images, I will get 10
images as a combination of 64 images/outputimage
just, before adding "for" instruction, I can get a result, but manually and only with the same image ( a duplication of image ).
any idea?
so I proceed as follows:
import os
import os.path
from PIL import Image
list = os.listdir(".") # current directory
number_files = len(list)
print (number_files)
for x in range(0, number_files):
# files = ['x.png']
# opens an image: here I can't find how
im = Image.open("1.png") # here I tried to
# creates a new empty image, RGB mode, and size 800 by 800.
new_im = Image.new('RGB', (800, 800))
# Here I resize my opened image, so it is no bigger than 100,100
im.thumbnail((100, 100))
# Iterate through a 8 by 8 grid with 100 spacing, to place my image
for i in xrange(0, 800, 100):
for j in xrange(0, 800, 100):
# paste the image at location i,j:
new_im.paste(im, (i, j))
new_im.save(os.path.expanduser('outputimage.png'))
update :
import os
import os.path
from PIL import Image
def drange(start, stop, step):
while start < stop:
yield start
start += step
list = os.listdir(".") # directory path
number_files = len(list)
print (number_files)
new_im = Image.new('RGB', (800, 800))
for x in drange(0, number_files, 64):
im = Image.open(list[x])
im.thumbnail((100, 100))
for i in xrange(0, 800, 100):
for j in xrange(0, 800, 100):
new_im.paste(im, (i, j))
new_im.save(os.path.expanduser('out.png'))
other update based on Sven solution :
import os.path
from PIL import Image
fileList = [] where_to_look = "png/"
for f in os.listdir(where_to_look):
if os.path.isfile(os.path.join(where_to_look, f)):
fileList.append(f)
print (len(fileList))
target_img = None n_targets = 0 collage_saved = False
for n in range(len(fileList)):
img = Image.open(fileList[n])
img.thumbnail((100, 100))
if n % 64 == 0:
# create an empty image for a collage
target_img = Image.new("RGB", (800, 800))
n_targets += 1
collage_saved = False
# paste the image at the correct position
i = int(n / 8)
j = n % 8
target_img.paste(img, (100*i, 100*j))
if (n + 1) % 64 == 0 and target_img is not None:
# save a finished 8x8 collage
target_img.save("{0:04}.png".format(n_targets))
collage_saved = True
# save the last collage if not collage_saved:
target_img.save("{0:04}.png".format(n_targets))
Based on your update, I quickly sketched a solution. Please beware that I did not test it:
import os
from PIL import Image
image_dir = os.path.abspath("png")
# list all files in directory
files = os.listdir(image_dir)
# get all PNGs
png_files = filter(lambda x: x.endswith(".png"), files)
# make file paths absolute
image_files = map(lambda x: os.sep.join([image_dir, x]), png_files)
n_files = len(image_files)
target_img = None
n_targets = 0
collage_saved = False
for n in range(n_files):
img = Image.open(image_files[n])
img.thumbnail((100, 100))
if n % 64 == 0:
# create an empty image for a collage
target_img = Image.new("RGB", (800, 800))
n_targets += 1
collage_saved = False
# paste the image at the correct position
i = int(n / 8)
j = n % 8
target_img.paste(img, (100*i, 100*j))
if (n + 1) % 64 == 0 and target_img is not None:
# save a finished 8x8 collage
target_img.save("{0:04}.png".format(n_targets))
collage_saved = True
# save the last collage
if not collage_saved:
target_img.save("{0:04}.png".format(n_targets))
This will iterate over all your images and assemble them in a 8x8 grid (I call it collage in the script). Whenever the grid is filled, the collage is saved as a file with the naming pattern 0001.png, 0002.png and so on.
Note that there are some points to improve:
os.listdir(".") will give you all files in the directory, not only images. You would have to filter the output for image files.
This only works in the current working directory.
The output is also saved to the current working directory.
UPDATE: filter PNGs and use absolute paths
I wanted to see that the images I used in my network were OK, so I saved a bunch of them using the following code:
train_set = dset.MNIST(root=root, train=True, transform=transforms.ToTensor(), download=download)
for it, (img, target) in enumerate(train_loader):
X = Variable(img)
tar = Variable(target)
X = X.view(batch_size, -1)
cur_img_batch = X.data.numpy()
cur_tar_batch = tar.data.numpy()
for i in range(batch_size):
cur_img = cur_img_batch[i]
im = Image.fromarray(cur_img.reshape((28, 28)).astype('uint8') * 255)
if cur_tar_batch[i] == 8:
im.save(test_img_dir + 'iter_' + str(it) + '_sample_' + str(i) + '.png')
This isn't the cleanest code, but it just saves a bunch of images that are all labeled as '8'. Upon opening them, I see that most of them look like this, even though a small minority of them are perfectly fine.
Am I doing something wrong?
From the comments:
The issue was in this line cur_img.reshape((28, 28)).astype('uint8') * 255, converting the normalized image to integer before multiplying it by 255, thus resulting in images with either 0 or 255.
The updated code:
train_set = dset.MNIST(root=root, train=True, transform=transforms.ToTensor(), download=download)
for it, (img, target) in enumerate(train_loader):
X = Variable(img)
tar = Variable(target)
X = X.view(batch_size, -1)
cur_img_batch = X.data.numpy()
cur_tar_batch = tar.data.numpy()
for i in range(batch_size):
cur_img = cur_img_batch[i]
im = Image.fromarray((cur_img.reshape((28, 28)) * 255).astype('uint8'))
if cur_tar_batch[i] == 8:
im.save(test_img_dir + 'iter_' + str(it) + '_sample_' + str(i) + '.png')
I am facing a little problem,
actually I have a function which generates so many frames from a video that I provided to my code which then saves in a specific folder , then I access some frames from that folder by using RND (random ) command , now what I want is that those random frames which my code pick randomly should also save in some other folder, for example, if there are 300 frames and my code pick 15 frames randomly from those 300 frames then these 15 frames must also save in some other separate folder .
This is my code,
def video_frames(nameof_video,frame_savelocation,cropimages_save):
vidcap = cv2.VideoCapture(nameof_video)
success, image = vidcap.read()
print(success)
count = 1
success = True
while success:
success, image = vidcap.read()
cv2.imwrite(frame_savelocation+"/%d.jpg" % count, image)
# save frame as JPEG file
# if cv2.waitKey(10) == 27: # exit if Escape is hit
# break
if count == 0:
break
count += 1
print("frames saved in the desired location!!!!!")
##### crop faces from frame and save them----###
for r in range(1, 15):
random_imagecrop(frame_savelocation, cropimages_save) #-----> function called
return
def random_imagecrop(frame_savelocation,cropimages_save):
#b=1
crop_faces_path = frame_savelocation
list_frames = os.listdir(crop_faces_path) # dir is your directory path
number_files = len(list_frames)
rnd = random.randint(1, number_files)
print("random:", rnd)
image = face_recognition.load_image_file(frame_savelocation + "/" + str(rnd) + ".jpg")
#pil_image.save("Datasets/randomimg" + "/" + str(b) + ".jpg")
#b=b+1
# Find all the faces in the image
face_locations = face_recognition.face_locations(image)
check = os.listdir(cropimages_save) # dir is your directory path
already_prsntimg = len(check)
a = 1+already_prsntimg
for face_location in face_locations:
# Print the location of each face in this image
top, right, bottom, left = face_location
# print("A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}".format(top, left, bottom, right))
# You can access the actual face itself like this:
face_image = image[top:bottom, left:right]
pil_image = Image.fromarray(face_image)
# pil_image.show()
pil_image.save(cropimages_save + "/" + str(a) + ".jpg")
a = a + 1
print("--> Images saved successfully...!!!")
# a=a+len(face_locations)
return
You can use os.chdir('output') to change the working directory to the output directory and then write the image. Then to return to the original directory to pick your random images use os.chdir('../').