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

Quick Introduction

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

LIPSedge Documents

57
  • LIPSMetric™ ST115b
    • User’s Manual
    • SDK Release
  • LIPSMetric™ HA110-M
    • User’s Manual
    • SDK Release
  • LIPSMetric™ HA115a
    • SDK Release
    • User’s Manual
  • LIPSMetric™ ST110d
    • User’s Manual
    • SDK Release
  • LIPSedge™ AE400 / AE450
    • LIPSedge™ AE400 / AE450 Complementary Documents
      • Certifications Documents
      • STEP files for CAD Use
      • Firmware
    • 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™ AE430 / AE470
    • LIPSedge™ AE430 / AE470 Supplementary Documents
      • Firmware
      • STEP files for CAD Use
    • LIPSedge™ AE430 / AE470 User Guide
      • LIPSedge™ AE430 / AE470
      • User Guide
      • Previous Releases (Archive)
    • LIPSedge™ AE430 / AE470 SDK Release
      • SDK Release
      • Previous Releases (Archive)
  • LIPSedge™ DL & M3 Series
    • LIPSedge™ DL & M3 Series Installation
      • Installation
      • Ubuntu
      • Windows
    • LIPSedge™ DL & M3 Supplementary Documents
      • STEP files for CAD Use
    • LIPSedge™ DL & M3 Series SDK Release
      • SDK Release
      • Changelog
      • Previous Releases (Archive)
    • LIPSedge™ DL & M3 Series User Guide
      • LIPSedge™ DL & M3 Series
      • User Guide
      • Previous Releases (Archive)
  • 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
  • LIPSedge™ L235
    •  LIPSedge™ L235 User’s Manual
    • LIPSedge™ L235 SDK Release
  • LIPSedge™ S Series
    • LIPSedge™ S Series User Guide
      •  LIPSedge™ S Series
      • User Guide
    • LIPSedge™ S Series SDK Release
      • SDK Release
    • LIPSedge™ S Series Installation
      • Windows
  • LIPSedge™ AE430-DK / AE470-DK
    • LIPSedge™ AE430-DK / AE470-DK
    • User Guide

LIPSedge™ SDK 1.x

82
  • 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
  • Tutorial and deployment
    • Tutorials
    • Development and Deployment on arm64
  • Features Articles
    • Features Articles
    • LIPSedge™ SDK Persistent Connection for PoE and USB
  • 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 v1.02 Tools
    • LIPSedge™ SDK v1.02 Tools
    • DepthViewer
    • PointCloudViewer
    • CameraParameterViewer
    • CameraCenterViewer
    • CameraEventListener
    • CameraPowerTest
    • LensModeSelector
    • LIPSImuReader
    • CameraSimpleViewer
    • RawFileViewer
  • 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
      • align
      • distance
      • grabcuts
      • measure
      • motion
      • post-processing
      • save-to-disk
      • sensor-control
    • 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
  • 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 Sample Codes
    • LIPSedge™ SDK Sample Codes
    • Sample Applications & Viewer & Utilities
      • Sample Applications & Viewer & Utilities
      • ni-viewer
      • ni-pointcloud-gl
      • ni-camera-matrix

LIPSense Documents

33
  • LIPSense™ 3D Body Pose Middleware
    • LIPSense™ 3D Body Pose SDK
    • User Manual & SDK Download
    • License Management
    • Changelog
    • Previous Releases (Archive)
    • Examples
      • Python
        • Python
        • python_example
      • c#
        • SkeletonCSharp
        • C#
      • C++
        • C++
        • skeleton_example
        • skeleton_opencv
  • LIPScan 3D ™ Middleware
    • LIPScan 3D ™ Middleware
    • LIPScan 3D™ Desktop
      • LIPScan 3D™ Desktop
      • User Guide
      • Application Download
      • Release Notes
      • Previous Releases
    • LIPScan 3D™ SDK
      • LIPScan 3D™ SDK
      • User Guide
      • SDK Download
      • Release Notes
      • Previous Releases
  • LIPSFace™ SDK
    • LIPSFace™ SDK
    • LIPSFace Overview
    • Changelog
  • 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
  • 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

LIPSMetric Documents

9
  • LIPSMetric™ Measure Master
    • User’s Manual
    • SDK Release
  • LIPSMetric™ VD115 Vehicle Dimensioner
    • LIPSMetric™ VD115 Vehicle Dimensioner
  • LIPSMetric™ ST115 Static Dimensioner
    • LIPSMetric™ ST115 Static Dimensioner
    • User’s Manual
  • LIPSMetric™ ST130 Pallet Dimensioner
    • LIPSMetric™ ST130 Pallet Dimensioner
    • User Guide
  • LIPSMetric™ HA110 Handheld Dimensioner
    • LIPSMetric™ HA110 Handheld Dimensioner
    • User’s Manual

Other LIPS Documents

1
  • LIPS License Management
    • LIPS License Management
View Categories
  • Home
  • LIPS® Developer Documentation
  • LIPSense Documents
  • 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_exampleC++
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

Copyright © 2026 LIPS Corporation | Privacy Policy | Cookie Policy | Do Not Sell My Personal Information