Skip to content
No results
Purple hexagonal logo with white diamond-shaped center featuring geometric star pattern design suitable for corporate branding and digital applications
LIPS®Developer
Documentation
Back To LIPS
Purple hexagonal logo with white diamond-shaped center featuring geometric star pattern design suitable for corporate branding and digital applications
LIPS®Developer
Documentation
Back To LIPS

WELCOME

7
  • LIPS® Documentation Overview
  • About 3D Depth Cameras
  • Depth Image
  • Understanding Depth
  • An Ideal Depth Camera
  • LIPSedge™ AE Series Camera Selection Guide
  • Frequently Asked Questions

LIPSedge™ SDK 1.x

30
  • Introduction to LIPSedge™ SDK 1.x
    • LIPSedge™ SDK 1.x
    • Benefits from LIPSedge™ SDK implementation
    • LIPSedge™ SDK 1.x Installation Architecture
    • How to identify each camera SDK
  • New Features for v1.02
    • New Features for v1.02
    • Installing and identifying packages on Windows
    • Saving Captures and Videos with the DepthViewer
    • Saving Point Cloud with PointCloudViewer
    • Live On-Screen displaying Depth, FPS
    • Live On-Screen displaying XYZ parameters in RawfileViewer
    • Distance measurement on-screen from point-to-point
    • Mouse Pointer Change
    • LIPSedge™ AE and S series Colormap new feature addition
    • Simple naming for LIPSedge™ SDK Tools
    • Importing parameters from .json files for LIPSedge™ AE and S series
  • LIPSedge™ SDK v1.02 Tools
    • LIPSedge™ SDK v1.02 Tools
    • DepthViewer
    • PointCloudViewer
    • CameraParameterViewer
    • CameraCenterViewer
    • CameraEventListener
    • CameraPowerTest
    • LensModeSelector
    • LIPSImuReader
    • CameraSimpleViewer
    • RawFileViewer
  • Tutorial and deployment
    • Tutorials
    • Development and Deployment on arm64
  • Features Articles
    • Features Articles
    • LIPSedge™ SDK Persistent Connection for PoE and USB

DOCUMENTS, INSTALLATION & SETUP

