123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- # Collect dataset
- # Import required modules
- import cv2
- import numpy as np
- import depthai as dai
- import os
- import blobconverter
- # Define directory paths
- real_face_dir = os.path.join("dataset", "real")
- os.makedirs(real_face_dir, exist_ok=True)
- spoofed_face_dir = os.path.join("dataset", "spoofed")
- os.makedirs(spoofed_face_dir, exist_ok=True)
- # Define Detection NN model name and input size
- DET_INPUT_SIZE = (300, 300)
- FACE_MODEL_NAME = "face-detection-retail-0004"
- ZOO_TYPE = "depthai"
- # Start defining a pipeline
- pipeline = dai.Pipeline()
- # Define a source - two mono (grayscale) cameras
- left = pipeline.createMonoCamera()
- left.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
- left.setBoardSocket(dai.CameraBoardSocket.LEFT)
- right = pipeline.createMonoCamera()
- right.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
- right.setBoardSocket(dai.CameraBoardSocket.RIGHT)
- # Create a node that will produce the depth map (using disparity output as it's easier to visualize depth this way)
- depth = pipeline.createStereoDepth()
- depth.setConfidenceThreshold(200)
- depth.setOutputRectified(True) # The rectified streams are horizontally mirrored by default
- depth.setRectifyEdgeFillColor(0) # Black, to better see the cutout
- depth.setExtendedDisparity(True) # For better close range depth perception
- # Convert model from OMZ to blob
- if FACE_MODEL_NAME is not None:
- blob_path = blobconverter.from_zoo(
- name=FACE_MODEL_NAME,
- shaves=6,
- zoo_type=ZOO_TYPE
- )
- # Define face detection NN node
- faceDetNn = pipeline.createMobileNetDetectionNetwork()
- faceDetNn.setConfidenceThreshold(0.75)
- faceDetNn.setBlobPath(blob_path)
- # Define face detection input config
- faceDetManip = pipeline.createImageManip()
- faceDetManip.initialConfig.setResize(DET_INPUT_SIZE[0], DET_INPUT_SIZE[1])
- faceDetManip.initialConfig.setKeepAspectRatio(False)
- faceDetManip.initialConfig.setFrameType(dai.RawImgFrame.Type.RGB888p)
- # Linking
- depth.rectifiedRight.link(faceDetManip.inputImage)
- faceDetManip.out.link(faceDetNn.input)
- # Create face detection output
- xOutDet = pipeline.createXLinkOut()
- xOutDet.setStreamName('det_out')
- faceDetNn.out.link(xOutDet.input)
- # Options: MEDIAN_OFF, KERNEL_3x3, KERNEL_5x5, KERNEL_7x7 (default)
- median = dai.StereoDepthProperties.MedianFilter.KERNEL_7x7 # For depth filtering
- depth.setMedianFilter(median)
- left.out.link(depth.left)
- right.out.link(depth.right)
- # Create left output
- xout_right = pipeline.createXLinkOut()
- xout_right.setStreamName("right")
- depth.rectifiedRight.link(xout_right.input)
- # Create depth output
- xout = pipeline.createXLinkOut()
- xout.setStreamName("disparity")
- depth.disparity.link(xout.input)
- # Initialize wlsFilter
- # wlsFilter = cv2.ximgproc.createDisparityWLSFilterGeneric(False)
- # wlsFilter.setLambda(8000)
- # wlsFilter.setSigmaColor(1.5)
- # Frame count
- count = 0
- # Set the number of frames to skip
- SKIP_FRAMES = 10
- real_count = 0
- spoofed_count = 0
- save_real = False
- save_spoofed = False
- # Pipeline defined, now the device is connected to
- with dai.Device(pipeline) as device:
- # Start pipeline
- device.startPipeline()
- # Output queue will be used to get the right camera frames from the outputs defined above
- q_right = device.getOutputQueue(name="right", maxSize=4, blocking=False)
- # Output queue will be used to get the disparity frames from the outputs defined above
- q_depth = device.getOutputQueue(name="disparity", maxSize=4, blocking=False)
- # Output queue will be used to get nn detection data from the video frames.
- qDet = device.getOutputQueue(name="det_out", maxSize=1, blocking=False)
- while True:
- # Get right camera frame
- in_right = q_right.get()
- r_frame = in_right.getFrame()
- # r_frame = cv2.flip(r_frame, flipCode=1)
- # cv2.imshow("right", r_frame)
- # Get depth frame
- in_depth = q_depth.get() # blocking call, will wait until a new data has arrived
- depth_frame = in_depth.getFrame()
- depth_frame = np.ascontiguousarray(depth_frame)
- depth_frame = cv2.bitwise_not(depth_frame)
- depth_frame = cv2.flip(depth_frame, flipCode=1)
- # Apply wls filter
- # cv2.imshow("without wls filter", cv2.applyColorMap(depth_frame, cv2.COLORMAP_JET))
- # depth_frame = wlsFilter.filter(depth_frame, r_frame)
- # frame is transformed, the color map will be applied to highlight the depth info
- depth_frame_cmap = cv2.applyColorMap(depth_frame, cv2.COLORMAP_JET)
- # frame is ready to be shown
- cv2.imshow("disparity", depth_frame_cmap)
- # Retrieve 'bgr' (opencv format) frame from gray scale
- frame = cv2.cvtColor(r_frame, cv2.COLOR_GRAY2RGB)
- img_h, img_w = frame.shape[0:2]
- bbox = None
- inDet = qDet.tryGet()
- if inDet is not None:
- detections = inDet.detections
- # for detection in detections:
- if len(detections) is not 0:
- detection = detections[0]
- # print(detection.confidence)
- x = int(detection.xmin * img_w)
- y = int(detection.ymin * img_h)
- w = int(detection.xmax * img_w - detection.xmin * img_w)
- h = int(detection.ymax * img_h - detection.ymin * img_h)
- bbox = (x, y, w, h)
- # Set default status
- status_color = (0, 0, 255)
- # Check if a face was detected in the frame
- if bbox:
- # Get face roi from right and depth frames
- face_d = depth_frame[max(0, bbox[1]):bbox[1] + bbox[3], max(0, bbox[0]):bbox[0] + bbox[2]]
- face_r = r_frame[max(0, bbox[1]):bbox[1] + bbox[3], max(0, bbox[0]):bbox[0] + bbox[2]]
- cv2.imshow("face_roi", face_d)
- # Display bounding box
- cv2.rectangle(frame, bbox, status_color, 2)
- # Create background for showing details
- cv2.rectangle(frame, (5, 5, 225, 100), (50, 0, 0), -1)
- # Display instructions on the frame
- cv2.putText(frame, 'Press F to save real Face.', (10, 45), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 255, 255))
- cv2.putText(frame, 'Press S to save spoofed Face.', (10, 65), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 255, 255))
- cv2.putText(frame, 'Press Q to Quit.', (10, 85), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 255, 255))
- # Capture the key pressed
- key_pressed = cv2.waitKey(1) & 0xff
- # Save face depth map is f was pressed
- if key_pressed == ord('f'):
- save_real = not save_real
- save_spoofed = False
- # Save face depth map is s was pressed
- elif key_pressed == ord('s'):
- save_spoofed = not save_spoofed
- save_real = False
- # Stop the program if q was pressed
- elif key_pressed == ord('q'):
- break
- if bbox:
- if face_d is not None and save_real:
- real_count += 1
- filename = f"real_{real_count}.jpg"
- cv2.imwrite(os.path.join(real_face_dir, filename), face_d)
- # Display authentication status on the frame
- cv2.putText(frame, f"Saving real face: {real_count}", (20, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255))
- elif face_d is not None and save_spoofed:
- spoofed_count += 1
- filename = f"spoofed_{spoofed_count}.jpg"
- cv2.imwrite(os.path.join(spoofed_face_dir, filename), face_d)
- # Display authentication status on the frame
- cv2.putText(frame, f"Saving spoofed face: {spoofed_count}", (20, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255))
- else:
- cv2.putText(frame, "Face not saved", (20, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255))
- # Display the final frame
- cv2.imshow("Data collection Cam", frame)
- count += 1
- cv2.destroyAllWindows()
|