In the previous tutorial, I told you about building a kinect application based on the Dragonboard 410c development board to implement automatic follow-up robots. Today we talk about implementing face recognition.
First, the core code: //------------------------------------------------ ------------------------------
//
// Copyright (c) Microsoft CorporaTIon. All rights reserved.
//
//------------------------------------------------ ------------------------------
// Defines the entry point for the applicaTIon.
//
#include "stdafx.h"
#include "SingleFace.h"
#include "EggAvatar.h"
#include
#include "FTHelper.h"
Class SingleFace
{
Public:
SingleFace ()
: m_hInst ( NULL )
, m_hWnd ( NULL )
, m_hAccelTable ( NULL )
, m_pImageBuffer ( NULL )
, m_pVideoBuffer ( NULL )
, m_depthType ( NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX )
, m_colorType ( NUI_IMAGE_TYPE_COLOR )
, m_depthRes ( NUI_IMAGE_RESOLUTION_320x240 )
, m_colorRes ( NUI_IMAGE_RESOLUTION_640x480 )
, m_bNearMode ( TRUE )
, m_bSeatedSkeletonMode ( FALSE )
{}
Int Run ( HINSTANCE hInst , PWSTR lpCmdLine , int nCmdShow );
Protected:
BOOL InitInstance ( HINSTANCE hInst , PWSTR lpCmdLine , int nCmdShow );
Void ParseCmdString ( PWSTR lpCmdLine );
Void UninitInstance ();
ATOM RegisterClass ( PCWSTR szWindowClass );
Static LRESULT CALLBACK WndProcStatic ( HWND hwnd , UINT message , WPARAM wParam , LPARAM lParam );
LRESULT CALLBACK WndProc ( HWND hwnd , UINT message , WPARAM wParam , LPARAM lParam );
Static INT_PTR CALLBACK About ( HWND hwnd , UINT message , WPARAM wParam , LPARAM lParam );
BOOL PaintWindow ( HDC hdc , HWND hWnd );
BOOL ShowVideo ( HDC hdc , int width , int height , int originX , int originY );
BOOL ShowEggAvatar ( HDC hdc , int width , int height , int originX , int originY );
Static void FTHelperCallingBack ( LPVOID lpParam );
Static int const MaxLoadStringChars = 100 ;
HINSTANCE m_hInst ;
HWND m_hWnd ;
HACCEL m_hAccelTable ;
EggAvatar m_eggavatar ;
FTHelper m_FTHelper ;
IFTImage * m_pImageBuffer ;
IFTImage * m_pVideoBuffer ;
NUI_IMAGE_TYPE m_depthType ;
NUI_IMAGE_TYPE m_colorType ;
NUI_IMAGE_RESOLUTION m_depthRes ;
NUI_IMAGE_RESOLUTION m_colorRes ;
BOOL m_bNearMode ;
BOOL m_bSeatedSkeletonMode ;
};
// Run the SingleFace application.
Int SingleFace :: Run ( HINSTANCE hInst , PWSTR lpCmdLine , int nCmdShow )
{
MSG msg = { static_cast < HWND > ( 0 ), static_cast < UINT > ( 0 ), static_cast < WPARAM > ( - 1 )};
If ( InitInstance ( hInst , lpCmdLine , nCmdShow ))
{
// Main message loop:
While ( GetMessage ( & msg , NULL , 0 , 0 ))
{
If ( ! TranslateAccelerator ( msg . hwnd , m_hAccelTable , & msg ))
{
TranslateMessage ( & msg );
DispatchMessage ( & msg );
}
}
}
UninitInstance ();
Return ( int ) msg . wParam ;
}
// In this function, we save the instance handle, then create and display the main program window.
BOOL SingleFace :: InitInstance ( HINSTANCE hInstance , PWSTR lpCmdLine , int nCmdShow )
{
m_hInst = hInstance ; // Store instance handle in our global variable
ParseCmdString ( lpCmdLine );
WCHAR szTitle [ MaxLoadStringChars ]; // The title bar text
LoadString ( m_hInst , IDS_APP_TITLE , szTitle , ARRAYSIZE ( szTitle ));
Static const PCWSTR RES_MAP [] = { L"80x60" , L"320x240" , L"640x480" , L"1280x960" };
Static const PCWSTR IMG_MAP [] = { L"PLAYERID" , L"RGB" , L"YUV" , L"YUV_RAW" , L"DEPTH" };
// Add mode params in title
WCHAR szTitleComplete [ MAX_PATH ];
Swprintf_s ( szTitleComplete , L"%s -- Depth:%s:%s Color:%s:%s NearMode:%s, SeatedSkeleton:%s" , szTitle ,
IMG_MAP [ m_depthType ], ( m_depthRes < 0 ) ? L"ERROR" : RES_MAP [ m_depthRes ], IMG_MAP [ m_colorType ], ( m_colorRes < 0 ) ? L"ERROR" : RES_MAP [ m_colorRes ], m_bNearMode ? L"ON" : L "OFF" ,
m_bSeatedSkeletonMode ? L"ON" : L"OFF" );
WCHAR szWindowClass [ MaxLoadStringChars ]; // the main window class name
LoadString ( m_hInst , IDC_SINGLEFACE , szWindowClass , ARRAYSIZE ( szWindowClass ));
RegisterClass ( szWindowClass );
m_hAccelTable = LoadAccelerators ( hInstance , MAKEINTRESOURCE ( IDC_SINGLEFACE ));
m_pImageBuffer = FTCreateImage ();
m_pVideoBuffer = FTCreateImage ();
m_hWnd = CreateWindow ( szWindowClass , szTitleComplete , WS_OVERLAPPEDWINDOW ,
CW_USEDEFAULT , 0 , CW_USEDEFAULT , 0 , NULL , NULL , m_hInst , this );
If ( ! m_hWnd )
{
Return FALSE ;
}
ShowWindow ( m_hWnd , nCmdShow );
UpdateWindow ( m_hWnd );
Return SUCCEEDED ( m_FTHelper . Init ( m_hWnd ,
FTHelperCallingBack ,
This ,
m_depthType ,
m_depthRes ,
m_bNearMode ,
TRUE , // if near mode doesn't work, fall back to default mode
m_colorType ,
m_colorRes ,
m_bSeatedSkeletonMode ));
}
Void SingleFace :: UninitInstance ()
{
// Clean up the memory allocated for Face Tracking and rendering.
m_FTHelper . Stop ();
If ( m_hAccelTable )
{
DestroyAcceleratorTable ( m_hAccelTable );
m_hAccelTable = NULL ;
}
DestroyWindow ( m_hWnd );
m_hWnd = NULL ;
If ( m_pImageBuffer )
{
m_pImageBuffer -> Release ();
m_pImageBuffer = NULL ;
}
If ( m_pVideoBuffer )
{
m_pVideoBuffer -> Release ();
m_pVideoBuffer = NULL ;
}
}
// Register the window class.
ATOM SingleFace :: RegisterClass ( PCWSTR szWindowClass )
{
WNDCLASSEX wcex = { 0 };
Wcex . cbSize = sizeof ( WNDCLASSEX );
Wcex . style = CS_HREDRAW | CS_VREDRAW ;
Wcex . lpfnWndProc = & SingleFace :: WndProcStatic ;
Wcex . cbClsExtra = 0 ;
Wcex . cbWndExtra = 0 ;
Wcex . hInstance = m_hInst ;
Wcex . hIcon = LoadIcon ( m_hInst , MAKEINTRESOURCE ( IDI_SINGLEFACE ));
Wcex . hCursor = LoadCursor ( NULL , IDC_ARROW );
Wcex . hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
Wcex . lpszMenuName = MAKEINTRESOURCE ( IDC_SINGLEFACE );
Wcex . lpszClassName = szWindowClass ;
Return RegisterClassEx ( & wcex );
}
LRESULT CALLBACK SingleFace :: WndProcStatic ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )
{
Static SingleFace * pThis = NULL ; // cheating, but since there is just one window now, it will suffice.
If ( WM_CREATE == message )
{
pThis = reinterpret_cast < SingleFace *> ( reinterpret_cast < CREATESTRUCT *> ( lParam ) -> lpCreateParams );
}
Return pThis ? pThis -> WndProc ( hWnd , message , wParam , lParam ) : DefWindowProc ( hWnd , message , wParam , lParam );
}
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_KEYUP - Exit in response to ESC key
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
LRESULT CALLBACK SingleFace :: WndProc ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )
{
UINT wmId , wmEvent ;
PAINTSTRUCT ps ;
HDC hdc ;
Switch ( message )
{
Case WM_COMMAND :
wmId = LOWORD ( wParam );
wmEvent = HIWORD ( wParam );
// Parse the menu selections:
Switch ( wmId )
{
case IDM_ABOUT:
DialogBox ( m_hInst , MAKEINTRESOURCE ( IDD_ABOUTBOX ), hWnd , About );
Break ;
case IDM_EXIT:
PostQuitMessage ( 0 );
Break ;
Default:
Return DefWindowProc ( hWnd , message , wParam , lParam );
}
Break ;
case WM_KEYUP:
If ( wParam == VK_ESCAPE )
{
PostQuitMessage ( 0 );
}
Break ;
Case WM_PAINT :
Hdc = BeginPaint ( hWnd , & ps );
// Draw the avatar window and the video window
PaintWindow ( hdc , hWnd );
EndPaint ( hWnd , & ps );
Break ;
case WM_DESTROY:
PostQuitMessage ( 0 );
Break ;
Default:
Return DefWindowProc ( hWnd , message , wParam , lParam );
}
Return 0 ;
}
// Message handler for about box.
INT_PTR CALLBACK SingleFace :: About ( HWND hDlg , UINT message , WPARAM wParam , LPARAM lParam )
{
UNREFERENCED_PARAMETER ( lParam );
Switch ( message )
{
case WM_INITDIALOG:
Return ( INT_PTR ) TRUE ;
Case WM_COMMAND :
If ( LOWORD ( wParam ) == IDOK || LOWORD ( wParam ) == IDCANCEL )
{
EndDialog ( hDlg , LOWORD ( wParam ));
Return ( INT_PTR ) TRUE ;
}
Break ;
}
Return ( INT_PTR ) FALSE ;
}
// Drawing the video window
BOOL SingleFace :: ShowVideo ( HDC hdc , int width , int height , int originX , int originY )
{
BOOL ret = TRUE ;
// Now, copy a fraction of the camera image into the screen.
IFTImage * colorImage = m_FTHelper . GetColorImage ();
If ( colorImage )
{
Int iWidth = colorImage -> GetWidth ();
Int iHeight = colorImage -> GetHeight ();
If ( iWidth > 0 && iHeight > 0 )
{
Int iTop = 0 ;
Int iBottom = iHeight ;
Int iLeft = 0 ;
Int iRight = iWidth ;
// Keep a separate buffer.
If ( m_pVideoBuffer && SUCCEEDED ( m_pVideoBuffer -> Allocate ( iWidth , iHeight , FTIMAGEFORMAT_UINT8_B8G8R8A8 )))
{
// Copy do the video buffer while converting bytes
colorImage -> CopyTo ( m_pVideoBuffer , NULL , 0 , 0 );
// Compute the best approximate copy ratio.
Float w1 = ( float ) iHeight * ( float ) width ;
Float w2 = ( float ) iWidth * ( float ) height ;
If ( w2 > w1 && height > 0 )
{
// video image too wide
Float wx = w1 / height ;
iLeft = ( int ) max ( 0 , m_FTHelper . GetXCenterFace () - wx / 2 );
iRight = iLeft + ( int ) wx ;
If ( iRight > iWidth )
{
iRight = iWidth ;
iLeft = iRight - ( int ) wx ;
}
}
Else if ( w1 > w2 && width > 0 )
{
// video image too narrow
Float hy = w2 / width ;
iTop = ( int ) max ( 0 , m_FTHelper . GetYCenterFace () - hy / 2 );
iBottom = iTop + ( int ) hy ;
If ( iBottom > iHeight )
{
iBottom = iHeight ;
iTop = iBottom - ( int ) hy ;
}
}
Int const bmpPixSize = m_pVideoBuffer -> GetBytesPerPixel ();
SetStretchBltMode ( hdc , HALFTONE );
BITMAPINFO bmi = { sizeof ( BITMAPINFO ), iWidth , iHeight , 1 , static_cast < WORD > ( bmpPixSize * CHAR_BIT ), BI_RGB , m_pVideoBuffer -> GetStride () * iHeight , 5000 , 5000 , 0 , 0 };
If ( 0 == StretchDIBits ( hdc , originX , originY , width , height ,
iLeft , iBottom , iRight - iLeft , iTop - iBottom , m_pVideoBuffer -> GetBuffer (), & bmi , DIB_RGB_COLORS , SRCCOPY ))
{
Ret = FALSE ;
}
}
}
}
Return ret ;
}
// Drawing code
BOOL SingleFace :: ShowEggAvatar ( HDC hdc , int width , int height , int originX , int originY )
{
Static int errCount = 0 ;
BOOL ret = FALSE ;
If ( m_pImageBuffer && SUCCEEDED ( m_pImageBuffer -> Allocate ( width , height , FTIMAGEFORMAT_UINT8_B8G8R8A8 )))
{
memset (m_pImageBuffer -> GetBuffer () , 0, m_pImageBuffer -> GetStride () * height); // clear to black
M_eggavatar . SetScaleAndTranslationToWindow ( height , width );
M_eggavatar . DrawImage ( m_pImageBuffer );
BITMAPINFO bmi = { sizeof ( BITMAPINFO ), width , height , 1 , static_cast < WORD > ( m_pImageBuffer -> GetBytesPerPixel () * CHAR_BIT ), BI_RGB , m_pImageBuffer -> GetStride () * height , 5000 , 5000 , 0 , 0 };
errCount += ( 0 == StretchDIBits ( hdc , 0 , 0 , width , height , 0 , 0 , width , height , m_pImageBuffer -> GetBuffer (), & bmi , DIB_RGB_COLORS , SRCCOPY ));
Ret = TRUE ;
}
Return ret ;
}
// Draw the egg head and the camera video with the mask superimposed.
BOOL SingleFace :: PaintWindow ( HDC hdc , HWND hWnd )
{
Static int errCount = 0 ;
BOOL ret = FALSE ;
RECT rect ;
GetClientRect ( hWnd , & rect );
Int width = rect . right - rect . left ;
Int height = rect . bottom - rect . top ;
Int halfWidth = width / 2 ;
// Show the video on the right of the window
errCount += ! ShowVideo ( hdc , width - halfWidth , height , halfWidth , 0 );
// Draw the egg avatar on the left of the window
errCount += ! ShowEggAvatar ( hdc , halfWidth , height , 0 , 0 );
11th Laptop
So happy to know that 11th laptop is ranking the No.1 position in 2022 custom market. You can see intel core i3 11th generation laptop,Gaming Laptop i5 11th generation, laptop price i7 11th generation, etc. At this store. Maybe you will ask why 11th gen gaming laptop is so popular and welcome, mainly reason is its competitive cost and high performance. Intel i7 11th Generation Laptop cost is similar as intel i7 10th gen laptop, but performance is much better than 10th one. Besides, 12th laptop is arriving in lot at the end of 2022 at custom laptop market, price is will much competitive at that time.
Whom this Gaming Laptop is more suitable to? Of course, heavier tasks workers, no matter office jobs, education tasks, or others. However, if your clients focus more powerful cpu and performance, i7 16gb ram 4gb graphics laptop or 15 Inch Gaming Laptop with 10th cpu and 2GB graphics also alternatives.
You can contact us directly to get get right and valuable information fast. Will try our best to support every clients no matter quantity you take.
11th Laptop,Intel Core I3 11th Generation Laptop,11th Gen Gaming Laptop,Gaming Laptop I5 11th Generation,Laptop Price I7 11th Generation
Henan Shuyi Electronics Co., Ltd. , https://www.shuyicustomlaptop.com