121
  • LIPSedge™ AE400 / AE450
    • LIPSedge™ AE400 / AE450 User Guide
      • LIPSedge™ AE400 / AE450
      • User Guide
      • Previous Releases (Archive)
    • LIPSedge™ AE400 / AE450 SDK Release
      • SDK Release
      • Previous Releases (Archive)
    • LIPSedge™ AE400 / AE450 Installation
      • Installation
      • Linux
      • Windows
      • ROS Wrapper
      • NVIDIA ISAAC Wrapper
      • Persistent Connection
    • LIPSedge™ AE400 / AE450 Complementary Documents
      • Certifications Documents
      • STEP files for CAD Use
      • Firmware
  • LIPSedge™ AE430 / AE470
    • LIPSedge™ AE430 / AE470 User Guide
      • LIPSedge™ AE430 / AE470
      • User Guide
      • Previous Releases (Archive)
    • LIPSedge™ AE430 / AE470 SDK Release
      • SDK Release
      • Previous Releases (Archive)
    • LIPSedge™ AE430 / AE470 Supplementary Documents
      • Firmware
      • STEP files for CAD Use
  • LIPSedge™ AE430-DK / AE470-DK
    • LIPSedge™ AE430-DK / AE470-DK
    • User Guide
  • LIPSedge™ DL & M3 Series
    • LIPSedge™ DL & M3 Series User Guide
      • LIPSedge™ DL & M3 Series
      • User Guide
      • Previous Releases (Archive)
    • LIPSedge™ DL & M3 Series SDK Release
      • SDK Release
      • Changelog
      • Previous Releases (Archive)
    • LIPSedge™ DL & M3 Series Installation
      • Installation
      • Ubuntu
      • Windows
    • LIPSedge™ DL & M3 Supplementary Documents
      • STEP files for CAD Use
  • LIPSedge™ L215u / L210u
    • LIPSedge™ L215u / L210u User Guide
      • LIPSedge™ L215u / L210u
      • User Guide
      • Previous Releases (Archive)
    • LIPSedge™ L215u / L210u SDK Release
      • SDK Release
      • Changelog
      • Previous Releases (Archive)
    • LIPSedge™ L215u / L210u Installation
      • Installation
      • Linux
      • Windows
    • LIPSedge™ L215u / L210u Supplementary Documents
      • STEP files for CAD Use
  • LIPSFace™ HW110/115 On-Device 3D Facial Recognition
    • LIPSFace™ HW110/115 On-Device 3D Facial Recognition
    • User Guide & SDK Download
    • STEP files for CAD Use
  • LIPSFace™ HW120/125 On-Device 3D Facial Recognition
    • LIPSFace™ HW120/125 On-Device 3D Facial Recognition
    • User Guide
    • SDK Download
    • STEP files for CAD Use
  • LIPScan 3D ™ Middleware
    • LIPScan 3D ™ Middleware
    • LIPScan 3D™ SDK
      • LIPScan 3D™ SDK
      • User Guide
      • SDK Download
      • Release Notes
      • Previous Releases
    • LIPScan 3D™ Desktop
      • LIPScan 3D™ Desktop
      • User Guide
      • Application Download
      • Release Notes
      • Previous Releases
  • LIPSense™ 3D Body Pose Middleware
    • LIPSense™ 3D Body Pose Middleware
    • User Manual & SDK Download
    • Changelog
    • Previous Releases (Archive)
    • Examples
      • C++
        • C++
        • skeleton_example
        • skeleton_opencv
  • LIPSMetric™ HA110 Handheld Dimensioner
    • LIPSMetric™ HA110 Handheld Dimensioner
    • User Guide
  • LIPSMetric™ ST115 Static Dimensioner
    • LIPSMetric™ ST115 Static Dimensioner
    • User Guide
  • LIPSMetric™ ST130 Pallet Dimensioner
    • LIPSMetric™ ST130 Pallet Dimensioner
    • User Guide
  • LIPSedge™ SDK Languages & Libraries
    • LIPSedge™ SDK Languages & Libraries
    • OpenCV
    • C++
      • C++
      • environment-setup
      • hello-lipsedge-sdk
      • opencv-viewer
      • roi
      • depth-data
      • align-depth-color
      • range-filter
      • remove-background
      • record
      • pointcloud
      • config-resolution
      • camera-parameter
    • Python
      • Python
      • environment-setup
      • hello-lipsedge-sdk
      • opencv-viewer
      • roi
      • depth-data
      • align-depth-color
      • range-filter
      • remove-background
      • record
    • Java
      • Java
      • ni-hello
    • C#
      • C#
      • ni-hello
      • simple-read
  • LIPSedge™ SDK Frameworks
    • LIPSedge™ SDK Frameworks
    • ROS
    • ROS2
    • NVIDIA Isaac Wrapper
    • GenICam (for Halcon / Aurora Vision)
      • GenICam (for Halcon / Aurora Vision)
      • User Manual
      • Driver(.cti) and Nodemap (.xml)
      • Supported LIPSedge™ Camera SDK
      • Installation Example
  • LIPSedge™ SDK Sample Codes
    • LIPSedge™ SDK Sample Codes
    • Sample Applications & Viewer & Utilities
      • Sample Applications & Viewer & Utilities
      • ni-viewer
      • ni-pointcloud-gl
      • ni-camera-matrix
  • LIPSFace™ SDK
    • LIPSFace™ SDK
    • LIPSFace Overview
    • Changelog
View Categories
  • Home
  • LIPS® Developer Documentation
  • DOCUMENTS, INSTALLATION & SETUP
  • LIPSense™ 3D Body Pose Middleware
  • Examples
  • C++
  • skeleton_opencv

skeleton_opencv

Overview #

The Skeleton Example (OpenCV) program demonstrates the results that LIPSense 3D Body Pose SDK working with OpenCV.

Tutorial #

1. Include header files to access the functions they provide.

