Very similar questions out already but I haven't been able to find one that really matches what I have going on.
This is a facial recognition app with about 200 lines of code so I will just post the part that is relevant.
The app does face recognition and then displays a the target photo next to the best matched mugshot. In case of false positives it also shows a list of the best 5 matches.
I would like for the images in this list to open upon running the code, however only one image in the list is opening for whatever reason.
Relevant piece of code:
# set distance between known faces and target face. The lower the distance between them the lower the match. Higher dist = more error.
if face_distances[best_match_index] < 0.60:
name = known_face_names[best_match_index]
resulttolog = "Match found within default tolerance level. " + "\n" "Match identified as: " + name + "\n"
log(resulttolog) # logging result
# save and display mugshot of best match
mugshot = cv2.imread(os.getcwd() + "/datasets/" + name + ".jpg")
mugshotresized = cv2.resize(mugshot, (500, 500), fx=0.5, fy=0.5)
cv2.imwrite(os.getcwd() + "/mugshot.jpg", mugshotresized)
# listing other closest maches
best_5_matches = n_known_face_names[top_3_matches]
matchestolist = list(best_5_matches)
log("Best matches in order:")
# sort list by number
for index, mugshot in enumerate(matchestolist, 1):
log("{}. {}".format(index, mugshot)) # log the numbered list
# pop up relevant matches
for filename in matchestolist:
path = os.getcwd() + "/datasets/"
file = path + filename + ".jpg"
img = cv2.imread(file)
cv2.imshow("image", img)
So in this last part, the images are supposed to all open. (i assume one pop up window for each image since its a for loop, but only one window is popping up with the first image).
Seems like an easy solution but I cant figure it out..
Any ideas?
You seem to be showing all images without waiting in the same named window 'image'.
Try
cv2.imshow(filename, img)
so they're opened in different windows?
Related
Right now here is all I'm having moviepy do:
full_video = VideoFileClip(input_video_path)
full_video.write_videofile("output.mp4")
quit()
It just takes the video and writes it to another file with no changes. But when the input video looks like this the output ends up looking like this with the video speed doubled but the audio just the same. I could take the audio and video separately, halve the speed of the video then put them back together but is there a way I can correct for whatever problem is causing this?
edit 2: It is the VideoFileClip method causing the speedup most likely, not the write_videofile method. When I try
full_video = VideoFileClip(input_video_path)
print( full_video.fps )
full_video.preview(fps = full_video.fps)
quit()
it is still double speed in the preview.
edit 3: The problem only happens with videos captured with Windows game bar. I tried a different video and it worked just fine with no speedup. I'll probably just find a different way to capture the screen recordings to fix it but I dont know what the root problem was
edit 1: the full code
from moviepy.editor import *
# get all dash times
times_path = "times.txt"
input_video_path = "input.mp4"
offset_time = 0
clip_length = float( input("Enter clip length: ") )
def get_times(path, offset):
dash_times_str = []
with open(path, "r") as file:
dash_times_str = file.readlines()
count = 0
# Strips the newline character
# also add offset time
temp = []
for line in dash_times_str:
count += 1
temp.append ("{}".format(line.strip()))
dash_times_str = temp
dash_times = []
for time in dash_times_str:
dash_times.append( float(time) + offset )
return dash_times
dash_times = get_times(times_path, offset_time)
def get_offset_time():
a = float(input("Enter time for first dash in video"))
b = dash_times[0]
return a-b
offset_time = get_offset_time()
full_video = VideoFileClip(input_video_path)
counter = 0
times_count = len(dash_times)
clips = []
for dash_time in dash_times:
clip = full_video.subclip(dash_time,dash_time+clip_length)
clips.append(clip)
counter+=1
print("Clip " + str(counter) + " out of " + str(times_count))
final_clip = concatenate_videoclips(clips)
final_clip.write_videofile("output.mp4")
I haven't been able to go deep down in the source code to figure out why this is, but I could indeed duplicate your bug with videos recorded with the Windows game bar.
I also agree with you that it seems to be tied directly to the VideoFileClip method.
I got my code to work by writing it like this:
full_video = VideoFileClip(input_video_path, fps_source="fps")
with the key detail being the (fps_source = "fps") bit.
I am trying to adopt mask_rcnn original code to my dataset.The original code takes xml files and I just modified my code to accept json format. Here is the code
def load_mask(self, image_id, xml=False):
# get details of image
info = self.image_info[image_id]
if xml:
# define anntation file location
path = info['annotation']
# load XML
boxes, w, h = self.extract_boxes(path, xml=True)
else:
with open('D:\Mask_RCNN\Mask_RCNN\dataset\\annots\\annotations.json', 'r') as f:
annots = json.load(f)
found = False
for value in annots.values():
if 'image' in value and value['instance_list']:
if value['image']['original_filename'][:-3] == info['id']:
boxes, w, h = self.extract_boxes(value)
found = True
break
if found:
# create one array for all masks, each on a different channel
masks = zeros([h, w, len(boxes)], dtype='uint8')
else:
stop = "here"
if found:
# create one array for all masks, each on a different channel
masks = zeros([h, w, len(boxes)], dtype='uint8')
else:
stop = "here"
# create masks
class_ids = list()
for i in range(len(boxes)):
box = boxes[i]
row_s, row_e = box[1], box[3]
col_s, col_e = box[0], box[2]
masks[row_s:row_e, col_s:col_e, i] = 1
class_ids.append(self.class_names.index('Penquins'))
return masks, asarray(class_ids, dtype='int32')
# load an image reference
#"""Return the path of the image."""
def image_reference(self, image_id):
info = self.image_info[image_id]
print(info)
return info['path']
It gives me the error
File "C:/PycharmProjects/Mask_RCNN/Mask_RCNN/objects.py", line 197, in load_mask
for i in range(len(boxes)):
UnboundLocalError: local variable 'boxes' referenced before assignment
I tried to debug the code,its throwing an error before creating masks but I am not able to figure out whats wrong. Any idea?
Only if xml is true, it is guaranteed, that boxes gets a value. Otherwise additional conditions have to be fulfilled, which does not seem to be the case.
boxes is initialized in some of the scenarios in load_mask's first if else block, which means it might not exists when you reach if found:. Just declare it in the beginning
def load_mask(self, image_id, xml=False):
# get details of image
info = self.image_info[image_id]
boxes = []
It means that you are trying to iterate over the number of boxes, but your if statements above are constructed in such a way that boxes might not exit by the time this statement gets executed.
try this simple example:
user_input = "no"
if user_input =="yes":
boxes = [1,2,3,4]
else:
pass
print(boxes)
This will result in the same error as you are seeing. Your problem is that both of these if statements must pass before boxes is defined:
if 'image' in value and value['instance_list']:
if value['image']['original_filename'][:-3] == info['id']:
Likely you either need additional logic that ensures the iteration only occurs if certain conditions are met. Or, if boxes is a list you could start your code by defining boxes=[]. In that case the iteration will simply pass over without doing anything as the length of boxes is zero in that case
The problem is that boxes isnt getting declared in line of this for loop, so define boxes as an empty list in the first part of the function
def load_mask(self, image_id, xml=False):
boxes = []
#do all the other stuff here
Then when you do the for loop it should now be declared (unless one of the functions don't return the boxes and give you something else)
Quick tip when doing the for loop, you can do
for i, box in enumerate(boxes):
...
which will not make you define box inside the loop (i will be 0 to len(boxes)-1 and box will be the box with that index)
In the code below i am drawing 3 images from a list (targetset) then displaying them to the screen. Next I am displaying another 3 images (pics) to a different part of the screen. For this second part; on 50% of occasions I want the 'pics' images to be the same as those displayed initially (target set). I am ok with this part, I am setting pics = targetset when x == 0 (basically flipping a coin).
My probleme is, on the other 50% of occasions I want one of the 'pics' set to be the same as one of the orignally showed set (targetset), any one of the three. And i want the remaining 2 to be randomly choosen from the pics list. As it stands, according to my logic, I can only get the 'pics' images to be all the same, or all different as the originally shown images from 'targetset'.
Adding to the problem: When x==0 (making pics=targetset) they all display ok, but when x==1 (meaning make no change) i get the following error message:
pics[i].pos = location[i]
UnboundLocalError: local variable 'pics' referenced before assignment
Here is my code:
#create initial target set
imgList1 = glob.glob(os.path.join('stim','*.png'))
random.shuffle(imgList1)
targetset = [visual.ImageStim(window, img) for img in imgList1[:3]]
#initial target set location
setlocation = [(-2,0),(0,0),(2,0)]
random.shuffle(setlocation)
#create target list
imgList = glob.glob(os.path.join('stim', '*.png'))
random.shuffle(imgList)
pics = [visual.ImageStim(window, img) for img in imgList[:3]]
#set target locations
location = [(1,2),(3,3),(5,5)]
random.shuffle(location)
'''define sequential presentation function'''
def seq():
x = random.randint(0,1)
if x == 0:
pics = targetset
print x
#display initial target set
for i in range(3):
targetset[i].pos = setlocation[i]
targetset[i].draw()
window.flip()
core.wait(3)
#display targets
for i in range(3):
pics[i].pos = location[i]
pics[i].draw()
window.flip()
core.wait(1)
seq()
core.wait(3)
window.close()
quit()
I hope someone can help,
Cheers
S
I see a few possible pitfalls with your code. One is that you are creating two separate lists imgList1 and imgList from the same set of images, then you are randomizing each of these lists separately and pulling the first three elements from each list into targetset and pics respectively. It is possible that these sub-sets will have some overlap in images. From the description of your task, I don't think that this is intentional. I might suggest creating only 1 imgList and then using the imgList.pop() function to pull images from the list. Pop returns the last element from the list and then deletes that element from the list. I think of it like drawing a card from a deck, you cannot draw the card again because it is no longer in the deck. What you're currently doing is like drawing cards from two different decks. You might get the same card twice.
The second problem I see here is that you define a condition for what to do when your coin-flip for x is 0, but you do not define one for when your coin-flip is 1. Currently, it will just display the first 3 images from imgList because that's how you've defined pics. I might suggest defining pics within an if/else block for your x coin-flip. If it's 0, then go with targetset, if it's 1, then randomly choose an element from target list, then copy that element to pics and pop two more images from imgList. As with all coding, there is more than one way to solve this problem, but I'll offer a solution here.
#Outside the trial loop
imgList = glob.glob(os.path.join('stim', '*.png'))
random.shuffle(imgList)
#Inside the trial loop
targetset = []
for i in range(0,3):
targetset.append(imgList.pop())
#Do your display stuff with targetset
if random.randint(0,1) == 0:
pics = targetset
else:
pics = []
pics.append(targetset[random.randint(0,2)])
pics.append(imgList.pop())
pics.append(imgList.pop())
random.shuffle(pics)
#Do your display stuff with pics
There seems to be something strange going on in this loop. I tried to debug it, and I have no explanation for what is going on.
This code is from another Stack Overflow post, and I made some edits to it.
modelImages = ['/home/lie/Desktop/dylan.jpg','/home/lie/Desktop/melissa.jpg']
for modelImage in modelImages:
**print modelImage**
template=cv2.imread(modelImage)
templateg = cv2.cvtColor(template,cv2.COLOR_BGR2GRAY)
keys = surf.detect(templateg)
keys,desc = surfDescriptorExtractor.compute(templateg, keys)
count = 0
for h,des in enumerate(desc):
des = np.array(des,np.float32).reshape((1,64))
retval, results, neigh_resp, dists = knn.find_nearest(des,1)
res,dist = int(results[0][0]),dists[0][0]
if dist<0.1: # draw matched keypoints in red color
count=count + 1
print "space"**
The important parts have asterisks. This is a portion of the code that was suppose to identify similarities among images of faces. What the code does is not important. The strange part is that this loop is executing 1 time for an array of size two.
The output is:
/home/lie/Desktop/dylan.jpg
/home/lie/Desktop/melissa.jpg
space
Notice that both strings in modelImages are printed before space. By the way this is part of a function that is called from a loop. This seems to be more of a python issue than an opencv issue. It almost seems like there is a hidden continue statment
Thanks
I have a script that is using OpenCV to find faces and if a face is not found it outputs "No faces found" but it never does anything else. It should look back up and ask for another image. Can anyone tell me why it just prints "No faces found" until I press CTRL+C?
def Crop(
imagePattern,
boxScale,
outputimg,
padding,
):
happy = True
imgList = glob.glob(imagePattern)
while happy:
if len(imgList) <= 0:
return
else:
for img in imgList:
pil_im = Image.open(img)
cv_im = pil2cvGrey(pil_im)
faces = DetectFace(cv_im, faceCascade)
if faces:
n = 1
for face in faces:
croppedImage = imgCrop(pil_im, face[0],
padding, boxScale=boxScale)
(fname, ext) = os.path.splitext(img)
fname = os.path.basename(fname)
croppedImage.save(outputimg + '\\' + fname
+ ' -c' + ext)
n += 1
print 'Cropping:', fname
else:
print 'No faces found:', img
break
# Verify image
# savedPath = outputimg + '\\' + fname + ' -c' + ext
# verify = cv2.imread(savedPath, 0)
# cv2.imshow('Saved Image', verify)
print 'Please open the file manually to view for now'
print 'Are you happy with the final crop?'
happyTest = raw_input('Enter y or n: ')
happyTest = happyTest.strip()
if happyTest == 'y':
happy = False
elif happyTest == 'n':
padding = int(raw_input('Enter crop padding:'))
else:
print 'Not a valid input'
print 'Do you have more pictures to take?'
again = raw_input('Enter y or n: ')
if again == 'y':
Webcam(webcam, padding, boxScale)
else:
print 'Closing application'
time.sleep(3)
raise SystemExit
Sorry for the confusion, I had a bad copy/paste due to me using tabs for my code.
EDIT:
Thank you for letting me know about the mixing tabs and spaces but my issue is still the same. It also does not matter if I use a break or a continue. Do I need to use recursion and call the function again?
You are using a break statement, which halts the for loop completely.
Instead, use a continue statement there to skip the current image and move on to the next one within the for loop.
Read more about break and continue here
Also, You are using tabs and spaces togather, which is causing the indentation of the blocks to be misaligned. While they look as if they are aligned all right, you will have nightmares debugging tab errors, so just change your editor settings to use a tab as 4 whitespaces.
EDIT
There are multiple issues in your code:
You are checking for len(imgList)<=0 which is redundant as has already been pointed out in other answer.
The happytest value that you take is taken for every img in imglist, yet only the one entered on the last run will affect the value of the happy variable.
Because of #2 above, I am inclined to think that your original intent was to stop at any run during which the value of happy was False, which is definitely not happening right now.
You are using capital letters and camel case both to begin the name of some functions and I am having a hard time figuring if something is a public class or another function.
There are multiple external functions being referenced within the code, but I have not much clue of what they are supposed to do, and whether they actually do whatever they are supposed to do.
I don't know if this is the problem, but it is how you posted it anyway: Your commands after the else statement are not indented. Shouldn't it have given you an error?
The break you have coded breaks out of the for img in imgList: loop, not the while happy: loop. And since the code you use to ask the user if the cropping is satisfactory, is inside that loop (and after the break), it never gets reached (and thus happy can never be set False).
You have an extar break on your code -this version should work:
for img in imgList:
pil_im=Image.open(img)
cv_im=pil2cvGrey(pil_im)
faces=DetectFace(cv_im,faceCascade)
if faces:
n=1
for face in faces:
croppedImage=imgCrop(pil_im, face[0], padding, boxScale=boxScale)
fname,ext=os.path.splitext(img)
fname = os.path.basename(fname)
croppedImage.save(outputimg + '\\' + fname + ' -c' + ext)
n+=1
print 'Cropping:', fname
else:
print 'No faces found:', img
So, while it is true on the other answers and comments that you shpould not have the "break" inside the elsestatement - the problem you put forward in your question happens because you have that break at all: if the code reach that else block, it will just break out of the for img in imgList: loop and process nothing further.
besides that, I have fixed two other things in this code:
indentation - in Python it is serious business, not "what works is fine". The recomendation is to use 4 spaces per block nesting - no more, no less, and never, never mix tabs and spaces. You have to configure that on your code editor preferences.
The other part of your code that is alien to Python is the verification prior to the loop
if len(imgList)<=0: that is complettly superfluous in Python (not to mention the <= part): if the list lenght is zero (it can't be negative), the forstatement will try to pick the first item, and since it does not exist, the program will simply continue after the for block. Each level of indentation you reduce in your code is a bonus in readability. (The Zen of Python even reads "Flat is better than nested"). On the other hand, if in some other part of the code you really have to check if the lsit is empty,just do if imgList:, as sequences in Python have the nice property of having a False boolean value if they are empty, and True otherwise.