def run(self, filepath): detector = dlib.get_frontal_face_detector() # predictor = dlib.shape_predictor(os.path.join(sys.path[0], "data/")) #ignore for now # Start the frame queue vs = FileVideoStream(filepath) if (not vs.stream.isOpened()): return 0, 0 self.maxframes = int(vs.stream.get(cv2.CAP_PROP_FRAME_COUNT)) vs.start() best_frame = 0 scoremax = 0 self.framecounter = 0 # loop over the frames from the video stream while (self.framecounter < self.maxframes): # grab the frame from the threaded video stream, resize it to # have a maximum width of 400 pixels, and convert it to # grayscale frame = vs.read() frame = imutils.resize(frame, width=400) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # detect faces in the grayscale frame rects, scores, idx = detector.run(gray, 0, 0) # loop over the face detections self.framecounter = self.framecounter + 1 for i, rect in enumerate(rects): # compute the bounding box of the face (bX, bY, bW, bH) = face_utils.rect_to_bb(rect) # keep track of the highest scored face if (scores[i] > scoremax): scoremax = scores[i] best_face = frame[bY:bY + bH, bX:bX + bW] best_frame = self.framecounter #cv2.imshow("BEST_FACE", best_face) # if the q key was pressed, break from the loop key = cv2.waitKey(1) & 0xFF if key == ord("q"): break # Stop the frame queue vs.stop() if (best_frame == 0): #If no face was found best_face = 0 else: # Swap the R,B values best_face = cv2.cvtColor(best_face, cv2.COLOR_BGR2RGB) return best_face, best_frame
def face_detection_in_video(path2video, seconds_per_frame=1): print(path2video) detected_faces = [] face_embeddings = [] facecodes = [] print("[INFO] starting video file thread...") fvs = FileVideoStream(path2video) org_frame_rate = fvs.stream.get(5) width = fvs.stream.get(3) # float height = fvs.stream.get(4) # float no_of_frames_to_skip = org_frame_rate * seconds_per_frame no_of_frames_to_skip = no_of_frames_to_skip if no_of_frames_to_skip >= 1 else 1 print("[INFO] original frame rate: {}".format(org_frame_rate)) print("[INFO] no_of_frames_to_skip: {}".format(no_of_frames_to_skip)) fvs.start() # start the FPS timer fps = FPS().start() frame_no = 1 # loop over frames from the video file stream while fvs.more(): # grab the frame from the threaded video file stream, resize # it, and convert it to grayscale (while still retaining 3 # channels) frame = fvs.read() if frame is not None: if frame_no % math.floor(no_of_frames_to_skip) == 0: data = detect_faces_from_frame(frame, frame_no, width, height) detected_faces.extend(data["faces"]) face_embeddings.extend(data["face_embeddings"]) facecodes.extend(data["facecodes"]) frame_no += 1 # update the FPS counter fps.update() # stop the timer and display FPS information fps.stop() print("[INFO] elasped time: {:.2f}".format(fps.elapsed())) print("[INFO] approx. FPS: {:.2f}".format(fps.fps())) print("[INFO] total faces detected: {} ".format(len(detected_faces))) print("[INFO] total frames: {} ".format(frame_no)) return { "faces": detected_faces, "face_embeddings": face_embeddings, "facecodes": facecodes }
class CustomStream: def __init__(self, src=0, use_cv2=False): if use_cv2: self.obj = cv2.VideoCapture(src) elif src == 0: self.obj = WebcamVideoStream(src) elif src != 0: self.obj = FileVideoStream(src) def isOpened(self): if isinstance(self.obj, cv2.VideoCapture): return self.obj.isOpened() return self.obj.stream.isOpened() def start(self): self.obj.start() return self def update(self): self.obj.update() def read(self): if isinstance(self.obj, cv2.VideoCapture): return self.obj.read() return not self.obj.stopped, self.obj.read() def stop(self): self.obj.stop() if isinstance(self.obj, cv2.VideoCapture): self.obj.release() else: self.obj.stream.release() def set(self, propId, value): if isinstance(self.obj, cv2.VideoCapture): self.obj.set(propId, value) return self.obj.stream.set(propId, value) def get(self, propId): if isinstance(self.obj, cv2.VideoCapture): self.obj.get(propId) return return self.obj.stream.get(propId)
if args["movie"]: vs = FileVideoStream(args["movie"]) imageSrc = MOVIE elif args["image"]: vs = FileVideoStream(args["image"]) imageSrc = IMAGE else: vs = VideoStream(src=args["webcam"]) imageSrc = WEBCAM #logging.info(f'fps: {vs.get(cv2.CAP_PROP_FPS):%.1f}') time.sleep(1.0) if args["log"]: log_file = open(args["log"], "w") vs.start() fps = FPS().start() log_start = time.time() frameID = -1 eventID = 0 frame = None faces = [] # loop over frames from the video stream while True: # grab the frame from the threaded video file stream, resize # it, and convert it to grayscale # channels) frameID += 1 if imageSrc in [MOVIE,WEBCAM]:
class IP(object): def __init__(self): #self.cap = cv2.VideoCapture(1) self.fvs = FileVideoStream(1) # self.fvs.stream.set(3,FULL_WIDTH) # self.fvs.stream.set(4,FULL_HEIGHT) self.fvs.start() #self.fvs = FileVideoStream(0).start # self.cap.set(3,FULL_WIDTH) #3 - WIDTH # self.cap.set(4,FULL_HEIGHT) #4 - HEIGHT def get_image(self): #ret,image = self.cap.read() # print image image = self.fvs.read() i = 0 #image = np.dstack([image, image, image]) #print ("SHAPE : ",image.shape) image = imutils.resize(image, width=FULL_WIDTH) #,height=FULL_HEIGHT) print("SHAPE : ", image.shape) # while not np.size(image,0) == FULL_HEIGHT or not np.size(image,1) == FULL_WIDTH : # print ("trying",i) # print ("SHAPE : ",image.shape) # i += 1 # image = self.fvs.read() # #ret,image = self.cap.read() return image def perspective_transform(self, image, pts1, pts2): return cv2.warpPerspective(image, cv2.getPerspectiveTransform(pts1, pts2), (FINAL_WIDTH, FINAL_HEIGHT)) def rgb2gray(self, image): return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) def rgb2hsv(self, image): return cv2.cvtColor(image, cv2.COLOR_BGR2HSV) def threshold_image(self, image, threshold, max_val): return cv2.threshold(image, threshold, max_val, cv2.THRESH_BINARY) def display_image(self, image, window_name="Image"): cv2.imshow(window_name, image) if cv2.waitKey(1) == ord('q'): cv2.destroyAllWindows() self.fvs.stop() return 0 return 1 def find_contours(self, image): major, _, _ = cv2.__version__.split('.') if major == '3': _, contour, hierarchy = cv2.findContours(image, cv2.RETR_TREE, 2) else: contour, hierarchy = cv2.findContours(image, cv2.RETR_TREE, 2) return contour, hierarchy def find_area(self, contour): return cv2.contourArea(contour) def find_moments(self, contour): return cv2.moments(contour) def crop_image(self, image, center, amount): #print int(center[1])-amount,int(center[0])-amount #print int(center[1])+amount,int(center[0])+amount if int(center[1]) - amount >= 0 and int(center[0]) - amount >= 0: if int(center[1]) + amount <= FINAL_HEIGHT and int( center[0]) + amount <= FINAL_WIDTH: img = image[(int(center[1]) - amount):(int(center[1]) + amount), (int(center[0]) - amount):(int(center[0]) + amount)] return img else: return -1 else: return -1 def get_hsv_mask(self, image, lower, upper): return cv2.inRange(image, lower, upper) def end_all(self): self.fvs.release() cv2.destroyAllWindows() def draw_grid(self, im2, x_grid_num, y_grid_num): #ret,frame = self.cap.read() row = [0 for i in range(18)] mat = np.zeros((12, 18), dtype=np.uint64) #for i in range(12): # mat.append([]) X = im2.shape[1] Y = im2.shape[0] start_x = 0 start_y = 0 end_x = X / 18 end_y = Y / 12 for i in range(18): for j in range(12): if i not in range(x_grid_num - 1, x_grid_num + 2) or j not in range( y_grid_num - 1, y_grid_num + 2): im2 = cv2.rectangle( im2, (start_x + (X / 18) * i, start_y + (Y / 12) * j), (end_x + (X / 18) * i, end_y + (Y / 12) * j), (0, 0, 255)) mat[j][i] = 0 else: im2 = cv2.rectangle( im2, (start_x + (X / 18) * i, start_y + (Y / 12) * j), (end_x + (X / 18) * i, end_y + (Y / 12) * j), (0, 0, 255), -1) mat[j][i] = 1 #print "HI", mat[j][i] ''' print "Printing mat..." for i in range(12): s = "" for j in range(18): s += str(mat[i][j]) + " " print s ''' MAT = np.copy(mat) #print "MAT.shape", MAT.shape return im2, MAT '''
class movement_direction: def __init__(self, video_source_info, user_roi): self.source_info = video_source_info self.source = None if self.source_info == '0' or self.source_info == '1': self.source = 'Camera' elif isinstance(self.source_info, str) and Path( self.source_info).exists() and Path(sys.argv[1]).is_file(): self.source = self.source_info self._is_valid = not (self.source is None) self.frame_count = 0 self.prev_frame = None self.prev_angle = None self.current_angle = None self.angle_estimate_available = False self.angle_posts = dict(Right=75, Left=120) self.angle_diff_threshold = 7 self.current_state = State.eUnknown self.prev_state = self.current_state self.logger = get_logger() self.angle_states = {} self.angle_states[State.eRight] = 'Right' self.angle_states[State.eLeft] = 'Left' self.angle_states[State.eSame] = 'Straight' self.angle_states[State.eUnknown] = 'Unknown' ''' Initialize Capture and set up region of interest ''' if self.source == 'Camera': self.cap = WebcamVideoStream(src=int(self.source_info)) else: self.cap = FileVideoStream(self.source_info) self.cap.start() frame = self.cap.read() self.prev_frame = frame.copy() shape = self.prev_frame.shape time.sleep(2) (self.source_height, self.source_width) = self.prev_frame.shape[:2] self._is_loaded = True self.logger.info('Source is ' + self.source) video_roi = user_roi if self.source == 'Camera': camera_roi = dict(row_low=0, row_high=self.source_height - 1, column_low=0, column_high=self.source_width - 1) video_roi = camera_roi self.logger.info(video_roi) self.row_range = (video_roi['row_low'], video_roi['row_high']) self.column_range = (video_roi['column_low'], video_roi['column_high']) self.settings = initialize_settings_from_video_roi(video_roi) self.width = video_roi['column_high'] - video_roi['column_low'] self.height = video_roi['row_high'] - video_roi['row_low'] assert (self.width <= self.source_width) assert (self.height <= self.source_height) self.logger.info((self.source_width, self.source_height)) ''' Initialize tracking parameters ''' self.feature_params = self.settings['feature_params'] self.lk_params = self.settings['lk_params'] self.max_dist = self.settings['max_distance'] self.prev_frame = None self.keypoint_dist = 0 self.min_features = self.settings['min_features'] self.old_points = [] self.new_points = [] self.keypoints = [] self.display = None self.debug = False self.direction = [] self.avg_angle = None self.show_vectors = False self.show_axis = False def is_loaded(self): return self._is_loaded def is_valid(self): return self._is_valid def run(self): frame = self.prev_frame.copy() self.prev_frame = self.prepare_frame(frame) self.logger.info(('frame: ', self.frame_count)) self.frame_count = self.frame_count + 1 cv.namedWindow('Frame', cv.WINDOW_NORMAL) while self.cap.running(): captured_frame = self.cap.read() if not (captured_frame is None): self.frame_count = self.frame_count + 1 frame = self.prepare_frame(captured_frame) assert (not (self.prev_frame is None)) self.update_features() self.get_flow(frame) self.prev_frame = frame.copy() # self.draw_tracks( self.keypoints, self.new_points) cv.imshow("Frame", self.display) def prepare_frame(self, frame): frame = frame[self.row_range[0]:self.row_range[1], self.column_range[0]:self.column_range[1]] self.display = frame.copy() frame = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) return frame def get_features(self): self.keypoint_dist = 0 # collect features on the prev frame and compute its geometric median self.old_points = cv.goodFeaturesToTrack(self.prev_frame, mask=None, **self.feature_params) self.keypoints = np.copy(self.old_points) def update_features(self): # if moved too much re create features on the prev frame if self.keypoint_dist > self.max_dist: self.get_features() def set_state(_instant_angle): if _instant_angle <= self.angle_posts['Right']: self.current_state = State.eRight elif _instant_angle >= self.angle_posts['Left']: self.current_state = State.eLeft else: self.current_state = State.eSame if self.debug: self.logger.debug('max distance passed: reset ') avg_angle = self.measure_tracks(self.keypoints, self.new_points) avg_angle = math.degrees(avg_angle) % 360 self.direction.append(avg_angle) instant_angle = int(np.average(self.direction)) if self.prev_angle is None: self.prev_angle = instant_angle self.prev_state = State.eUnknown self.current_angle = instant_angle diff = self.current_angle - self.prev_angle ok = diff < self.angle_diff_threshold if ok and self.current_state == self.prev_state: self.current_state = State.eSame else: set_state(instant_angle) self.prev_angle = self.current_angle self.prev_state = self.current_state ## determine current direction: ## difference = current - prev ## if difference < 0 threshold and current is not Unknow ==> Straight ## if prev != current ==> current self.logger.info(('frame, direction:', self.frame_count, instant_angle, self.current_state)) # if few new points create features on the prev frame elif len(self.new_points) < self.min_features: self.get_features() if self.debug: self.logger.debug('copied old points to keypoints ') else: # check number of features in each quadrant to ensure a good distribution of features across entire image nw = ne = sw = se = 0 w = self.width h = self.height for x, y in self.new_points: if x > w // 2: if y > h // 2: se += 1 else: ne += 1 else: if y > h // 2: sw += 1 else: nw += 1 self.num_features = min((nw, ne)) if self.num_features < self.min_features // 4: self.get_features() # if self.debug: self.logger.debug('too few features reset ') else: # just copy new points to old points dim = np.shape(self.new_points) self.old_points = np.reshape(self.new_points, (-1, 1, 2)) if self.debug: self.logger.debug('ok') def get_flow(self, frame): self.new_points, self.status, self.error = cv.calcOpticalFlowPyrLK( self.prev_frame, frame, self.old_points, None, **self.lk_params) self.keypoints = np.reshape( self.keypoints, (-1, 1, 2)) # TODO find out why this is necessary?! self.old_points = self.old_points[self.status == 1] self.new_points = self.new_points[self.status == 1] self.keypoints = self.keypoints[self.status == 1] self.keypoint_dist += self.get_mean_distance_2d( self.old_points, self.new_points) def get_mean_distance_2d(self, features1, features2): num_features = min((len(features1), len(features2))) features1 = np.reshape(features1, (num_features, 2)) features2 = np.reshape(features2, (num_features, 2)) features = zip(features1, features2) n = 0 dist = 0 for f1, f2 in features: dx = f1[0] - f2[0] dy = f1[1] - f2[1] d = math.sqrt(dx**2 + dy**2) dist += d n += 1 if n == 0: return 0 dist /= n return dist def draw_direction(self): if self.prev_state != State.eUnknown and self.current_state != State.eUnknown: direction = self.angle_states[self.current_state] cv.putText(self.display, direction, (self.width // 2, self.height // 2), cv.FONT_HERSHEY_DUPLEX, 2, (225, 0, 0), 7) def draw_tracks(self, points1, points2): if self.show_vectors: for i, (new, old) in enumerate(zip(points1, points2)): a, b = new.ravel() c, d = old.ravel() cl = (0, 255, 0) if a < self.width / 2: cl = (255, 0, 0) frame = cv.line(self.display, (c, d), (a, b), cl, 1) cv.circle(self.display, (a, b), 5, cl, 0, 3) self.draw_direction() cv.putText(self.display, str(self.frame_count), (self.width // 16, (15 * self.height) // 16), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) if self.show_axis: cv.line(self.display, (0, self.height // 2), (self.width, self.height // 2), (255, 0, 0), 1) cv.line(self.display, (self.width // 2, 0), (self.width // 2, self.height), (255, 0, 0), 1) def measure_tracks(self, points1, points2): angles = [] for i, (new, old) in enumerate(zip(points1, points2)): a, b = new.ravel() c, d = old.ravel() line = [c, d, a, b] angle = get_line_angle(line) angles.append(angle) angles = np.asanyarray(angles) mean_angle = np.arctan2(np.sin(angles).mean(), np.cos(angles).mean()) if mean_angle < 0: mean_angle = math.pi + math.pi + mean_angle return mean_angle
class Moviebarcode: """ Generate moviebarcode from an input video """ # TODO: Optimize the resize process and rescale 1K+ size videos to 480 def __init__( self, video_path=None, verbose=True, # optimize=True # TODO: Work on to optimize the moviebarcode generation barcode_width=1): self.video_path = video_path self.verbose = verbose self.generate_features = True # Generate input video specs such as fps, width, and height self.video = None self.fvs = None # FVS object for accelerating video stream to threads self.frame_count = 0 self.video_fps = 0 # We get FPS value from OpenCV Flags self.video_width = None # We get width value from OpenCV Flags self.video_height = None # We get height value from OpenCV Flags self.frame_avgs = [] # Raw pixel values of frame pixel averages self.elapsed_time = 0.0 # Accelerated video queueing time self.processed_frame_count = 0 # How many frames of video is processed in threaded process self.processed_video_width = 0 # Final version of each frame processed width value self.processed_video_height = 0 # Final version of each frame processed height value self.barcode_frame_count = 0 # don't want to visualize all frames, change barcode_frequency self.barcode_frequency = None self.fps = 0 # We get this value from imutils' fps() function self.barcode = None # Keep barcode object for further use self.barcode_height = 224 # Set barcode image height self.barcode_width = barcode_width def if_exist(self): """ For provided video path, check if it exists :return: The result of if the video exists """ if not os.path.exists(self.video_path): logging.info(msg=f"{self.video_path} doesn't exist!") return False return True def load_video(self): """ Accelerated video stream with multi-threading support :return: """ if self.verbose: logging.info(msg=f"{self.video_path} is loading ..") if self.if_exist(): self.video = FileVideoStream(self.video_path) def get_frames_avgs(self): """ Calculate frames' average pixel values for all frames of loaded video :return: build the list for average pixel values """ if self.video is None: self.load_video() # Start video stream if self.verbose: logging.debug(msg=f"Video is being started ..") self.fvs = self.video.start() fps = FPS().start() # Generate video features before processing if self.generate_features: self.frame_count = int( self.video.stream.get(cv2.CAP_PROP_FRAME_COUNT)) self.video_fps = int(self.video.stream.get(cv2.CAP_PROP_FPS)) self.video_width = int( self.video.stream.get(cv2.CAP_PROP_FRAME_WIDTH)) self.video_height = int( self.video.stream.get(cv2.CAP_PROP_FRAME_HEIGHT)) if self.verbose: logging.info(msg=f"[Video] frame count: {self.frame_count}") logging.info(msg=f"[Video] FPS: {self.video_fps}") logging.info( msg= f"[Video] Size: {self.video_width} x {self.video_height}") # Loop frames in a while if self.verbose: logging.info( msg=f"Video frame average pixel values are being calculated .." ) while self.fvs.more(): frame = self.fvs.read() self.frame_avgs.append(cv2.mean(frame)[:3]) fps.update() fps.stop() self.fvs.stop() # Generate video features after processing if self.generate_features: self.fps = int(fps.fps()) self.elapsed_time = fps.elapsed() self.processed_frame_count = fps.elapsed() * fps.fps() self.processed_video_width = int(self.video_width) self.processed_video_height = int(self.video_height) if self.verbose: logging.info( msg=f"[Processed] frame count: {self.frame_count}") logging.info(msg=f"[Processed] FPS: {self.fps}") logging.info( msg= f"[Processed] Size: {self.processed_video_width} x {self.processed_video_height}" ) def get_barcode_frame_count(self): """ Get the total number of frames for input video :return: """ if self.barcode is not None: self.barcode_frame_count = self.barcode.shape[0] if self.verbose: logging.info( msg= f"Total number of frames in barcode: {self.barcode_frame_count}" ) def barcode_frame_sequence(self): """ On moviebarcode generation, the sequence of frames average can be set :return: Setting the frequency with the user input """ # per frame if self.barcode_frequency is None: self.barcode_frequency = 1 # per second elif self.barcode_frequency == "second": self.barcode_frequency = self.fps # per n-frame elif "frames" in self.barcode_frequency: freq = self.barcode_frequency.split("frames")[0] if freq != int(freq): self.barcode_frequency = freq # per n-second elif "seconds" in self.barcode_frequency: freq = self.barcode_frequency.split("seconds")[0] if freq != int(freq): self.barcode_frequency = self.fps * freq # per minute elif self.barcode_frequency == "minute": self.barcode_frequency = self.fps * 60 # per n-minute elif "minutes" in self.barcode_frequency: freq = self.barcode_frequency.split("minutes")[0] if freq != int(freq): self.barcode_frequency = self.fps * freq * 60 def generate(self, colors=None): """ Moviebarcode generation function. This function has options, if a list of pixel values are provided, the moviebarcode image can be generated :param colors: A list or list-like object that contains pixel values Default value is None :return: RGB image of generated moviebarcode """ if colors is None: # generate frames average self.get_frames_avgs() else: self.frame_avgs = colors # TODO: Add barcode_frequency option to this assignment self.barcode = np.zeros((self.barcode_height, len(self.frame_avgs), 3), dtype="uint8") for (i, avg) in enumerate(np.array(self.frame_avgs)): cv2.rectangle( self.barcode, (int(i * self.barcode_width), 0), (int(i + 1) * self.barcode_width, self.barcode_height), (int(avg[0]), int(avg[1]), int(avg[2])), 3) if self.verbose: logging.info(msg="Barcode is being calculated ...") # TODO: Make the barcode name dynamic to input video id def make_image(self, file_name="output/moviebarcode.png"): """ Create the PNG RGB image for the barcode object. :param file_name: The filename to name and record the image. The default value is "output/moviebarcode.png" :return: Write RGB image to a PNG file. """ # save as image if self.barcode is not None: cv2.imwrite(filename=file_name, img=self.barcode) else: self.generate() cv2.imwrite(filename=file_name, img=self.barcode) def display_barcode(self): """ visualize the moviebarcode image with OpenCV :return: """ if self.verbose: logging.info(msg="Barcode is displayed with OpenCV") cv2.imshow("Barcode", self.barcode) cv2.waitKey(0) # TODO: make json file name dynamic to input video id def write2json(self, file_name="output/barcode.json"): """ Write moviebarcode pixel values to a json file :param file_name: Name the json file to record to the disk The default value is "output/barcode.json" :return: """ # Since our values are OpenCV image object which is BGR imager, convert the moviebarcode array to RGB b = np.array(self.frame_avgs)[:, 0].reshape(-1, 1) g = np.array(self.frame_avgs)[:, 1].reshape(-1, 1) r = np.array(self.frame_avgs)[:, 2].reshape(-1, 1) self.frame_avgs = np.concatenate([r, g, b], axis=1) with open(file_name, "w") as json_file: json_file.write(json.dumps(self.frame_avgs.tolist())) if self.verbose: logging.info(msg="Barcode is being written to json file!")
def detect(self, video_path, output_path=None, skip_secs=0, real_show=False, show_fps=True, ): logging.info("Detect video: " + str(video_path)) fvs = FileVideoStream(video_path, transform=_transform) vid = fvs.stream if not vid.isOpened(): raise IOError("Couldn't open webcam or video") video_FourCC = int(vid.get(cv2.CAP_PROP_FOURCC)) video_fps = int(vid.get(cv2.CAP_PROP_FPS)) video_size = (int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)), int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))) total_frames = int(vid.get(cv2.CAP_PROP_FRAME_COUNT)) skip_frames = int(skip_secs) * video_fps if skip_secs > total_frames: print("Can't skip over total video!") else: vid.set(cv2.CAP_PROP_POS_FRAMES, skip_frames) isOutput = True if output_path is not None else False if isOutput: logging.info(f"Output Type: {output_path}, {video_FourCC}, {video_fps}, {video_size}") out = cv2.VideoWriter(output_path, self.fourcc, video_fps, video_size) if real_show: cv2.namedWindow("result", cv2.WINDOW_NORMAL) cv2.resizeWindow("result", 960, 540) pass fvs.start() accum_time = 0 curr_fps = 0 fps = "FPS: ??" prev_time = time.time() hold_detections = None actions = [] frames = 0 try: while fvs.more(): frame = fvs.read() #frame = cv2.resize(frame, (608, 608), interpolation=cv2.INTER_LINEAR) # frame = cv2.hconcat([frame, frame, frame]) if frame is None: break # BGR -> RGB if frames % self.skip_frames == 0: detections = self.image_detector.detect(frame) if detections is not None and self.tracker is not None: boxs = p1p2Toxywh(detections[:, :4]) class_ids = detections[:, -1] confidences = detections[:, 4] if self.class_mask is not None: mask_set = [class_ids == mask_id for mask_id in self.class_mask] mask = reduce(lambda a, b: a | b, mask_set) boxs = boxs[mask] confidences = confidences[mask] class_ids = class_ids[mask] detections = self.tracker.update(boxs.float(), confidences, frame, class_ids) if self.action_id is not None: actions = self.action_id.update(detections) else: actions = [] hold_detections = detections frames = 0 else: actions = [] if hold_detections is not None: if self.tracker is not None: image, plane, plane_mask = self.label_drawer.draw_labels_by_trackers(frame, hold_detections, only_rect=False) else: image, plane, plane_mask = self.label_drawer.draw_labels(frame, hold_detections, only_rect=False) else: image, plane, plane_mask = frame, None, None # RGB -> BGR result = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) frames += 1 curr_time = time.time() exec_time = curr_time - prev_time prev_time = curr_time accum_time += exec_time curr_fps += 1 if accum_time > 1: accum_time = accum_time - 1 fps = "FPS: " + str(curr_fps) curr_fps = 0 print(fps) if show_fps: cv2.putText(result, text=fps, org=(3, 15), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.6, color=(255, 0, 0), thickness=self.thickness) # Show the video in real time. if real_show: cv2.imshow("result", result) if isOutput: out.write(result) yield result, hold_detections, actions if real_show: if cv2.waitKey(1) & 0xFF == ord('q'): break finally: if isOutput: out.release() if real_show: cv2.destroyAllWindows()
def start(self): thread = Thread(target=self.process, args=(), name='BallFinderProcess', daemon=True) thread.start() def stop(self): self.stopped = True if __name__ == "__main__": video_file = "data/VID_20201224_134735.mp4" video = FileVideoStream(video_file) video.start() output_video = cv.VideoWriter('output.avi', cv.VideoWriter_fourcc(*"MJPG"), 20.0, (320, 568)) finder = BallFinder(video) try: finder.start() while True: ball_found, ball_center, frame, ball_greyscale, hsv_mask, ball_mask = finder.get_frame( ) if frame is not None: if ball_found: print('Ball found at ' + str(ball_center)) cv.circle(frame, ball_center, 4, (255, 0, 0), -1) else:
def main(video, shape_predictor): def eye_aspect_ratio(eye): # compute the euclidean distances between the two sets of # vertical eye landmarks (x, y)-coordinates A = dist.euclidean(eye[1], eye[5]) B = dist.euclidean(eye[2], eye[4]) # compute the euclidean distance between the horizontal # eye landmark (x, y)-coordinates C = dist.euclidean(eye[0], eye[3]) # compute the eye aspect ratio ear = (A + B) / (2.0 * C) # return the eye aspect ratio return ear # construct the argument parse and parse the arguments # ap = argparse.ArgumentParser() # ap.add_argument("-p", "--shape-predictor", required=True, # help="path to facial landmark predictor") # ap.add_argument("-v", "--video", type=str, default="", # help="path to input video file") ap = argparse.ArgumentParser() ap.add_argument(shape_predictor, nargs=1) ap.add_argument(video, nargs=1) args = vars(ap.parse_args()) # define two constants, one for the eye aspect ratio to indicate # blink and then a second constant for the number of consecutive # frames the eye must be below the threshold EYE_AR_THRESH = 0.3 EYE_AR_CONSEC_FRAMES = 3 # initialize the frame counters and the total number of blinks COUNTER = 0 global TOTAL TOTAL = 0 # initialize dlib's face detector (HOG-based) and then create # the facial landmark predictor #print("[INFO] loading facial landmark predictor...") detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor(shape_predictor) # grab the indexes of the facial landmarks for the left and # right eye, respectively (lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"] (rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"] # start the video stream thread #print("[INFO] starting video stream thread...") cap = cv2.VideoCapture(video) vs = FileVideoStream(video) vs.start() fileStream = True # vs = VideoStream(src=0).start() # vs = VideoStream(usePiCamera=True).start() # fileStream = False time.sleep(1.0) # loop over frames from the video stream while True: # if this is a file video stream, then we need to check if # there any more frames left in the buffer to process if fileStream and not vs.more(): break # grab the frame from the threaded video file stream, resize # it, and convert it to grayscale # channels) frame = vs.read() if np.shape(frame) != (): frame = imutils.resize(frame, width=450) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # detect faces in the grayscale frame rects = detector(gray, 0) # loop over the face detections for rect in rects: # determine the facial landmarks for the face region, then # convert the facial landmark (x, y)-coordinates to a NumPy # array shape = predictor(gray, rect) shape = face_utils.shape_to_np(shape) # extract the left and right eye coordinates, then use the # coordinates to compute the eye aspect ratio for both eyes leftEye = shape[lStart:lEnd] rightEye = shape[rStart:rEnd] leftEAR = eye_aspect_ratio(leftEye) rightEAR = eye_aspect_ratio(rightEye) # average the eye aspect ratio together for both eyes ear = (leftEAR + rightEAR) / 2.0 # compute the convex hull for the left and right eye, then # visualize each of the eyes leftEyeHull = cv2.convexHull(leftEye) rightEyeHull = cv2.convexHull(rightEye) cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1) cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1) # check to see if the eye aspect ratio is below the blink # threshold, and if so, increment the blink frame counter if ear < EYE_AR_THRESH: COUNTER += 1 # otherwise, the eye aspect ratio is not below the blink # threshold else: # if the eyes were closed for a sufficient number of # then increment the total number of blinks if COUNTER >= EYE_AR_CONSEC_FRAMES: TOTAL += 1 # reset the eye frame counter COUNTER = 0 # draw the total number of blinks on the frame along with # the computed eye aspect ratio for the frame #cv2.putText(frame, "Blinks: {}".format(TOTAL), (10, 30), #cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) #cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30), #cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) # show the frame #if np.shape(frame) != (): #cv2.imshow("Frame", frame) key = cv2.waitKey(1) & 0xFF # if the `q` key was pressed, break from the loop if key == ord("q"): break # output final results # if "FAKE" in str(video): # print("Fake " + str(TOTAL)) # else: # print("Real " + str(TOTAL)) print(str(TOTAL)) # do a bit of cleanup cv2.destroyAllWindows() vs.stop()