#include <LIPSBodyPose.h>
#include <iostream>
#include <opencv2/opencv.hpp>

2. Create a drawSkeleton function which contains the following part:

void drawSkeletons( cv::Mat& img, std::vector<lips::Skeleton>& skeletons )
{
    const std::vector<std::array<enum lips::Skeleton::Part, 2>> connection_pairs =  //1
    {
        // Face
        { lips::Skeleton::R_EYE, lips::Skeleton::R_EAR },
        { lips::Skeleton::L_EYE, lips::Skeleton::L_EAR },
        { lips::Skeleton::R_EYE, lips::Skeleton::NOSE },
        { lips::Skeleton::L_EYE, lips::Skeleton::NOSE },
        { lips::Skeleton::R_EYE, lips::Skeleton::HEAD },
        { lips::Skeleton::L_EYE, lips::Skeleton::HEAD },
        // Body
        { lips::Skeleton::NOSE, lips::Skeleton::NECK },
        { lips::Skeleton::NECK, lips::Skeleton::R_CLAVICLE },
        { lips::Skeleton::R_CLAVICLE, lips::Skeleton::R_SHOULDER },
        { lips::Skeleton::NECK, lips::Skeleton::L_CLAVICLE },
        { lips::Skeleton::L_CLAVICLE, lips::Skeleton::L_SHOULDER },
        { lips::Skeleton::R_SHOULDER, lips::Skeleton::R_HIP },
        { lips::Skeleton::L_SHOULDER, lips::Skeleton::L_HIP },
        { lips::Skeleton::L_HIP, lips::Skeleton::PELVIS },
        { lips::Skeleton::PELVIS, lips::Skeleton::R_HIP },
        { lips::Skeleton::NECK, lips::Skeleton::CHEST_SPINE },
        { lips::Skeleton::CHEST_SPINE, lips::Skeleton::NAVEL_SPINE },
        { lips::Skeleton::NAVEL_SPINE, lips::Skeleton::PELVIS },

        // Right arm
        { lips::Skeleton::R_SHOULDER, lips::Skeleton::R_ELBOW },
        { lips::Skeleton::R_ELBOW, lips::Skeleton::R_WRIST },
        { lips::Skeleton::R_WRIST, lips::Skeleton::R_HAND },
        { lips::Skeleton::R_HAND, lips::Skeleton::R_THUMB_TIP },
        { lips::Skeleton::R_HAND, lips::Skeleton::R_HAND_TIP },
        // Left arm
        { lips::Skeleton::L_SHOULDER, lips::Skeleton::L_ELBOW },
        { lips::Skeleton::L_ELBOW, lips::Skeleton::L_WRIST },
        { lips::Skeleton::L_WRIST, lips::Skeleton::L_HAND },
        { lips::Skeleton::L_HAND, lips::Skeleton::L_THUMB_TIP },
        { lips::Skeleton::L_HAND, lips::Skeleton::L_HAND_TIP },
        // Right leg
        { lips::Skeleton::R_HIP, lips::Skeleton::R_KNEE },
        { lips::Skeleton::R_KNEE, lips::Skeleton::R_ANKLE },
        { lips::Skeleton::R_ANKLE, lips::Skeleton::R_FOOT },
        // Left leg
        { lips::Skeleton::L_HIP, lips::Skeleton::L_KNEE },
        { lips::Skeleton::L_KNEE, lips::Skeleton::L_ANKLE },
        { lips::Skeleton::L_ANKLE, lips::Skeleton::L_FOOT }
    };

    const std::vector<cv::Scalar> color_list = { cv::Scalar( 255, 100, 100 ),  //2
                                                 cv::Scalar( 255, 255, 100 ),
                                                 cv::Scalar( 100, 255, 100 ),
                                                 cv::Scalar( 100, 255, 255 ),
                                                 cv::Scalar( 100, 100, 255 ) };

    for( auto& skeleton : skeletons )                                           //3
    {
        // Draw connection lines
        const int color_idx = skeleton.id() % color_list.size();
        const cv::Scalar line_color = color_list[color_idx];
        const int line_width = 2;
        for( auto& pair : connection_pairs )
        {
            lips::Keypoint keypoint_a = skeleton[pair[0]];
            lips::Keypoint keypoint_b = skeleton[pair[1]];
            if( keypoint_a.is_valid && keypoint_b.is_valid )
            {
                const cv::Point2f point_a = { keypoint_a.point2d.x, keypoint_a.point2d.y } ;
                const cv::Point2f point_b = { keypoint_b.point2d.x, keypoint_b.point2d.y } ;

                cv::line( img, point_a, point_b, line_color, line_width );
            }
        }

        // Draw keypoints
        const cv::Scalar circle_color( line_color[0] + 100, line_color[1] + 100, line_color[2] + 100 ); //4
        const int circle_radius = 4;
        const int circle_line_width = -1;  // solid
        for( auto& keypoint : skeleton )
        {
            if( keypoint.is_valid )
            {
                cv::circle( img, cv::Point2f{ keypoint.point2d.x, keypoint.point2d.y },
                            circle_radius, circle_color, circle_line_width );
            }
        }
    }
}
  • 1 Defines  the keypoints (joints) that should be connected with lines to form the stick-like skeletal figure. Examples: Face: eye → ear, eye → nose.
  • 2 Creates a list of predefined colors (BGR format) to represent each skeleton in a distinct color. Example: Person 1 = red, Person 2 = yellow, etc.
  • 3 For every detected person:
    Pick a color for their skeleton → Draw lines between valid joint pairs from connection_pairs. → Draw circles at each joint if it is marked as valid.
  • 4 Circles (filled) are drawn at each keypoint location to highlight joint positions — usually brighter than the line color for higher visibility.

