Beispiel #1
0
class Kinect:

    # Kinects's intrinsic parameters based on v2 hardware (estimated).
    CameraParams = {
        "cx": 254.878,
        "cy": 205.395,
        "fx": 365.456,
        "fy": 365.456,
        "k1": 0.0905474,
        "k2": -0.26819,
        "k3": 0.0950862,
        "p1": 0.0,
        "p2": 0.0,
    }

    # Kinect's physical orientation in the real world.
    CameraPosition = {
        "x": -4,  # distance of kinect sensor from wall.
        "y":
        0,  # actual position in meters of kinect sensor relative to the viewport's center.
        "z": 0,  # height in meters of actual kinect sensor from the floor.
        "roll":
        0,  # angle in degrees of sensor's roll (used for INU input - trig function for this is commented out by default).
        "azimuth": 0,  # sensor's yaw angle in degrees.
        "elevation": 0,  # sensor's pitch angle in degrees.
    }

    DEPTH_SHAPE = (424, 512)
    N_DEPTH_PIXELS = DEPTH_SHAPE[0] * DEPTH_SHAPE[1]
    COLOR_SHAPE = (360, 640, 3)

    def __init__(self,
                 frametypes=FrameType.Color | FrameType.Depth,
                 registration=True):

        # open the device and start the listener
        num_devices = fn.enumerateDevices()
        assert num_devices > 0, "Couldn't find any devices"
        serial = fn.getDeviceSerialNumber(0)
        self.device = fn.openDevice(serial, pipeline=pipeline)
        self.listener = SyncMultiFrameListener(frametypes)
        self.device.setColorFrameListener(self.listener)
        self.device.setIrAndDepthFrameListener(self.listener)
        self.device.start()

        # NOTE: must be called after device.start()
        if registration:
            ir = self.device.getIrCameraParams()
            color = self.device.getColorCameraParams()
            self.registration = Registration(ir, color)

            # create these here so we don't have to every time we call update()
            self.undistorted = Frame(512, 424, 4)
            self.registered = Frame(512, 424, 4)

        # which kinds of frames are we going to be reading?
        # will be true or false
        self.need_color = frametypes & FrameType.Color
        self.need_depth = frametypes & FrameType.Depth
        self.need_ir = frametypes & FrameType.Ir

        # initialize our frames
        self.frames = {}

        # ensure that we shut down smoothly
        atexit.register(self.close)

    def hasNextFrame(self):
        return True

    def close(self):
        self.device.stop()
        self.device.close()

    def get_frames(self):
        self._update()
        return self.frames

    def _update(self):
        if self.listener.hasNewFrame() or len(self.frames) == 0:
            _frames = self.listener.waitForNewFrame()

            if self.need_color:
                # get the data, then throw out the 4th channel
                color = _frames['color'].asarray()[:, :, :3]
                h, w, d = self.COLOR_SHAPE
                color = cv2.resize(color, (w, h))
                self.frames['color'] = color

                # print('color:' +str(_frames['color'].timestamp))
            if self.need_depth:
                depth = _frames['depth'].asarray() / 4500
                self.frames['depth'] = depth

                # print('depth:' + str(_frames['depth'].timestamp))
            if self.need_ir:
                ir = _frames['ir'].asarray() / 65535.
                self.frames['ir'] = ir

                # print('ir:' + str(_frames['ir'].timestamp))

            # register the franes if we need to
            if self.registration and self.need_color and self.need_color:
                c, d, u, r = _frames['color'], _frames[
                    'depth'], self.undistorted, self.registered
                self.registration.apply(c, d, u, r)
                self.frames['undistorted'] = self.undistorted.asarray(
                    np.float32)
                self.frames['registered'] = self.registered.asarray(np.uint8)

            # we NEED to explicitly deallocate the frames from the listener
            self.listener.release(_frames)

    def makePointCloud(self, undistorted, registered=None):

        # convert depth frame to point cloud
        pts = self.depthMatrixToPointCloudPos(undistorted)
        # # Kinect sensor real-world orientation compensation.
        pts = self.applyCameraMatrixOrientation(pts)

        # if supplied with registered color image, figure out color of each point
        if registered is not None:
            colors = self.registered2points(registered)
        else:
            # else default to white RBGA
            colors = (1.0, 1.0, 1.0, 1.0)
        pts = pts.astype(np.float32)
        return (pts, colors)

    def depthMatrixToPointCloudPos(self, z, scale=1000):
        # calculate the real-world xyz vertex coordinates from the raw depth data matrix.
        C, R = np.indices(z.shape)

        R = np.subtract(R, self.CameraParams['cx'])
        R = np.multiply(R, z)
        R = np.divide(R, self.CameraParams['fx'] * scale)

        C = np.subtract(C, self.CameraParams['cy'])
        C = np.multiply(C, z)
        C = np.divide(C, self.CameraParams['fy'] * scale)

        return np.column_stack((z.ravel() / scale, R.ravel(), -C.ravel()))

    def applyCameraMatrixOrientation(self, pt):
        # Kinect Sensor Orientation Compensation
        # bacically this is a vectorized version of applyCameraOrientation()
        # uses same trig to rotate a vertex around a gimbal.
        def rotatePoints(ax1, ax2, deg):
            # math to rotate vertexes around a center point on a plane.
            hyp = np.sqrt(
                pt[:, ax1]**2 + pt[:, ax2]**2
            )  # Get the length of the hypotenuse of the real-world coordinate from center of rotation, this is the radius!
            d_tan = np.arctan2(
                pt[:, ax2], pt[:, ax1]
            )  # Calculate the vertexes current angle (returns radians that go from -180 to 180)

            cur_angle = np.degrees(
                d_tan
            ) % 360  # Convert radians to degrees and use modulo to adjust range from 0 to 360.
            new_angle = np.radians(
                (cur_angle + deg) % 360
            )  # The new angle (in radians) of the vertexes after being rotated by the value of deg.

            pt[:, ax1] = hyp * np.cos(
                new_angle)  # Calculate the rotated coordinate for this axis.
            pt[:, ax2] = hyp * np.sin(
                new_angle)  # Calculate the rotated coordinate for this axis.

        #rotatePoints(1, 2, CameraPosition['roll']) #rotate on the Y&Z plane # Disabled because most tripods don't roll. If an Inertial Nav Unit is available this could be used)
        if self.CameraPosition['elevation'] != 0:
            rotatePoints(0, 2,
                         self.CameraPosition['elevation'])  #rotate on the X&Z
        if self.CameraPosition['azimuth'] != 0:
            rotatePoints(0, 1,
                         self.CameraPosition['azimuth'])  #rotate on the X&Y

        # Apply offsets for height and linear position of the sensor (from viewport's center)
        if any([
                self.CameraPosition['x'], self.CameraPosition['y'],
                self.CameraPosition['z']
        ]):
            pt[:] += np.float_([
                self.CameraPosition['x'], self.CameraPosition['y'],
                self.CameraPosition['z']
            ])

        return pt

    def registered2points(self, registered):
        # Format the color registration map from an 2D image of BGRA-pixels to a 1D list of RGB pixels
        colors = np.divide(registered, 255)  # values must be between 0.0 - 1.0
        colors = colors.reshape(
            colors.shape[0] * colors.shape[1],
            4)  # From: Rows X Cols X RGB -to- [[r,g,b],[r,g,b]...]
        colors = colors[:, :3:]  # remove alpha (fourth index) from BGRA to BGR
        colors = colors[..., ::-1]  #BGR to RGB

        return colors
Beispiel #2
0
device.setColorFrameListener(listener)
device.setIrAndDepthFrameListener(listener)

device.start()

# undistorted = Frame(512, 424, 4)
# registered = Frame(512, 424, 4)

start = time.time()

withDetection = False

# while time.time() < (start+5):
while True:
    frames = listener.waitForNewFrame()
    while listener.hasNewFrame():
        frames = listener.waitForNewFrame()

    color = frames["color"]
    depth = frames["depth"]

    colors = color.asarray()
    colors = cv2.cvtColor(colors, cv2.COLOR_RGBA2RGB)

    if withDetection:
        processImage(colors)

    colors = cv2.resize(colors, (WIDTH, HEIGHT))
    colors = cv2.flip(colors, 0)

    # depth8bit = ((numpy.clip(depth.asarray(), 1800, 2200)-1800)/400*256).astype("uint8")