3.  Create a colorizeDepthMap function which contains the following part:

cv::Mat colorizeDepthMap( const cv::Mat& depth, const int display_min_z = 300, const int display_max_z = 3000 ) //1
{
    const double normalize_alpha = 255.0 / static_cast<double>( display_max_z - display_min_z );
    const double normalize_beta = static_cast<double>( -255.0 * display_min_z ) /
                                  static_cast<double>( display_max_z - display_min_z );

    cv::Mat output;                                                         //2
    cv::Mat depth_normal;
    depth.convertTo( depth_normal, CV_8UC1, normalize_alpha, normalize_beta );
    cv::applyColorMap( depth_normal, output, cv::COLORMAP_JET );            //3

    return output;
}
SegmentsFunctions
1Normalize depth values within a 8-bit range. Maps depth values from [display_min_z, display_max_z] (e.g., 300–3000 mm) to [0, 255].
2Converts the original 16-bit depth image to 8-bit for color mapping.
3Uses OpenCV’s JET colormap to turn grayscale visualization into a colorful one (red-yellow-green-blue).

4. Create the main function and put on the whole process:

int main()
{
    lips::LIPSBodyPose lipsbodypose;                                       //1

    lipsbodypose.run();                                                     //2

    std::cout << "Press ESC to exit" << std::endl;
    while( true )
    {
        lips::Frame frame;                                                  //3
        lipsbodypose.readFrame( frame );                                    //4
        lips::Image<unsigned char[3]> lips_img_color = frame.color_image_bgr; //5
        lips::Image<unsigned short> lips_img_depth = frame.depth_image_mm;
        std::vector<lips::Skeleton> skeletons = frame.skeletons;

        cv::Mat img_color = cv::Mat( cv::Size( lips_img_color.width(), lips_img_color.height() ), //6
                                     CV_8UC3, reinterpret_cast<void*>( lips_img_color.data() ) );
        cv::Mat img_depth = cv::Mat( cv::Size( lips_img_depth.width(), lips_img_depth.height() ),
                                     CV_16UC1, reinterpret_cast<void*>( lips_img_depth.data() ) );

        drawSkeletons( img_color, skeletons );                              //7

        cv::imshow( "BGR Image", img_color );                               //8
        cv::imshow( "Depth Image", colorizeDepthMap( img_depth ) );

        const char key_input = cv::waitKey( 1 );                            //9
        if( key_input == 27 ) // ESC
            break;
    }

    lipsbodypose.stop();                                                    //10

    return 0;
}
SegmentsFunctions
1Creates an instance of the body pose detection engine.
2Starts the body pose engine.
3A structure that holds one frame’s value of: RGB image, Depth image, Detected skeletons.
4Reads the latest available frame from the LIPS SDK.
5Extract image and skeleton data (color_image_bgr, depth_image_mm, skeletons).
6Converts LIPS SDK’s custom Image<> type into standard OpenCV image types.
7Draw skeletons on top of the image.
8Display images in windows.
9If the key is ESC (ASCII 27), exit the loop.
10Terminates the SDK engine.

Expected output #

Expected outputopencv - LIPS® Developer Documentation

Full code #

#include <LIPSBodyPose.h>
#include <iostream>
#include <opencv2/opencv.hpp>

void drawSkeletons( cv::Mat& img, std::vector<lips::Skeleton>& skeletons )
{
    const std::vector<std::array<enum lips::Skeleton::Part, 2>> connection_pairs =
    {
        // Face
        { lips::Skeleton::R_EYE, lips::Skeleton::R_EAR },
        { lips::Skeleton::L_EYE, lips::Skeleton::L_EAR },
        { lips::Skeleton::R_EYE, lips::Skeleton::NOSE },
        { lips::Skeleton::L_EYE, lips::Skeleton::NOSE },
        { lips::Skeleton::R_EYE, lips::Skeleton::HEAD },
        { lips::Skeleton::L_EYE, lips::Skeleton::HEAD },
        // Body
        { lips::Skeleton::NOSE, lips::Skeleton::NECK },
        { lips::Skeleton::NECK, lips::Skeleton::R_CLAVICLE },
        { lips::Skeleton::R_CLAVICLE, lips::Skeleton::R_SHOULDER },
        { lips::Skeleton::NECK, lips::Skeleton::L_CLAVICLE },
        { lips::Skeleton::L_CLAVICLE, lips::Skeleton::L_SHOULDER },
        { lips::Skeleton::R_SHOULDER, lips::Skeleton::R_HIP },
        { lips::Skeleton::L_SHOULDER, lips::Skeleton::L_HIP },
        { lips::Skeleton::L_HIP, lips::Skeleton::PELVIS },
        { lips::Skeleton::PELVIS, lips::Skeleton::R_HIP },
        { lips::Skeleton::NECK, lips::Skeleton::CHEST_SPINE },
        { lips::Skeleton::CHEST_SPINE, lips::Skeleton::NAVEL_SPINE },
        { lips::Skeleton::NAVEL_SPINE, lips::Skeleton::PELVIS },

        // Right arm
        { lips::Skeleton::R_SHOULDER, lips::Skeleton::R_ELBOW },
        { lips::Skeleton::R_ELBOW, lips::Skeleton::R_WRIST },
        { lips::Skeleton::R_WRIST, lips::Skeleton::R_HAND },
        { lips::Skeleton::R_HAND, lips::Skeleton::R_THUMB_TIP },
        { lips::Skeleton::R_HAND, lips::Skeleton::R_HAND_TIP },
        // Left arm
        { lips::Skeleton::L_SHOULDER, lips::Skeleton::L_ELBOW },
        { lips::Skeleton::L_ELBOW, lips::Skeleton::L_WRIST },
        { lips::Skeleton::L_WRIST, lips::Skeleton::L_HAND },
        { lips::Skeleton::L_HAND, lips::Skeleton::L_THUMB_TIP },
        { lips::Skeleton::L_HAND, lips::Skeleton::L_HAND_TIP },
        // Right leg
        { lips::Skeleton::R_HIP, lips::Skeleton::R_KNEE },
        { lips::Skeleton::R_KNEE, lips::Skeleton::R_ANKLE },
        { lips::Skeleton::R_ANKLE, lips::Skeleton::R_FOOT },
        // Left leg
        { lips::Skeleton::L_HIP, lips::Skeleton::L_KNEE },
        { lips::Skeleton::L_KNEE, lips::Skeleton::L_ANKLE },
        { lips::Skeleton::L_ANKLE, lips::Skeleton::L_FOOT }
    };

    const std::vector<cv::Scalar> color_list = { cv::Scalar( 255, 100, 100 ),
                                                 cv::Scalar( 255, 255, 100 ),
                                                 cv::Scalar( 100, 255, 100 ),
                                                 cv::Scalar( 100, 255, 255 ),
                                                 cv::Scalar( 100, 100, 255 ) };

    for( auto& skeleton : skeletons )
    {
        // Draw connection lines
        const int color_idx = skeleton.id() % color_list.size();
        const cv::Scalar line_color = color_list[color_idx];
        const int line_width = 2;
        for( auto& pair : connection_pairs )
        {
            lips::Keypoint keypoint_a = skeleton[pair[0]];
            lips::Keypoint keypoint_b = skeleton[pair[1]];
            if( keypoint_a.is_valid && keypoint_b.is_valid )
            {
                const cv::Point2f point_a = { keypoint_a.point2d.x, keypoint_a.point2d.y } ;
                const cv::Point2f point_b = { keypoint_b.point2d.x, keypoint_b.point2d.y } ;

                cv::line( img, point_a, point_b, line_color, line_width );
            }
        }

        // Draw keypoints
        const cv::Scalar circle_color( line_color[0] + 100, line_color[1] + 100, line_color[2] + 100 );
        const int circle_radius = 4;
        const int circle_line_width = -1;  // solid
        for( auto& keypoint : skeleton )
        {
            if( keypoint.is_valid )
            {
                cv::circle( img, cv::Point2f{ keypoint.point2d.x, keypoint.point2d.y },
                            circle_radius, circle_color, circle_line_width );
            }
        }
    }
}

cv::Mat colorizeDepthMap( const cv::Mat& depth, const int display_min_z = 300, const int display_max_z = 3000 )
{
    const double normalize_alpha = 255.0 / static_cast<double>( display_max_z - display_min_z );
    const double normalize_beta = static_cast<double>( -255.0 * display_min_z ) /
                                  static_cast<double>( display_max_z - display_min_z );

    cv::Mat output;
    cv::Mat depth_normal;
    depth.convertTo( depth_normal, CV_8UC1, normalize_alpha, normalize_beta );
    cv::applyColorMap( depth_normal, output, cv::COLORMAP_JET );

    return output;
}

int main()
{
    lips::LIPSBodyPose lipsbodypose;

    lipsbodypose.run();

    std::cout << "Press ESC to exit" << std::endl;
    while( true )
    {
        lips::Frame frame;
        lipsbodypose.readFrame( frame );
        lips::Image<unsigned char[3]> lips_img_color = frame.color_image_bgr;
        lips::Image<unsigned short> lips_img_depth = frame.depth_image_mm;
        std::vector<lips::Skeleton> skeletons = frame.skeletons;

        cv::Mat img_color = cv::Mat( cv::Size( lips_img_color.width(), lips_img_color.height() ),
                                     CV_8UC3, reinterpret_cast<void*>( lips_img_color.data() ) );
        cv::Mat img_depth = cv::Mat( cv::Size( lips_img_depth.width(), lips_img_depth.height() ),
                                     CV_16UC1, reinterpret_cast<void*>( lips_img_depth.data() ) );

        drawSkeletons( img_color, skeletons );

        cv::imshow( "BGR Image", img_color );
        cv::imshow( "Depth Image", colorizeDepthMap( img_depth ) );

        const char key_input = cv::waitKey( 1 );
        if( key_input == 27 ) // ESC
            break;
    }

    lipsbodypose.stop();

    return 0;
}
Updated on 2025 年 9 月 4 日
LIPSense Body Pose
skeleton_example
Table of Contents
  • Overview
  • Tutorial
  • Expected output
  • Full code

#LIPS

About Us

Store

Blog

Terms of Use

DEVELOPER

Technical Support

SDK Download

Code Samples

Github

© 2025 LIPS Corporation