From: Jinkun Jang Date: Tue, 12 Mar 2013 16:50:38 +0000 (+0900) Subject: Tizen 2.1 base X-Git-Tag: 2.1b_release~15 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ad52b5fc5ba54712b904d966f35d2971d68b111c;p=framework%2Fosp%2Fface.git Tizen 2.1 base --- diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..f31acf2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,74 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +SET (this_target osp-face) + +SET(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/cmake_build_tmp/output) + +INCLUDE_DIRECTORIES( + inc + src + /usr/include/osp + /usr/include/uix + /usr/include/osp/base + ) + +SET (${this_target}_SOURCE_FILES + src/FUixVisionFaceBuffer.cpp + src/FUixVisionFaceComponentsPosition.cpp + src/FUixVisionFaceDetector.cpp + src/FUixVision_FaceDetectorImpl.cpp + src/FUixVisionFaceRecognitionInfo.cpp + src/FUixVisionFaceRecognizer.cpp + src/FUixVision_FaceRecognizerImpl.cpp + ) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall" ) + +## SET C COMPILER FLAGS +SET(CMAKE_C_FLAGS "${OSP_DEBUG_FLAGS} ${OSP_OPT_FLAGS} ${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} ${OSP_COMPILER_FLAGS}") + +## SET CPP COMPILER FLAGS +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") +SET(CMAKE_CXX_FLAGS "${OSP_DEBUG_FLAGS} ${OSP_OPT_FLAGS} ${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} ${OSP_COMPILER_FLAGS}") + +## Create Library +ADD_LIBRARY (${this_target} SHARED ${${this_target}_SOURCE_FILES}) + +## SET LINKER FLAGS +SET(CMAKE_SHARED_LINKER_FLAGS -Wl,--no-undefined) + +TARGET_LINK_LIBRARIES(${this_target} "-L/usr/lib/osp -losp-appfw" ) +TARGET_LINK_LIBRARIES(${this_target} "-losp-uifw" ) +TARGET_LINK_LIBRARIES(${this_target} "-lcapi-uix-face" ) + +SET_TARGET_PROPERTIES(${this_target} + PROPERTIES + VERSION ${FULLVER} + SOVERSION ${MAJORVER} + CLEAN_DIRECT_OUTPUT 1 + ) + +ADD_CUSTOM_COMMAND(TARGET ${this_target} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${LIBRARY_OUTPUT_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX} ${LIBRARY_OUTPUT_PATH}/debug/${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX}.${FULLVER} + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX}.${FULLVER} ${LIBRARY_OUTPUT_PATH}/debug/${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX}.${MAJORVER} + COMMAND ${CMAKE_STRIP} --strip-unneeded ${LIBRARY_OUTPUT_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}${this_target}${CMAKE_SHARED_LIBRARY_SUFFIX} + COMMENT "strip ${this_target}" + ) + +INSTALL(DIRECTORY ${LIBRARY_OUTPUT_PATH}/ DESTINATION lib/osp + FILES_MATCHING PATTERN "*.so*" + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ) +INSTALL(DIRECTORY ${LIBRARY_OUTPUT_PATH}/debug/ DESTINATION lib/osp/debug + FILES_MATCHING PATTERN "*.so*" + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ) + +INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/inc/ DESTINATION include/osp FILES_MATCHING PATTERN "*.h") + +# pkgconfig file +CONFIGURE_FILE(${this_target}.pc.in ${CMAKE_SOURCE_DIR}/${this_target}.pc @ONLY) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/${this_target}.pc DESTINATION lib/pkgconfig) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100755 index 0000000..8c778e0 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE file for Apache License terms and conditions. diff --git a/inc/FUixVision.h b/inc/FUixVision.h new file mode 100755 index 0000000..8845030 --- /dev/null +++ b/inc/FUixVision.h @@ -0,0 +1,56 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVision.h + * @brief This is the header file for the %Vision namespace. + * + * This header file contains the declarations and descriptions of the %Tizen::Uix::Vision namespace. + */ + +#ifndef _FUIX_VISION_H_ +#define _FUIX_VISION_H_ + +#include +#include +#include +#include +#include + +/** + * @namespace Tizen::Uix::Vision + * @brief This namespace contains the classes for the face and its related functions. + * @since 2.0 + * + * @remarks @b Header @b %file: @b \#include @b @n + * @b Library : @b osp-face + * + * The %Vision namespace provides the ability to automatically detect and trace faces in a still image or a video stream. + * @n + * For more information on the class features, see Face Detector and Recognizer. + * + * The following diagram illustrates the relationships between the classes belonging to the %Vision namespace. + * @image html uix_vision_namespace_classdiagram.png + + */ + +namespace Tizen { namespace Uix { namespace Vision +{ + +} } } // Tizen::Uix::Vision + +#endif // _FUIX_VISION_H_ diff --git a/inc/FUixVisionFaceBuffer.h b/inc/FUixVisionFaceBuffer.h new file mode 100755 index 0000000..5219b10 --- /dev/null +++ b/inc/FUixVisionFaceBuffer.h @@ -0,0 +1,121 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +/** + * @file FUixVisionFaceBuffer.h + * @brief This is the header file for the %FaceBuffer class. + * + * This header file contains the declarations of the %FaceBuffer class. + */ + +#ifndef _FUIX_VISION_FACE_BUFFER_H_ +#define _FUIX_VISION_FACE_BUFFER_H_ + +#include +#include + +namespace Tizen { namespace Base +{ +class ByteBuffer; +} } + +namespace Tizen { namespace Uix { namespace Vision +{ + +/** + * @class FaceBuffer + * @brief This class encapsulates the information processed by the FaceDetector and FaceRecognizer classes. + * + * @since 2.0 + * + * @remarks @b Header @b %file: @b \#include @b @n + * @b Library : @b osp-face + * + * The %FaceBuffer class encapsulates the information processed by the FaceDetector and FaceRecognizer classes. + * It contains proper data format that can be used in the face related methods. The user can get the face buffer from + * FaceDetector::PreprocessDataN(). + * @n + * For more information on the class features, see Face Detector and Recognizer. + * + */ + +class _OSP_EXPORT_ FaceBuffer + : public Tizen::Base::Object +{ + +public: + /** + * This is the destructor for this class. @n + * The resources are deallocated by this method. + * This destructor overrides Tizen::Base::Object::~Object(). + * + * @since 2.0 + */ + virtual ~FaceBuffer(void); + +// Operation + + /** + * Gets the width and height of the face data. + * + * @since 2.0 + * + * @return The dimension of the face data + */ + Tizen::Graphics::Dimension GetDimension(void) const; + + + /** + * Gets the buffer that contains the face data. + * + * @since 2.0 + * + * @return A pointer to the buffer containing the face data + */ + const Tizen::Base::ByteBuffer* GetBuffer(void) const; + +private: + /** + * This is the default constructor for this class. + * This default constructor is intentionally declared as private so that only the platform can create an instance. + */ + FaceBuffer(void); + /** + * This constructor is intentionally declared as private so that only the platform can create an instance. + */ + FaceBuffer(const Tizen::Base::ByteBuffer& buffer, const Tizen::Graphics::Dimension& dim); + /** + * The implementation of this copy constructor is intentionally blank and declared as private to prohibit copying of objects. + */ + FaceBuffer(const FaceBuffer& value); + /** + * The implementation of this copy assignment operator is intentionally blank and declared as private to prohibit copying of objects. + */ + FaceBuffer& operator =(const FaceBuffer& value); + +private: + Tizen::Base::ByteBuffer* __pBuffer; + Tizen::Graphics::Dimension __resolution; + + friend class FaceDetector; + +}; // FaceBuffer + +} } } // Tizen::Uix::Vision + +#endif // _FUIX_VISION_FACE_BUFFER_H_ diff --git a/inc/FUixVisionFaceComponentsPosition.h b/inc/FUixVisionFaceComponentsPosition.h new file mode 100755 index 0000000..40dc438 --- /dev/null +++ b/inc/FUixVisionFaceComponentsPosition.h @@ -0,0 +1,210 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +/** + * @file FUixVisionFaceComponentsPosition.h + * @brief This is the header file for the %FaceComponentsPosition class. + * + * This header file contains the declarations of the %FaceComponentsPosition class. + */ + +#ifndef _FUIX_VISION_FACE_COMPONENTS_POSITION_H_ +#define _FUIX_VISION_FACE_COMPONENTS_POSITION_H_ + +#include +#include +#include +#include + +namespace Tizen { namespace Uix { namespace Vision +{ + +/** + * @class FaceComponentsPosition + * @brief This class encapsulates the extracted face component's information that is processed by the FaceDetector class. + * + * @since 2.0 + * + * @remarks @b Header @b %file: @b \#include @b @n + * @b Library : @b osp-face + * + * The %FaceComponentsPosition class encapsulates the extracted face component's information that is processed by the FaceDetector class. + * + * This class provides the following functionalities: @n + * - Getting/Setting the position of a face. + * - Getting/Setting the position of the eyes. + * - Getting/Setting the position of the mouth. + * @n + * For more information on the class features, see Face Detector and Recognizer. + */ + +class _OSP_EXPORT_ FaceComponentsPosition + : public Tizen::Base::Object +{ +public: + /** + * This is the default constructor for this class. @n + * Initializes this instance of %FaceComponentsPosition with all its attributes set to @c -1. + * + * @since 2.0 + * + * @remarks The attributes are set to @c -1 when initialized. + */ + FaceComponentsPosition(void); + + /** + * Initializes this instance of %FaceComponentsPosition with the specified parameter. + * + * @since 2.0 + * + * @param[in] faceRect The face position that can be obtained using the FaceDetector::DetectFacesN() method + */ + FaceComponentsPosition(const Tizen::Graphics::Rectangle& faceRect); + + /** + * Initializes this instance of %FaceComponentsPosition with the specified parameters. + * + * @since 2.0 + * + * @param[in] faceRect The face position that can be obtained using the FaceDetector::DetectFacesN() method + * @param[in] leftEyePos The eye position on the left that can be obtained using the FaceDetector::ExtractFaceComponentsN() method + * @param[in] rightEyePos The eye position on the right that can be obtained using the FaceDetector::ExtractFaceComponentsN() method + */ + FaceComponentsPosition(const Tizen::Graphics::Rectangle& faceRect, const Tizen::Graphics::Point& leftEyePos, const Tizen::Graphics::Point& rightEyePos); + + /** + * This is the destructor for this class. @n + * The resources are deallocated by this method. + * This destructor overrides Tizen::Base::Object::~Object(). + * + * @since 2.0 + */ + virtual ~FaceComponentsPosition(void); + + + /** + * Gets the position of the face. + * + * @since 2.0 + * + * @return The position of the face + * @remarks The value of all the attributes is set to @c -1 if their value is not set to @c -1 during initialization. + */ + Tizen::Graphics::Rectangle GetFacePosition(void) const; + + /** + * Gets the position of the eyes. + * + * @since 2.0 + * + * @param[out] leftEyePos The eye position on the left + * @param[out] rightEyePos The eye position on the right + * @remarks The value of @c leftEyePos and @c rightEyePos is set to @c -1 if it is not set to @c -1 during initialization. + */ + void GetEyePosition(Tizen::Graphics::Point& leftEyePos, Tizen::Graphics::Point& rightEyePos) const; + + /** + * Gets the position of the mouth. + * + * @since 2.0 + * + * @return The position of the mouth + * @remarks The value of all the attributes is set to @c -1 if their value is not set to @c -1 during initialization. + */ + Tizen::Graphics::Rectangle GetMouthPosition(void) const; + + /** + * Sets the position of the face. + * + * @since 2.0 + * + * @return An error code + * @param[in] faceRect The face position that can be obtained using the FaceDetector::DetectFacesN() method @n + * The value of the x and y positions for the @c faceRect parameter must be greater than or equal to @c 0. @n + * The value of the width and height for the @c faceRect parameter must be greater than @c 0. + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG The specified input parameter is invalid. + * @see FaceDetector::ExtractFaceComponentsN() + */ + result SetFacePosition(const Tizen::Graphics::Rectangle& faceRect); + + /** + * Sets the position of the eyes. + * + * @since 2.0 + * + * @return An error code + * @param[in] leftEyePos The eye position on the left @n + * This position can be obtained using the FaceDetector::ExtractFaceComponentsN() method. + * @param[in] rightEyePos The eye position on the right @n + * This position can be obtained using the FaceDetector::ExtractFaceComponentsN() method. @n + * The position of the eyes must be greater than or equal to @c 0. @n + * The position of @c rightEyePos must be greater than the position of @c leftEyePos. + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + */ + result SetEyePosition(const Tizen::Graphics::Point& leftEyePos, const Tizen::Graphics::Point& rightEyePos); + + /** + * Sets the position of the mouth. + * + * @since 2.0 + * + * @return An error code + * @param[in] mouthRect The position of the mouth that can be obtained using the FaceDetector::ExtractFaceComponentsN() + * method + * @exception E_SUCCESS The method is successful. @n + * The value of the x and y positions for the @c mouthRect parameter must be greater than or equal to @c 0. @n + * The value of the width and height for the @c mouthRect parameter must be greater than @c 0. + * @exception E_INVALID_ARG The specified input parameter is invalid. + */ + result SetMouthPosition(const Tizen::Graphics::Rectangle& mouthRect); + + /** + * This is the copy constructor for the %FaceComponentsPosition class. @n + * Initializes this instance of %FaceComponentsPosition with the specified parameter. + * Copying of objects using this copy constructor is allowed. + * + * @since 2.0 + * + * @param[in] rhs An instance of %FaceComponentsPosition + */ + FaceComponentsPosition(const FaceComponentsPosition& rhs); + + /** + * Assigns the value of the indicated %FaceComponentsPosition object to the current instance. @n + * Copying of objects using this copy assignment operator is allowed. + * + * @since 2.0 + * + * @param[in] rhs An instance of %FaceComponentsPosition + */ + FaceComponentsPosition& operator =(const FaceComponentsPosition& rhs); + +// Member variable +private: + Tizen::Graphics::Rectangle __faceRect; + Tizen::Graphics::Point __eyeRight; + Tizen::Graphics::Point __eyeLeft; + Tizen::Graphics::Rectangle __mouthRect; + +}; // FaceComponentsPosition + +} } } // Tizen::Uix::Vision + +#endif diff --git a/inc/FUixVisionFaceDetector.h b/inc/FUixVisionFaceDetector.h new file mode 100755 index 0000000..4e41050 --- /dev/null +++ b/inc/FUixVisionFaceDetector.h @@ -0,0 +1,417 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +/** + * @file FUixVisionFaceDetector.h + * @brief This is the header file for the %FaceDetector class. + * + * This header file contains the declarations of the %FaceDetector class. + */ + +#ifndef _FUIX_VISION_FACE_DETECTOR_H_ +#define _FUIX_VISION_FACE_DETECTOR_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace Tizen { namespace Base +{ +class ByteBuffer; +} } + +namespace Tizen { namespace Base { namespace Collection +{ +class IList; +template class IListT; +} } } + +namespace Tizen { namespace Graphics +{ +class Bitmap; +class Dimension; +class Rectangle; +} } + +namespace Tizen { namespace Uix { namespace Vision +{ +class _FaceDetectorImpl; + +/** + * @class FaceDetector + * @brief This class is used to trace faces in an image or a video. + * + * @since 2.0 + * + * @remarks @b Header @b %file: @b \#include @b @n + * @b Library : @b osp-face + * + * The %FaceDetector class provides the ability to automatically detect and trace faces in a still image or a video stream. + * @n + * For more information on the class features, see Face Detector and Recognizer. + * + * The following example demonstrates how to use the %FaceDetector class. + * + * @code + * #include + * #include + * #include + * #include + * #include + * + * using namespace Tizen::Base; + * using namespace Tizen::Media; + * using namespace Tizen::Graphics; + * using namespace Tizen::Io; + * using namespace Tizen::Uix::Vision; + * + * result + * MyClass::TestFaceDetect(void) + * { + * ByteBuffer* pByteBuffer = null; + * int width = 0, height = 0; + * result r = E_SUCCESS; + * + * Image* pImage = new Image(); + * r = pImage->Construct(); + * + * String path(L"test.bmp"); + * + * pByteBuffer = pImage->DecodeToBufferN(path, BITMAP_PIXEL_FORMAT_RGB565,width,height ); + * + * //Deletes the image object + * delete pImage; + * + * if (pByteBuffer) + * { + * //Detects faces + * FaceDetector faceDetect; + * r = faceDetect.Construct(); + * const Tizen::Base::Collection::IList* pFaceDetectList = faceDetect.DetectFacesFromStillImageN(*pByteBuffer, Dimension(width,height), BITMAP_PIXEL_FORMAT_RGB565); + * + * if(pFaceDetectList == null) + * { + * delete pByteBuffer; + * return GetLastResult(); + * } + * + * for(int i=0; i < pFaceDetectList->GetCount(); i++) + * { + * Tizen::Graphics::Rectangle* pRect = (Tizen::Graphics::Rectangle*)pFaceDetectList->GetAt(i); + * } + * + * delete pFaceDetectList; + * } + * + * return r; + * } + * @endcode + */ +class _OSP_EXPORT_ FaceDetector + : public Tizen::Base::Object +{ + +// Lifecycle +public: + /** + * This is the default constructor for this class. + * The object is not fully constructed after this constructor is called. + * For full construction, the Construct() method must be called right after calling this constructor. + * + * @since 2.0 + */ + FaceDetector(void); + + /** + * This is the destructor for this class. @n + * The resources are deallocated by this method. + * This destructor overrides Tizen::Base::Object::~Object(). + * + * @since 2.0 + */ + virtual ~FaceDetector(void); + + +// Operation + + /** + * Initializes this instance of %FaceDetector. + * + * @since 2.0 + * + * @return An error code + * @exception E_SUCCESS The method is successful. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + */ + result Construct(void); + + /** + * Gets the range and default value of the specified configuration property. + * + * @since 2.0 + * + * @return An error code + * @param[in] configProperty The property to query + * @param[out] min The minimum value of the property + * @param[out] max The maximum value of the property + * @param[out] steppingDelta The step size for the property @n + * The step size is the smallest increment by which the property can be changed. + * @param[out] defaultVal The default value of the property + * @exception E_SUCCESS The method is successful. + * @exception E_UNSUPPORTED_OPERATION The device does not support this property. + */ + result GetRange(FaceDetectorConfigProperty configProperty, long& min, long& max, long& steppingDelta, long& defaultVal) const; + + /** + * Sets the value of the specified property. + * + * @since 2.0 + * + * @return An error code + * @param[in] configProperty The property to query + * @param[in] value The new value of the property + * @exception E_SUCCESS The method is successful. + * @exception E_UNSUPPORTED_OPERATION The device does not support this property. + * @exception E_OUT_OF_RANGE The specified @c value is out of range. + * @see GetRange() + */ + result SetProperty(FaceDetectorConfigProperty configProperty, long value); + + /** + * Gets the current setting of the specified configuration property. + * + * @since 2.0 + * + * @return The value of the property, @n + * else @c -1 if an exception occurs + * @param[in] configProperty The property to query + * @exception E_SUCCESS The method is successful. + * @exception E_UNSUPPORTED_OPERATION The device does not support this property. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + long GetProperty(FaceDetectorConfigProperty configProperty) const; + + /** + * Gets a list of supported pixel formats. + * + * @since 2.0 + * + * @return A list of the supported pixel formats that are used in the DetectFacesFromVideoStreamN() method @n + * The format is in the form of a string. + * @exception E_SUCCESS The method is successful. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::Collection::IListT * GetSupportedFormatListN(void) const; + + /** + * Searches for faces from a video. + * + * @since 2.0 + * + * @return A list of the detected face positions @n + * Each list's item has a pointer of Tizen::Graphics::Rectangle value. @n + * An empty list, if there are no detected faces and there is no error. @n + * The faces are not detected when the faces are too small or the video data is not clear. @n + * This is the result of a normal operation, @n + * else @c null if an exception occurs. + * @param[in] byteBuffer The buffer containing the video data + * @param[in] dim The width and height of the video data @n + * Both the width and height must be greater than @c 0. + * @param[in] format The format of video data @n + * It must be one of the pixel formats extracted from GetSupportedFormatListN(). + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_FAILURE A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::Collection::IList* DetectFacesFromVideoStreamN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, const Tizen::Graphics::PixelFormat format); + + /** + * @if OSPDEPREC + * Detects faces from a still image. + * + * @brief [Deprecated] + * @deprecated This method is deprecated as it may return an improper result. + * Instead of using this method, use DetectFacesFromStillImageN(Tizen::Base::ByteBuffer &, Tizen::Graphics::Dimension &, Tizen::Graphics::BitmapPixelFormat). + * To optimize the memory usage and processing time, the bitmap scales down an image by decreasing its resolution in some models, + * that in turn decreases the accuracy of the face library. Therefore, the usage of this method using Tizen::Base::ByteBuffer is encouraged. + * @since 2.0 + * + * @return A list of the detected face positions @n + * Each list's item has a pointer of Tizen::Graphics::Rectangle value. @n + * An empty list, if there are no detected faces and there is no error @n + * The faces are not detected when the faces are too small or the image is not clear. @n + * This is the result of a normal operation, @n + * else @c null if an exception occurs. + * @param[in] bitmap The bitmap file containing the input image data + * @exception E_SUCCESS The method is successful. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_FAILURE A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @remarks BitmapPixelFormat::BITMAP_PIXEL_FORMAT_R8G8B8A8 is not applicable for this method. + * @endif + */ + Tizen::Base::Collection::IList* DetectFacesFromStillImageN(const Tizen::Graphics::Bitmap& bitmap); + + /** + * Searches for faces from a still image. + * + * @since 2.0 + * + * @return A list of the detected face positions @n + * Each list's item has a pointer of Tizen::Graphics::Rectangle value. @n + * An empty list, if there are no detected faces and there is no error @n + * The faces are not detected when the faces are too small or the image is not clear. @n + * This is the result of a normal operation, @n + * else @c null if an exception occurs. + * @param[in] byteBuffer The buffer containing the input image data + * @param[in] dim The width and height of the input image @n + * Both the width and height must be greater than @c 0. + * @param[in] format The color format defined by Tizen::Graphics::BitmapPixelFormat + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_FAILURE A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @remarks BitmapPixelFormat::BITMAP_PIXEL_FORMAT_R8G8B8A8 is not applicable for this method. + */ + Tizen::Base::Collection::IList* DetectFacesFromStillImageN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, Tizen::Graphics::BitmapPixelFormat format); + + + /** + * Converts the input data to a proper data format that can be used in the face related methods. + * + * @since 2.0 + * + * @return The preprocessed data, @n + * else @c null if an exception occurs + * @param[in] byteBuffer The buffer containing the input data + * @param[in] dim The width and height of the input data @n + * Both the width and height must be greater than @c 0. + * @param[in] format The format of the input data @n + * It must be one of the pixel formats extracted from GetSupportedFormatListN(). + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_SYSTEM A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @see FaceBuffer + */ + FaceBuffer* PreprocessDataN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, Tizen::Graphics::PixelFormat format); + + /** + * Searches for faces from the preprocessed data. + * + * @since 2.0 + * + * @return A list of the detected face positions @n + * Each list's item has a pointer of Tizen::Graphics::Rectangle value. @n + * An empty list, if there are no detected faces and there is no error. @n + * The faces are not detected when the faces are too small or the input data is not clear. @n + * This is the result of a normal operation, @n + * else @c null if an exception occurs. + * @param[in] preprocessedFaceBuffer The preprocessed data @n + * The @c preprocessedFaceBuffer must be obtained from PreprocessDataN(). + * @param[in] option The working option of detecting faces + * @exception E_SUCCESS The method is successful. + * @exception E_UNSUPPORTED_OPERATION The specified mode is not supported. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_SYSTEM A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @see FaceDetectorConfigProperty + */ + Tizen::Base::Collection::IList* DetectFacesN(const FaceBuffer& preprocessedFaceBuffer, FaceDetectionOption option = FACE_DETECTION_OPTION_FAST); + + /** + * Extracts the facial components information. + * + * @since 2.0 + * + * @return The facial components information, @n + * else @c null if an exception occurs + * @param[in] preprocessedFaceBuffer The preprocessed data @n + * The @c preprocessedFaceBuffer must be obtained from PreprocessDataN(). + * @param[in] faceRect The position of the detected face that is from DetectFacesN() @n + * The value of x and y positions for the @c faceRect parameter must be greater than or equal to @c 0. @n + * The value of width and height for the @c faceRect parameter must be greater than @c 0. @n + * The position of @c faceRect must be within @c preprocessedFaceBuffer. + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_SYSTEM A system error has occurred. + * @exception E_OPERATION_FAILED The method has failed to extract the facial information, but there is no error reported. @n + * This happens when the detected faces are too small or the input data is not clear. This is the result of a normal operation. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @see FaceComponentsPosition + */ + FaceComponentsPosition* ExtractFaceComponentsN(const FaceBuffer& preprocessedFaceBuffer, const Tizen::Graphics::Rectangle& faceRect); + + + /** + * Gets the position difference of the face. + * + * @since 2.0 + * + * @return An error code + * @param[in] prevData The buffer containing the previous video data + * @param[in] curData The buffer containing the current video data @n + * The size of @c prevData and @c curData must be the same. @n + * The @c prevData and @c curData must be gotten from PreprocessDataN(). + * @param[in] prevFaceRect The region of the face inside @c prevData @n + * The value of x and y positions for the @c prevFaceRect parameter must be greater than or equal to @c 0. @n + * The value of width and height for the @c prevFaceRect parameter must be greater than @c 0. @n + * The specified @c prevFaceRect must be within @c prevData. + * @param[out] xDiff The x offset that is moved from the previous to current video data + * @param[out] yDiff The y offset that is moved from the previous to current video data + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OPERATION_FAILED The method has failed to get the position difference of the specified region, but there is no error reported. @n + * In this case, @c xDiff and @c yDiff will be returned with @c 0. @n + * It can happen when the detected faces are too small or two video data are different even if they contain the same face. + * This is the result of a normal operation. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @remarks This can be used for tracking the face from a sequential video data. + * @see DetectFacesN() + */ + result GetFaceMovement(const FaceBuffer& prevData, const FaceBuffer& curData, const Tizen::Graphics::Rectangle& prevFaceRect, int& xDiff, int& yDiff); + +private: + /** + * The implementation of this copy constructor is intentionally blank and declared as private to prohibit copying of objects. + */ + FaceDetector(const FaceDetector& value); + /** + * The implementation of this copy assignment operator is intentionally blank and declared as private to prohibit copying of objects. + */ + FaceDetector& operator =(const FaceDetector& value); + friend class _FaceDetectorImpl; + +//Member variables +private: + _FaceDetectorImpl* __pFaceDetectorImpl; + +}; // FaceDetector + +} } } // Tizen::Uix::Vision + +#endif // _FUIX_VISION_FACE_DETECTOR_H_ diff --git a/inc/FUixVisionFaceRecognitionInfo.h b/inc/FUixVisionFaceRecognitionInfo.h new file mode 100755 index 0000000..605eb57 --- /dev/null +++ b/inc/FUixVisionFaceRecognitionInfo.h @@ -0,0 +1,136 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +/** + * @file FUixVisionFaceRecognitionInfo.h + * @brief This is the header file for the %FaceRecognitionInfo class. + * + * This header file contains the declarations of the %FaceRecognitionInfo class. + */ + +#ifndef _FUIX_VISION_FACE_RECOGNITION_INFO_H_ +#define _FUIX_VISION_FACE_RECOGNITION_INFO_H_ + +#include +#include +#include + +namespace Tizen { namespace Base{ +class ByteBuffer; +} } + +namespace Tizen { namespace Uix { namespace Vision +{ +class _FaceRecognizerImpl; + +/** + * @class FaceRecognitionInfo + * @brief This class encapsulates the information class of a recognized face using FaceRecognizer. + * + * @since 2.0 + * + * @remarks @b Header @b %file: @b \#include @b @n + * @b Library : @b osp-face + * + * The %FaceRecognitionInfo class encapsulates the information of a face recognized using the FaceRecognizer class by: + * - Getting the position of a recognized face. + * - Getting the facial features of a recognized face. + * @n + * For more information on the class features, see Face Detector and Recognizer. + */ + +class _OSP_EXPORT_ FaceRecognitionInfo + : public Tizen::Base::Object +{ +public: + /** + * This is the default constructor for this class. + * The object is not fully constructed after this constructor is called. + * For full construction, the Construct() method must be called right after calling this constructor. + * + * @since 2.0 + */ + FaceRecognitionInfo(void); + + /** + * This is the destructor for this class. @n + * The resources are deallocated by this method. + * This destructor overrides Tizen::Base::Object::~Object(). + * + * @since 2.0 + */ + virtual ~FaceRecognitionInfo(void); + +// Operation + /** + * Initializes this instance of %FaceRecognitionInfo with the specified parameter. + * + * @since 2.0 + * + * @return An error code + * @param[in] faceFeatures The face features obtained from the extract methods in the FaceRecognizer class + * @exception E_SUCCESS The method is successful. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @see FaceRecognizer::ExtractFaceInfoFromVideoStreamN() + * @see FaceRecognizer::ExtractFaceInfoFromStillImageN() + */ + result Construct(const Tizen::Base::ByteBuffer& faceFeatures); + + /** + * Gets the position of a recognized face. + * + * @since 2.0 + * + * @return The position of a recognized face + */ + Tizen::Graphics::Rectangle GetFacePosition(void) const; + + + /** + * Gets the facial features of a recognized face. + * + * @since 2.0 + * + * @return The facial features of a recognized face + */ + const Tizen::Base::ByteBuffer* GetFaceFeatures(void) const; + + +private: + /* + * The implementation of this copy constructor is intentionally blank and declared as private to prohibit copying of objects. + */ + FaceRecognitionInfo(const FaceRecognitionInfo& value); + /** + * The implementation of this copy assignment operator is intentionally blank and declared as private to prohibit copying of objects. + */ + FaceRecognitionInfo& operator =(const FaceRecognitionInfo& value); + + void SetFacePosition(int x, int y, int width, int height); + +private: + Tizen::Graphics::Rectangle __faceRect; + Tizen::Base::ByteBuffer* __pfaceFeatures; + + friend class _FaceRecognizerImpl; + +}; // FaceRecognitionInfo + +} } } // Tizen::Uix::Vision + +#endif diff --git a/inc/FUixVisionFaceRecognizer.h b/inc/FUixVisionFaceRecognizer.h new file mode 100755 index 0000000..53c5e9b --- /dev/null +++ b/inc/FUixVisionFaceRecognizer.h @@ -0,0 +1,547 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +/** + * @file FUixVisionFaceRecognizer.h + * @brief This is the header file for the %FaceRecognizer class. + * + * This header file contains the declarations of the %FaceRecognizer class. + */ + +#ifndef _FUIX_VISION_FACE_RECOGNIZER_H_ +#define _FUIX_VISION_FACE_RECOGNIZER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Tizen { namespace Base +{ +class ByteBuffer; +} } + +namespace Tizen { namespace Base { namespace Collection +{ +class IList; +template class IListT; +template class IMapT; +} } } + +namespace Tizen { namespace Graphics +{ +class Bitmap; +class Dimension; +class Rectangle; +} } + +namespace Tizen { namespace Uix { namespace Vision +{ +class _FaceRecognizerImpl; + +/** + * @class FaceRecognizer + * @brief This class provides methods to recognize a face in an image or a video. + * + * @since 2.0 + * + * @remarks @b Header @b %file: @b \#include @b @n + * @b Library : @b osp-face + * + * The %FaceRecognizer class provides the ability to automatically recognize faces in a still image or video stream. + * @n + * For more information on the class features, see Face Detector and Recognizer. + * + * The following example demonstrates how to use the %FaceRecognizer class. + * + * @code + * #include + * #include + * #include + * #include + * #include + * + * using namespace Tizen::Base; + * using namespace Tizen::Media; + * using namespace Tizen::Graphics; + * using namespace Tizen::Io; + * using namespace Tizen::Uix::Vision; + * + * result + * MyClass::TestFaceRecognize(void) + * { + * ByteBuffer* pByteBuffer1 = null, * pByteBuffer2 = null; + * int width1 = 0, height1 = 0, width2 = 0, height2 = 0; + * result r; + * + * Image * pImage = new Image(); + * r = pImage->Construct(); + * + * String path1(L"test1.bmp"); + * String path2(L"test2.bmp"); + * + * pByteBuffer1 = pImage->DecodeToBufferN(path1, BITMAP_PIXEL_FORMAT_RGB565,width1,height1 ); + * pByteBuffer2 = pImage->DecodeToBufferN(path2, BITMAP_PIXEL_FORMAT_RGB565,width2,height2 ); + * + * //Deletes the image object + * delete pImage; + * + * if (pByteBuffer1 && pByteBuffer2) + * { + * FaceRecognizer faceRecog; + * r = faceRecog.Construct(); + * const Tizen::Base::Collection::IList* pFaceDetectList1 = faceRecog.ExtractFaceInfoFromStillImageN(*pByteBuffer1, Dimension(width1,height1), BITMAP_PIXEL_FORMAT_RGB565); + * const Tizen::Base::Collection::IList* pFaceDetectList2 = faceRecog.ExtractFaceInfoFromStillImageN(*pByteBuffer2, Dimension(width2,height2), BITMAP_PIXEL_FORMAT_RGB565); + * + * if(pFaceDetectList1 == null || pFaceDetectList2 == null) + * { + * delete pByteBuffer1; + * delete pByteBuffer2; + * return GetLastResult(); + * } + * + * FaceRecognitionInfo* pFInfo1 = null, *pFInfo2 = null; + * for(int i=0; i < pFaceDetectList1->GetCount(); i++) + * { + * pFInfo1 = (Tizen::Uix::FaceRecognitionInfo*)pFaceDetectList1->GetAt(i); + * for(int j=0; j < pFaceDetectList2->GetCount(); j++) + * { + * pFInfo2 = (Tizen::Uix::FaceRecognitionInfo*)pFaceDetectList2->GetAt(j); + * if(faceRecog.IsMatching(*pFInfo1, *pFInfo2)) + * { + * Tizen::Graphics::Rectangle rect1 = (Tizen::Graphics::Rectangle)pFInfo1->GetFacePosition(); + * } + * } + * } + * + * delete pByteBuffer1; + * delete pByteBuffer2; + * } + * return r; + * } + * @endcode + */ +class _OSP_EXPORT_ FaceRecognizer + : public Tizen::Base::Object +{ + +// Lifecycle +public: + /** + * This is the default constructor for this class. @n + * The object is not fully constructed after this constructor is called. + * For full construction, the Construct() method must be called right after calling this constructor. + * + * @since 2.0 + */ + FaceRecognizer(void); + + /** + * This is the destructor for this class. @n + * The resources are deallocated by this method. + * This destructor overrides Tizen::Base::Object::~Object(). + * + * @since 2.0 + */ + virtual ~FaceRecognizer(void); + + +// Operation + + /** + * Initializes an instance of %FaceRecognizer. + * + * @since 2.0 + * + * @return An error code + * @exception E_SUCCESS The method is successful. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + */ + result Construct(void); + + /** + * Gets the range and default value of the specified configuration property. + * + * @since 2.0 + * + * @return An error code + * @param[in] configProperty The property to query + * @param[out] min The minimum value of the property + * @param[out] max The maximum value of the property + * @param[out] steppingDelta The step size of the property @n + * The step size is the smallest increment by which the property can be changed. + * @param[out] defaultVal The default value of the property + * @exception E_SUCCESS The method is successful. + * @exception E_UNSUPPORTED_OPERATION The device does not support the specified configuration property. + */ + result GetRange(FaceRecognizerConfigProperty configProperty, long& min, long& max, long& steppingDelta, long& defaultVal) const; + + /** + * Sets the value of the specified property. + * + * @since 2.0 + * + * @return An error code + * @param[in] configProperty The property to query + * @param[in] value The new value of the property + * @exception E_SUCCESS The method is successful. + * @exception E_UNSUPPORTED_OPERATION The device does not support the specified configuration property. + * @exception E_OUT_OF_RANGE The specified @c value is out of range. + * @see GetRange() + */ + result SetProperty(FaceRecognizerConfigProperty configProperty, long value); + + /** + * Gets the current setting of the specified configuration property. + * + * @since 2.0 + * + * @return The value of the property, @n + * else @c -1 if an exception occurs + * @param[in] configProperty The property to query + * @exception E_SUCCESS The method is successful. + * @exception E_UNSUPPORTED_OPERATION The device does not support the specified configuration property. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + long GetProperty(FaceRecognizerConfigProperty configProperty) const; + + /** + * Gets a list of supported pixel formats. + * + * @since 2.0 + * + * @return A list of the supported pixel formats that are used in ExtractFaceInfoFromVideoStreamN() @n + * The format is in the form of a string. + * @exception E_SUCCESS The method is successful. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::Collection::IListT * GetSupportedFormatListN(void) const; + + /** + * Extracts the facial template that represents the face from a video. + * + * @since 2.0 + * + * @return A list of the FaceRecognitionInfo instances that contain the extracted facial features, @n + * else @c null if an exception occurs @n + * Each list's item has a pointer to the %FaceRecognitionInfo value. @n + * An empty list, if there are no detected faces and there is no error. @n + * The faces are not detected when the faces are too small, or when the video data is not + * clear. + * This is the result of a normal operation. + * @param[in] byteBuffer A pointer to the buffer containing the video data + * @param[in] dim The width and height of the video data @n + * Both the width and height must be greater than @c 0. + * @param[in] format The format of the video data @n + * It must be one of the pixel formats extracted from GetSupportedFormatListN(). + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid, or + * the specified @c format is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_FAILURE A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::Collection::IList* ExtractFaceInfoFromVideoStreamN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, const Tizen::Graphics::PixelFormat format); + + /** + * @if OSPDEPREC + * Extracts the facial template that represents the face from the still image. + * + * @brief [Deprecated] + * @deprecated This method is deprecated as it may return an improper result. + * Instead of using this method, use ExtractFaceInfoFromStillImageN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, Tizen::Graphics::BitmapPixelFormat format). + * To optimize the memory usage and processing time, the bitmap scales down an image + * by decreasing its resolution in some models, that in turn decreases the accuracy of the face library. + * Therefore, the usage of this method using Tizen::Base::ByteBuffer is encouraged. + * @since 2.0 + * + * @return A list of the FaceRecognitionInfo instances that contain the extracted facial features, @n + * else @c null if an exception occurs @n + * Each list's item has a pointer to the %FaceRecognitionInfo value. @n + * An empty list, if there are no detected faces and there is no error. @n + * The faces are not detected when the faces are too small or the image is not clear. + * This is the result of a normal operation. + * @param[in] bitmap The bitmap file containing the input image data + * @exception E_SUCCESS The method is successful. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_FAILURE A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @remarks BitmapPixelFormat::BITMAP_PIXEL_FORMAT_R8G8B8A8 is not applicable for this method. + * @endif + */ + Tizen::Base::Collection::IList* ExtractFaceInfoFromStillImageN(const Tizen::Graphics::Bitmap& bitmap); + + /** + * Extracts the facial template that represents the face from the still image. + * + * @since 2.0 + * + * @return A list of the FaceRecognitionInfo instances that contain the extracted facial features, @n + * else @c null if an exception occurs @n + * Each list's item has a pointer to the %FaceRecognitionInfo value. @n + * An empty list, if there are no detected faces and there is no error. @n + * The faces are not detected when the faces are too small or the image is not clear. + * This is the result of a normal operation. + * @param[in] byteBuffer The buffer containing the input image data + * @param[in] dim The width and height of the input image @n + * Both the width and height must be greater than @c 0. + * @param[in] format The color format defined by Tizen::Graphics::BitmapPixelFormat + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_FAILURE A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @remarks BitmapPixelFormat::BITMAP_PIXEL_FORMAT_R8G8B8A8 is not applicable for this method. + */ + Tizen::Base::Collection::IList* ExtractFaceInfoFromStillImageN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, Tizen::Graphics::BitmapPixelFormat format); + + /** + * Checks whether the two specified faces match. + * + * @since 2.0 + * + * @return @c true if the two faces match, @n + * else @c false + * @param[in] face1 The face information of the first face + * @param[in] face2 The face information of the second face + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid, or a specified FaceRecognitionInfo is not constructed. + * @exception E_FAILURE A system error has occurred. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + bool IsMatching(const FaceRecognitionInfo& face1, const FaceRecognitionInfo& face2); + + /** + * Gets the similarity of the two specified faces. + * + * @since 2.0 + * + * @return The degree of similarity in percentage @n + * The range is from @c 0 to @c 100. @c 100 means the faces are the same, and @c 0 means there is no similarity at all between the two faces, @n + * else @c -1 if an exception occurs. + * @param[in] face1 The face information of the first face + * @param[in] face2 The face information of the second face + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid, or a specified FaceRecognitionInfo is not constructed. + * @exception E_FAILURE A system error has occurred. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + int MeasureSimilarity(const FaceRecognitionInfo& face1, const FaceRecognitionInfo& face2); + + /** + * Extracts the facial template that represents a face. + * + * @since 2.0 + * + * @return The facial features of a recognized face, @n + * else @c null if an exception occurs + * @param[in] preprocessedFaceBuffer The preprocessed data + * @param[in] faceComponentPos The facial information that is obtained from the + * ExtractFaceComponentsN() method @n + * The @c faceComponentPos parameter must contain the eye position. + * The position of the eyes must be greater than or equal to @c 0. + * The position of the eyes must be within @c preprocessedFaceBuffer. + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_SYSTEM A system error has occurred. + * @exception E_OPERATION_FAILED The method has failed to extract the facial information but there is no error reported. @n + * This can happen when the detected faces are too small or the input data is not clear. + * This is the result of a normal operation. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @remarks If there are wrong values in the @c faceComponentPos, the result cannot be guaranteed even if it returns @c E_SUCCESS. Therefore, be sure not to change the value of @c faceComponentPos after getting it from ExtractFaceComponentsN(). + * @see FaceDetector::PreprocessDataN() + * @see FaceDetector::ExtractFaceComponentsN() + */ + Tizen::Base::ByteBuffer* ExtractFeatureN(const FaceBuffer& preprocessedFaceBuffer, const FaceComponentsPosition& faceComponentPos); + + /** + * Detects the eye status. + * + * @since 2.0 + * + * @return The eye status, @n + * else @c EYE_STATE_NONE if an exception occurs + * @param[in] preprocessedFaceBuffer The preprocessed data + * @param[in] faceComponentPos The facial information that is obtained from the FaceDetector::ExtractFaceComponentsN() method @n + * The @c faceComponentPos parameter must contain the eye position. + * The position of the eyes must be greater than or equal to @c 0. + * The position of the eyes must be within @c preprocessedFaceBuffer. + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_SYSTEM A system error has occurred. + * @exception E_OPERATION_FAILED The method has failed to detect the eye state but there is no error reported. @n + * This can happen when the detected faces are too small or the input data is not clear. + * This is the result of a normal operation. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @remarks If there are wrong values in the @c faceComponentPos, the result cannot be guaranteed even if it returns @c E_SUCCESS. + * Therefore, be sure not to change the value of @c faceComponentPos after getting it from ExtractFaceComponentsN(). + * @see FaceDetector::PreprocessDataN() + */ + EyeState GetEyeState(const FaceBuffer& preprocessedFaceBuffer, const FaceComponentsPosition& faceComponentPos); + + /** + * Recognizes the facial expression. + * + * @since 2.0 + * + * @return The facial expression, @n + * else @c FACIAL_EXPRESSION_NONE if an exception occurs + * @param[in] preprocessedFaceBuffer The preprocessed data + * @param[in] faceComponentPos The facial information that is obtained from the FaceDetector::ExtractFaceComponentsN() method @n + * The @c faceComponentPos parameter must contain the eye position. + * The position of the eyes must be greater than or equal to @c 0. + * The position of the eyes must be within @c preprocessedFaceBuffer. + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_SYSTEM A system error has occurred. + * @exception E_OPERATION_FAILED The method has failed to extract the facial expression but there is no error reported. @n + * This can happen when the detected faces are too small or the input data is not clear. + * This is the result of a normal operation. + * @remarks The specific error code can be accessed using the GetLastResult() method. + * @remarks If there are wrong values in the @c faceComponentPos, the result cannot be guaranteed even if it returns @c E_SUCCESS. Therefore, + * be sure not to change the value of @c faceComponentPos after getting it from ExtractFaceComponentsN(). + * @see FaceDetector::PreprocessDataN() + */ + FacialExpression RecognizeExpression(const FaceBuffer& preprocessedFaceBuffer, const FaceComponentsPosition& faceComponentPos); + + /** + * Detects the eye states from a video. + * + * @since 2.0 + * + * @return A list of eye states, @n + * else @c null if an exception occurs @n + * Each list's item has an EyeState value. @n + * An empty list, if there are no detected eye states and there is no error. @n + * The eye states are not detected when the faces are too small or the video data is not clear. + * This is the result of a normal operation. + * @param[in] byteBuffer The buffer containing the video data + * @param[in] dim The width and height of the video data @n + * Both the width and height must be greater than @c 0. + * @param[in] format The format of the video data @n + * It must be one of the pixel formats extracted from GetSupportedFormatListN(). + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_SYSTEM A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::Collection::IMapT * DetectBlinksFromVideoStreamN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, const Tizen::Graphics::PixelFormat format); + + + /** + * Detects the eye states from a still image. + * + * @since 2.0 + * + * @return The list of eye states, @n + * else @c null if an exception occurs @n + * Each list's item has an EyeState value. @n + * An empty list, if there are no detected eye states and there is no error. @n + * The eye states are not detected when the faces are too small or the video data is not clear. + * This is the result of a normal operation. + * @param[in] byteBuffer The buffer containing the input image data + * @param[in] dim The width and height of the input image @n + * Both the width and height must be greater than @c 0. + * @param[in] format The color format defined by Tizen::Graphics::BitmapPixelFormat + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_SYSTEM A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::Collection::IMapT * DetectBlinksFromStillImageN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, Tizen::Graphics::BitmapPixelFormat format); + + /** + * Recognizes the facial expressions from a video. + * + * @since 2.0 + * + * @return A list of facial expressions, @n + * else @c null if an exception occurs @n + * Each list's item has a FacialExpression value. @n + * An empty list, if there are no recognized facial expression and there is no error. @n + * The expressions are not recognized when the faces are too small or the video data is not clear. + * This is the result of a normal operation. + * @param[in] byteBuffer The buffer containing the video data + * @param[in] dim The width and height of the video data @n + * Both the width and height must be greater than @c 0. + * @param[in] format The format of the video data @n + * It must be one of the pixel formats extracted from GetSupportedFormatListN(). + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_SYSTEM A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::Collection::IMapT * RecognizeExpressionsFromVideoStreamN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, const Tizen::Graphics::PixelFormat format); + + + /** + * Recognizes the facial expressions from the still image. + * + * @since 2.0 + * + * @return A list of the facial expressions, @n + * else @c null if an exception occurs @n + * Each list's item has a FacialExpression value. @n + * An empty list, if there are no recognized facial expression and there is no error. @n + * The expressions are not recognized when the faces are too small or the image is not clear. + * This is the result of a normal operation. + * @param[in] byteBuffer The buffer containing the input image data + * @param[in] dim The width and height of the input image @n + * Both the width and height must be greater than @c 0. + * @param[in] format The color format defined by Tizen::Graphics::BitmapPixelFormat + * @exception E_SUCCESS The method is successful. + * @exception E_INVALID_ARG A specified input parameter is invalid. + * @exception E_OUT_OF_MEMORY The memory is insufficient. + * @exception E_SYSTEM A system error has occurred. + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::Collection::IMapT * RecognizeExpressionsFromStillImageN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, Tizen::Graphics::BitmapPixelFormat format); + + +private: + /** + * The implementation of this copy constructor is intentionally blank and declared as private to prohibit copying of objects. + */ + FaceRecognizer(const FaceRecognizer& value); + /** + * The implementation of this copy assignment operator is intentionally blank and declared as private to prohibit copying of objects. + */ + FaceRecognizer& operator =(const FaceRecognizer& value); + friend class _FaceRecognizerImpl; + +private: + _FaceRecognizerImpl* __pFaceRecognizerImpl; + +}; // FaceRecognizer + +} } } // Tizen::Uix::Vision + +#endif diff --git a/inc/FUixVisionFaceTypes.h b/inc/FUixVisionFaceTypes.h new file mode 100755 index 0000000..33c7a4e --- /dev/null +++ b/inc/FUixVisionFaceTypes.h @@ -0,0 +1,199 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVisionFaceTypes.h + * @brief This is the header file for the declarations of the Tizen::Uix::Vision namespace. + * + * This header file contains the declarations of the Tizen::Uix::Vision namespace. + */ + +#ifndef _FUIX_VISION_FACE_TYPES_H_ +#define _FUIX_VISION_FACE_TYPES_H_ + +namespace Tizen { namespace Uix { namespace Vision +{ + +/** + * @enum FaceDetectorConfigProperty + * + * Defines the configuration properties of a FaceDetector. + * + * @since 2.0 + * + * @see FaceDetector::GetRange() + * @see FaceDetector::GetProperty() + */ +enum FaceDetectorConfigProperty +{ + /** + * The maximum number of faces to detect from a video stream. @n + * This will be used when FaceDetector::DetectFacesFromVideoStreamN() is called. + */ + FACEDETECTOR_MAXNUMBER_VIDEO, + + /** + * The maximum number of faces to detect from a still image. @n + * This will be used when FaceDetector::DetectFacesFromStillImageN() is called. + */ + FACEDETECTOR_MAXNUMBER_IMAGE, + + /** + * The minimum ratio of detectable faces is relative to the size of a video stream. @n + * The range is from values @c 1 to @c 3, where the value @c 1 has the longest execution time and @c 3 + * has the shortest execution time. The value @c 1 detects small faces. + * Therefore, for an application using a camera or a video file, the value @c 3 is an appropriate option. + * The value @c 3 is used when FaceDetector::DetectFacesFromVideoStreamN() is called unless it has been changed earlier + * using the FaceDetector::SetProperty() method. @n + * + * This will be used when %FaceDetector::DetectFacesFromVideoStreamN() is called. + */ + FACEDETECTOR_SCALE_VIDEO, + + /** + * The minimum ratio of detectable faces is relative to the size of a still image. @n + * The range is from values @c 1 to @c 3, where the value @c 1 has the longest execution time and @c 3 has + * the shortest execution time. The value @c 1 detects small faces. + * Therefore, for an application handling images, the value @c 1 is an appropriate option. + * The value @c 1 is used when FaceDetector::DetectFacesFromStillImageN() is called unless it has been changed + * earlier using the FaceDetector::SetProperty() method. @n + * + * This will be used when %FaceDetector::DetectFacesFromStillImageN() is called. + */ + FACEDETECTOR_SCALE_IMAGE, + + /** + * The maximum number of faces to detect. @n + * The value @c 1 is used when DetectFacesN() is called unless it has been changed earlier + * using the FaceDetector::SetProperty() method. @n + * This will be used when FaceDetector::DetectFacesN() is called. + */ + FACEDETECTOR_MAXNUMBER_FACES, + + /** + * The minimum ratio of detectable faces relative to the input data. @n + * The range is from values @c 1 to @c 3, where the value @c 1 has the longest execution time and @c 3 + * has the shortest execution time. The value @c 1 detects small faces. + * The value @c 3 is used when FaceDetector::DetectFacesN() is called unless it has been changed earlier using + * the FaceDetector::SetProperty() method. @n + * + * This will be used when %FaceDetector::DetectFacesN() is called. + */ + FACEDETECTOR_SCALE_FACTOR, +}; + +/** + * @enum FaceRecognizerConfigProperty + * + * Defines the configuration properties of a FaceRecognizer. + * + * @since 2.0 + * + * @see FaceRecognizer::GetRange() + * @see FaceRecognizer::GetProperty() + */ +enum FaceRecognizerConfigProperty +{ + /** + * The maximum number of faces to extract face information from a video stream. @n + * This will be used when FaceRecognizer::ExtractFaceInfoFromVideoStreamN() is called. + */ + FACERECOGNIZER_MAXNUMBER_VIDEO, + + /** + * The maximum number of faces to extract face information from a still image. @n + * This will be used when FaceRecognizer::ExtractFaceInfoFromStillImageN() is called. + */ + FACERECOGNIZER_MAXNUMBER_IMAGE, + + /** + * The minimum ratio of the detectable faces relative to the size of a video stream. @n + * The range is from values @c 1 to @c 3, where the value @c 1 has the longest execution time and @c 3 has + * the shortest execution time. The value @c 1 detects small faces. + * Therefore, for an application using a camera or a video file, the value @c 3 is an appropriate option. + * The value @c 3 is used when ExtractFaceInfoFromVideoStreamN() is called unless it has been changed + * earlier using the FaceDetector::SetProperty() method. @n + * + * This will be used when FaceRecognizer::ExtractFaceInfoFromVideoStreamN() is called. + */ + FACERECOGNIZER_SCALE_VIDEO, + + /** + * The minimum ratio of the detectable faces relative to the size of a still image. @n + * The range is from values @c 1 to @c 3, where the value @c 1 has the longest execution time and @c 3 has + * the shortest execution time. + * The value @c 1 detects small faces. + * Therefore, for an application handling images, the value @c 1 is an appropriate option. + * The value @c 1 is used when ExtractFaceInfoFromStillImageN() is called unless it has been changed + * earlier using the FaceDetector::SetProperty() method. @n + * + * This will be used when FaceRecognizer::ExtractFaceInfoFromStillImageN() is called. + */ + FACERECOGNIZER_SCALE_IMAGE, +}; + +/** + * @enum FaceDetectionOption + * + * Defines the face detection options. + * + * @since 2.0 + * + * @see FaceDetector::DetectFacesN() + */ +enum FaceDetectionOption +{ + FACE_DETECTION_OPTION_FAST, /**< The option to detect faces as fast as possible even if the accuracy is low */ + FACE_DETECTION_OPTION_ROBUST, /**< The option to detect faces as accurate as possible even if it takes more time */ +}; + +/** + * @enum EyeState + * + * Defines the eye state. + * + * @since 2.0 + * + * @see FaceRecognizer::GetEyeState() + */ +enum EyeState +{ + EYE_STATE_NONE, /**< The no eye state, when the eye detect fails */ + EYE_STATE_BOTH_OPEN, /**< The state when both eyes are open */ + EYE_STATE_BOTH_CLOSED, /**< The state when both eyes are closed */ +}; + +/** + * @enum FacialExpression + * + * Defines the facial expressions. + * + * @since 2.0 + * + * @see FaceRecognizer::RecognizeExpression() + */ +enum FacialExpression +{ + FACIAL_EXPRESSION_NONE, /**< The no face expression, when the face recognition fails */ + FACIAL_EXPRESSION_NEUTRAL, /**< The neutral face expression */ + FACIAL_EXPRESSION_ANGRY, /**< The angry face expression */ + FACIAL_EXPRESSION_HAPPY, /**< The happy face expression */ + FACIAL_EXPRESSION_SURPRISED, /**< The surprised face expression */ +}; + +} } } // Tizen::Uix::Vision +#endif diff --git a/osp-face.manifest b/osp-face.manifest new file mode 100644 index 0000000..ae3e6f7 --- /dev/null +++ b/osp-face.manifest @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/osp-face.pc.in b/osp-face.pc.in new file mode 100755 index 0000000..eb6c3b7 --- /dev/null +++ b/osp-face.pc.in @@ -0,0 +1,14 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=/usr/lib/osp +includedir=/usr/include/osp + +Name: @PC_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} + diff --git a/packaging/osp-face.spec b/packaging/osp-face.spec new file mode 100755 index 0000000..6c7ce57 --- /dev/null +++ b/packaging/osp-face.spec @@ -0,0 +1,75 @@ +%define debug_package %{nil} +%define __strip /bin/true + +Name: osp-face +Summary: osp face library +Version: 1.2.0.0 +Release: 2 +Group: System/Libraries +License: TO_BE/FILLED_IN +Source0: %{name}-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: capi-uix-face-devel +BuildRequires: pkgconfig(osp-appfw) +BuildRequires: osp-appfw-internal-devel +BuildRequires: pkgconfig(osp-uifw) +BuildRequires: osp-uifw-internal-devel + +# runtime requires +Requires: osp-appfw + +%description +osp face library + +%package devel +Summary: osp face library (Development) +Group: TO_BE/FILLED_IN +Requires: %{name} = %{version}-%{release} + +%description devel +osp face library (DEV) + +%package debug +Summary: osp face library (Development) +Group: TO_BE/FILLED_IN +Requires: %{name} = %{version}-%{release} + +%description debug +osp face library (DEV) + +%prep +%setup -q + +%build +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` +%ifarch %{ix86} +CXXFLAGS="$CXXFLAGS -D_OSP_DEBUG_ -D_OSP_X86_ -D_OSP_EMUL_" cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DFULLVER=%{version} -DMAJORVER=${MAJORVER} +%else +CXXFLAGS="-O2 -g -pipe -Wall -fno-exceptions -Wformat -Wformat-security -Wl,--as-needed -fmessage-length=0 -march=armv7-a -mtune=cortex-a8 -mlittle-endian -mfpu=neon -mfloat-abi=softfp -D__SOFTFP__ -mthumb -Wa,-mimplicit-it=thumb -funwind-tables -D_OSP_DEBUG_ -D_OSP_ARMEL_" cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DFULLVER=%{version} -DMAJORVER=${MAJORVER} +%endif + +# Call make instruction with smp support +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}/usr/share/license +cp %{_builddir}/%{name}-%{version}/LICENSE %{buildroot}/usr/share/license/%{name} + +%make_install + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%manifest osp-face.manifest +/usr/share/license/%{name} +%{_libdir}/osp/*.so* + +%files devel +%{_includedir}/osp/*.h +%{_libdir}/pkgconfig/osp-face.pc + +%files debug +%{_libdir}/osp/debug/*.so* \ No newline at end of file diff --git a/src/FUixVisionFaceBuffer.cpp b/src/FUixVisionFaceBuffer.cpp new file mode 100755 index 0000000..3b17763 --- /dev/null +++ b/src/FUixVisionFaceBuffer.cpp @@ -0,0 +1,74 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/** + * @file FUixVisionFaceBuffer.cpp + * @brief This is the implementation file for the %FaceBuffer class. + * + * This files contains implementation of the %FaceBuffer class. + */ + +// Includes +#include +#include +#include +#include +#include +#include + +namespace Tizen { namespace Uix { namespace Vision +{ + +FaceBuffer::FaceBuffer(void) + : __pBuffer(null) + , __resolution(0, 0) +{ + +} + +FaceBuffer::~FaceBuffer(void) +{ + if (__pBuffer != null) + { + delete __pBuffer; + __pBuffer = null; + } +} + +FaceBuffer::FaceBuffer(const Tizen::Base::ByteBuffer& buffer, const Tizen::Graphics::Dimension& resolution) +{ + __pBuffer = new (std::nothrow) Tizen::Base::ByteBuffer; + SysTryReturn(NID_UIX, __pBuffer != null, , E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + __pBuffer->Construct(buffer); + + __resolution.width = resolution.width; + __resolution.height = resolution.height; +} + +Tizen::Graphics::Dimension +FaceBuffer::GetDimension(void) const +{ + return __resolution; +} + +const Tizen::Base::ByteBuffer* +FaceBuffer::GetBuffer(void) const +{ + return __pBuffer; +} + +} } } //Tizen::Uix::Vision \ No newline at end of file diff --git a/src/FUixVisionFaceComponentsPosition.cpp b/src/FUixVisionFaceComponentsPosition.cpp new file mode 100755 index 0000000..fc88a9d --- /dev/null +++ b/src/FUixVisionFaceComponentsPosition.cpp @@ -0,0 +1,188 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVisionFaceComponentsPosition.cpp + * @brief This is the implementation file for the %FaceComponentsPosition class. + * + * This files contains implementation of the %FaceComponentsPosition class. + */ + +// Includes +#include +#include +#include +#include +#include + +namespace Tizen { namespace Uix { namespace Vision +{ + +FaceComponentsPosition::FaceComponentsPosition(void) + : __faceRect(-1, -1, -1, -1) + , __eyeRight(-1, -1) + , __eyeLeft(-1, -1) + , __mouthRect(-1, -1, -1, -1) +{ + +} + +FaceComponentsPosition::~FaceComponentsPosition(void) +{ + +} + +FaceComponentsPosition::FaceComponentsPosition(const Tizen::Graphics::Rectangle& faceRect) + : __eyeRight(-1, -1) + , __eyeLeft(-1, -1) + , __mouthRect(-1, -1, -1, -1) +{ + __faceRect.x = faceRect.x; + __faceRect.y = faceRect.y; + __faceRect.width = faceRect.width; + __faceRect.height = faceRect.height; +} + +FaceComponentsPosition::FaceComponentsPosition(const Tizen::Graphics::Rectangle& faceRect, const Tizen::Graphics::Point& eyeRight, const Tizen::Graphics::Point& eyeLeft) + : __mouthRect(-1, -1, -1, -1) +{ + __faceRect.x = faceRect.x; + __faceRect.y = faceRect.y; + __faceRect.width = faceRect.width; + __faceRect.height = faceRect.height; + + __eyeRight.x = eyeRight.x; + __eyeRight.y = eyeRight.y; + __eyeLeft.x = eyeLeft.x; + __eyeLeft.y = eyeLeft.y; +} + +Tizen::Graphics::Rectangle +FaceComponentsPosition::GetFacePosition(void) const +{ + return __faceRect; +} + +void +FaceComponentsPosition::GetEyePosition(Tizen::Graphics::Point& eyeLeft, Tizen::Graphics::Point& eyeRight) const +{ + eyeRight.x = __eyeRight.x; + eyeRight.y = __eyeRight.y; + eyeLeft.x = __eyeLeft.x; + eyeLeft.y = __eyeLeft.y; +} + +Tizen::Graphics::Rectangle +FaceComponentsPosition::GetMouthPosition(void) const +{ + return __mouthRect; +} + +result +FaceComponentsPosition::SetEyePosition(const Tizen::Graphics::Point& eyeLeft, const Tizen::Graphics::Point& eyeRight) +{ + SysTryReturn(NID_UIX, eyeLeft.x > 0 && eyeLeft.y > 0 && eyeRight.x > 0 && eyeRight.y > 0, E_INVALID_ARG, E_INVALID_ARG, + "[%s] The position of eyes should be greater or equal 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryReturn(NID_UIX, eyeRight.x > eyeLeft.x, E_INVALID_ARG, E_INVALID_ARG, + "[%s] The position of eyeRight should be greater than the position of eyeLeft.", GetErrorMessage(E_INVALID_ARG)); + + __eyeRight.x = eyeRight.x; + __eyeRight.y = eyeRight.y; + __eyeLeft.x = eyeLeft.x; + __eyeLeft.y = eyeLeft.y; + + return E_SUCCESS; +} + +result +FaceComponentsPosition::SetMouthPosition(const Tizen::Graphics::Rectangle& mouthRect) +{ + SysTryReturn(NID_UIX, mouthRect.x >= 0 && mouthRect.y >= 0, E_INVALID_ARG, E_INVALID_ARG, + "[%s] The x and y of the mouthRect should be greater or equal 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryReturn(NID_UIX, mouthRect.width > 0 && mouthRect.height > 0, E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width and height of the mouthRect should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + __mouthRect.x = mouthRect.x; + __mouthRect.y = mouthRect.y; + __mouthRect.width = mouthRect.width; + __mouthRect.height = mouthRect.height; + + return E_SUCCESS; +} + +result +FaceComponentsPosition::SetFacePosition(const Tizen::Graphics::Rectangle& faceRect) +{ + SysTryReturn(NID_UIX, faceRect.x >= 0 && faceRect.y >= 0, E_INVALID_ARG, E_INVALID_ARG, + "[%s] The x and y of the faceRect should be greater or equal 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryReturn(NID_UIX, faceRect.width > 0 && faceRect.height > 0, E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width and height of the mouthRect should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + __faceRect.x = faceRect.x; + __faceRect.y = faceRect.y; + __faceRect.width = faceRect.width; + __faceRect.height = faceRect.height; + + return E_SUCCESS; +} + +FaceComponentsPosition::FaceComponentsPosition(const FaceComponentsPosition& rhs) +{ + __eyeLeft.x = rhs.__eyeLeft.x; + __eyeLeft.y = rhs.__eyeLeft.y; + + __eyeRight.x = rhs.__eyeRight.x; + __eyeRight.y = rhs.__eyeRight.y; + + __faceRect.x = rhs.__faceRect.x; + __faceRect.y = rhs.__faceRect.y; + __faceRect.width = rhs.__faceRect.width; + __faceRect.height = rhs.__faceRect.height; + + __mouthRect.x = rhs.__mouthRect.x; + __mouthRect.y = rhs.__mouthRect.y; + __mouthRect.width = rhs.__mouthRect.width; + __mouthRect.height = rhs.__mouthRect.height; +} + +FaceComponentsPosition& +FaceComponentsPosition::operator =(const FaceComponentsPosition& rhs) +{ + if (&rhs == this) + { + return *this; + } + this->__eyeLeft.x = rhs.__eyeLeft.x; + this->__eyeLeft.y = rhs.__eyeLeft.y; + + this->__eyeRight.x = rhs.__eyeRight.x; + this->__eyeRight.y = rhs.__eyeRight.y; + + this->__faceRect.x = rhs.__faceRect.x; + this->__faceRect.y = rhs.__faceRect.y; + this->__faceRect.width = rhs.__faceRect.width; + this->__faceRect.height = rhs.__faceRect.height; + + this->__mouthRect.x = rhs.__mouthRect.x; + this->__mouthRect.y = rhs.__mouthRect.y; + this->__mouthRect.width = rhs.__mouthRect.width; + this->__mouthRect.height = rhs.__mouthRect.height; + + return *this; +} + +} } } //Tizen::Uix::Vision diff --git a/src/FUixVisionFaceDetector.cpp b/src/FUixVisionFaceDetector.cpp new file mode 100755 index 0000000..3cc0bea --- /dev/null +++ b/src/FUixVisionFaceDetector.cpp @@ -0,0 +1,390 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVisionFaceDetector.cpp + * @brief This is the implementation file for the %FaceDetector class. + * + * This files contains implementation of the %FaceDetector class. + */ + +// Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "FUixVision_FaceDetectorImpl.h" + +namespace Tizen { namespace Uix { namespace Vision +{ + +FaceDetector::FaceDetector(void) + : __pFaceDetectorImpl(null) +{ + +} + +FaceDetector::~FaceDetector(void) +{ + if (__pFaceDetectorImpl != null) + { + delete __pFaceDetectorImpl; + __pFaceDetectorImpl = null; + } +} + +result +FaceDetector::Construct(void) +{ + SysAssertf(__pFaceDetectorImpl == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class."); + + result r = E_SUCCESS; + + std::unique_ptr<_FaceDetectorImpl> pFaceDetectorImpl (new (std::nothrow) _FaceDetectorImpl()); + SysTryReturn(NID_UIX, pFaceDetectorImpl != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pFaceDetectorImpl->Construct(); + SysTryReturn(NID_UIX, r == E_SUCCESS, r, r,"[%s] Propagating.", GetErrorMessage(r)); + + __pFaceDetectorImpl = pFaceDetectorImpl.release(); + + return r; +} + +result +FaceDetector::GetRange(FaceDetectorConfigProperty configProperty, long& min, long& max, long& steppingDelta, + long& defaultVal) const +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + SysTryReturn(NID_UIX, configProperty >= FACEDETECTOR_MAXNUMBER_VIDEO && configProperty <= FACEDETECTOR_SCALE_FACTOR, + E_UNSUPPORTED_OPERATION, E_UNSUPPORTED_OPERATION, + "[%s] The device does not support this property.", GetErrorMessage(E_UNSUPPORTED_OPERATION)); + + return __pFaceDetectorImpl->GetRange(configProperty, min, max, steppingDelta, defaultVal); +} + +long +FaceDetector::GetProperty(FaceDetectorConfigProperty configProperty) const +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + + SysTryCatch(NID_UIX, configProperty >= FACEDETECTOR_MAXNUMBER_VIDEO && configProperty <= FACEDETECTOR_SCALE_FACTOR, + r = E_UNSUPPORTED_OPERATION, E_UNSUPPORTED_OPERATION, + "[%s] The device does not support this property.", GetErrorMessage(E_UNSUPPORTED_OPERATION)); + + return __pFaceDetectorImpl->GetProperty(configProperty); + +CATCH: + SetLastResult(r); + return (long)-1; +} + +result +FaceDetector::SetProperty(FaceDetectorConfigProperty configProperty, long value) +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + SysTryReturn(NID_UIX, configProperty >= FACEDETECTOR_MAXNUMBER_VIDEO && configProperty <= FACEDETECTOR_SCALE_FACTOR, + E_UNSUPPORTED_OPERATION, E_UNSUPPORTED_OPERATION, + "[%s] The device does not support this property.", GetErrorMessage(E_UNSUPPORTED_OPERATION)); + + return __pFaceDetectorImpl->SetProperty(configProperty, value); +} + +Tizen::Base::Collection::IListT * +FaceDetector::GetSupportedFormatListN(void) const +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + return __pFaceDetectorImpl->GetSupportedFormatListN(); +} + +Tizen::Base::Collection::IList* +FaceDetector::DetectFacesFromVideoStreamN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::PixelFormat format) +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + + result r = E_SUCCESS; + float bytePerPixel = 0.0f; + + Tizen::Base::Collection::IListT * pList = null; + + SysTryCatch(NID_UIX, 0 < resolution.width, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width of the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryCatch(NID_UIX, 0 < resolution.height, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The height of the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + pList = GetSupportedFormatListN(); + + SysTryCatch(NID_UIX, pList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult())); + + if (pList->Contains(format) == false) + { + SysTryCatch(NID_UIX, false, r = E_INVALID_ARG, E_INVALID_ARG, "[%s] A specified format is invalid.", GetErrorMessage(E_INVALID_ARG)); + } + + pList->RemoveAll(); + delete pList; + pList = null; + + // Below check routine includes the Pixelformat. Therefore it is checked after verifying format is valid. + if (format == Tizen::Graphics::PIXEL_FORMAT_YCbCr420_PLANAR) + { + bytePerPixel = 1.5f; + } + else if (format == Tizen::Graphics::PIXEL_FORMAT_RGB565) + { + bytePerPixel = 2.0f; + } + + SysTryCatch(NID_UIX, + byteBuffer.GetLimit() == (int) (resolution.width * resolution.height * bytePerPixel), r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The specified @c byteBuffer does not have the size specified by the @c width, @c height, and @c format.", GetErrorMessage(E_INVALID_ARG)); + + return __pFaceDetectorImpl->DetectFacesFromBufferN(byteBuffer, resolution, format); + +CATCH: + if (pList != null) + { + pList->RemoveAll(); + delete pList; + pList = null; + } + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IList* +FaceDetector::DetectFacesFromStillImageN(const Tizen::Graphics::Bitmap& bitmap) +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + return __pFaceDetectorImpl->DetectFacesFromBitmapN(bitmap); +} + +Tizen::Base::Collection::IList* +FaceDetector::DetectFacesFromStillImageN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::BitmapPixelFormat format) +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + + SysTryCatch(NID_UIX, 0 < resolution.width, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryCatch(NID_UIX, 0 < resolution.height, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The height the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + SysTryCatch(NID_UIX, format > Tizen::Graphics::BITMAP_PIXEL_FORMAT_MIN && format < Tizen::Graphics::BITMAP_PIXEL_FORMAT_MAX, r = + E_INVALID_ARG, E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(E_INVALID_ARG)); + + return __pFaceDetectorImpl->DetectFacesFromBitmapN(byteBuffer, resolution, format); + +CATCH: + SetLastResult(r); + return null; +} + +/*** since 2.0 ***/ +FaceBuffer* +FaceDetector::PreprocessDataN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& dim, + Tizen::Graphics::PixelFormat format) +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + + float bytePerPixel = 0.0f; + std::unique_ptr pProcessedData; + + Tizen::Base::Collection::IListT * pFormatList = null; + Tizen::Base::ByteBuffer* pGrayBuf = null; + + SysTryCatch(NID_UIX, 0 < dim.width, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryCatch(NID_UIX, 0 < dim.height, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The height the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + pFormatList = GetSupportedFormatListN(); + SysTryCatch(NID_UIX, pFormatList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult())); + SysTryCatch(NID_UIX, pFormatList->Contains( + format) == true, r = E_INVALID_ARG, E_INVALID_ARG, "[%s] A specified format is invalid.", GetErrorMessage(E_INVALID_ARG)); + + pFormatList->RemoveAll(); + + delete pFormatList; + pFormatList = null; + + if (format == Tizen::Graphics::PIXEL_FORMAT_YCbCr420_PLANAR) + { + bytePerPixel = 1.5f; + } + else if (format == Tizen::Graphics::PIXEL_FORMAT_RGB565) + { + bytePerPixel = 2.0f; + } + + SysTryCatch(NID_UIX, + (int) (dim.width * dim.height * bytePerPixel) == byteBuffer.GetLimit(), r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The specified @c byteBuffer does not have the size specified by the @c width, @c height, and @c format.", GetErrorMessage(E_INVALID_ARG)); + + pGrayBuf = __pFaceDetectorImpl->ConvertToGrayN(byteBuffer, dim, format); + + pProcessedData = std::unique_ptr(new (std::nothrow) FaceBuffer(*pGrayBuf, dim)); + SysTryCatch(NID_UIX, pProcessedData != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + + delete pGrayBuf; + pGrayBuf = null; + + return pProcessedData.release(); + +CATCH: + delete pFormatList; + pFormatList = null; + + delete pGrayBuf; + pGrayBuf = null; + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IList* +FaceDetector::DetectFacesN(const FaceBuffer& preprocessedData, FaceDetectionOption mode) +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + + switch (mode) + { + case FACE_DETECTION_OPTION_FAST: + // fall through + case FACE_DETECTION_OPTION_ROBUST: + break; + + default: + SysTryCatch(NID_UIX, false, r = E_UNSUPPORTED_OPERATION, E_UNSUPPORTED_OPERATION, "[%s] The specified mode is not supported.", + GetErrorMessage(E_UNSUPPORTED_OPERATION)); + break; + } + + return __pFaceDetectorImpl->DetectFacesN(*(preprocessedData.GetBuffer()), preprocessedData.GetDimension(), mode); + +CATCH: + SetLastResult(r); + return null; +} + +FaceComponentsPosition* +FaceDetector::ExtractFaceComponentsN(const FaceBuffer& preprocessedFaceBuffer, const Tizen::Graphics::Rectangle& faceRect) +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + + Tizen::Graphics::Dimension resolution; + Tizen::Graphics::Point eyeRight; + Tizen::Graphics::Point eyeLeft; + Tizen::Graphics::Rectangle mouthRect; + + std::unique_ptr pGeoInfo(new (std::nothrow) FaceComponentsPosition()); + SysTryReturn(NID_UIX, pGeoInfo != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + resolution = preprocessedFaceBuffer.GetDimension(); + SysTryReturn(NID_UIX, + faceRect.x >= 0 && faceRect.y >= 0 && faceRect.width > 0 && faceRect.height > 0 && + faceRect.x + faceRect.width < resolution.width && faceRect.y + faceRect.height < resolution.height, + null, E_INVALID_ARG, + "[%s] The specified @c faceRect is not within the @c FaceComponentsPosition.", GetErrorMessage(E_INVALID_ARG)); + + r = pGeoInfo->SetFacePosition(faceRect); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + resolution = preprocessedFaceBuffer.GetDimension(); + + r = __pFaceDetectorImpl->ExtractFaceComponents(*(preprocessedFaceBuffer.GetBuffer()), resolution, faceRect, eyeRight, eyeLeft, mouthRect); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + r = pGeoInfo->SetEyePosition(eyeLeft, eyeRight); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + r = pGeoInfo->SetMouthPosition(mouthRect); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + return pGeoInfo.release(); +} + +result +FaceDetector::GetFaceMovement(const FaceBuffer& prevData, const FaceBuffer& curData, const Tizen::Graphics::Rectangle& prevFaceRect, + int& xDiff, + int& yDiff) +{ + SysAssertf(__pFaceDetectorImpl != null, "Not yet constructed. Construct() should be called before use."); + + result r = E_SUCCESS; + Tizen::Graphics::Dimension resolution; + Tizen::Graphics::Point posDiff(0, 0); + + resolution = prevData.GetDimension(); + SysTryReturn(NID_UIX, + resolution == curData.GetDimension(), E_INVALID_ARG, E_INVALID_ARG, + "[%s] The size of @c prevData and @c curData should be the same.", GetErrorMessage(E_INVALID_ARG)); + + SysTryReturn(NID_UIX, + prevFaceRect.x >= 0 && prevFaceRect.y >= 0 && prevFaceRect.width > 0 && prevFaceRect.height > 0 && + prevFaceRect.x + prevFaceRect.width < resolution.width && prevFaceRect.y + prevFaceRect.height < resolution.height, + E_INVALID_ARG, E_INVALID_ARG, + "[%s] The specified @c prevFaceRect is not within the @c preprocessedData.", GetErrorMessage(E_INVALID_ARG)); + + r = __pFaceDetectorImpl->GetPosDifference(*(prevData.GetBuffer()), *(curData.GetBuffer()), resolution, prevFaceRect, posDiff); + SysTryReturn(NID_UIX, r == E_SUCCESS, r, r, "[%s] Propagating.", GetErrorMessage(r)); + + xDiff = posDiff.x; + yDiff = posDiff.y; + return r; +} + +} } } //Tizen::Uix::Vision diff --git a/src/FUixVisionFaceRecognitionInfo.cpp b/src/FUixVisionFaceRecognitionInfo.cpp new file mode 100755 index 0000000..032bc0d --- /dev/null +++ b/src/FUixVisionFaceRecognitionInfo.cpp @@ -0,0 +1,91 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVisionFaceRecognitionInfo.cpp + * @brief This is the implementation file for the %FaceRecognitionInfo class. + * + * This files contains implementation of the %FaceRecognitionInfo class. + */ + +// Includes +#include +#include +#include +#include +#include +#include +#include + +namespace Tizen { namespace Uix { namespace Vision +{ + +FaceRecognitionInfo::FaceRecognitionInfo(void) + : __pfaceFeatures(null) +{ + +} + +result +FaceRecognitionInfo::Construct(const Tizen::Base::ByteBuffer& faceFeatures) +{ + SysAssertf(__pfaceFeatures == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class."); + + __pfaceFeatures = new (std::nothrow) Tizen::Base::ByteBuffer; + SysTryReturn(NID_UIX, __pfaceFeatures != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + result r = __pfaceFeatures->Construct(faceFeatures); + if (IsFailed(r)) + { + SysLogException(NID_UIX, E_INVALID_ARG, "[%s] The faceFeatures is not constructed.", GetErrorMessage(E_INVALID_ARG)); + delete __pfaceFeatures; + __pfaceFeatures = null; + } + + return r; +} + +FaceRecognitionInfo::~FaceRecognitionInfo(void) +{ + if (__pfaceFeatures != null) + { + delete __pfaceFeatures; + __pfaceFeatures = null; + } +} + +Tizen::Graphics::Rectangle +FaceRecognitionInfo::GetFacePosition(void) const +{ + return __faceRect; +} + +const Tizen::Base::ByteBuffer* +FaceRecognitionInfo::GetFaceFeatures(void) const +{ + SysAssertf(__pfaceFeatures != null, "Not yet constructed. Construct() should be called before use."); + + return __pfaceFeatures; +} + +void +FaceRecognitionInfo::SetFacePosition(int x, int y, int width, int height) +{ + __faceRect = Tizen::Graphics::Rectangle(x, y, width, height); +} + +} } } //Tizen::Uix::Vision diff --git a/src/FUixVisionFaceRecognizer.cpp b/src/FUixVisionFaceRecognizer.cpp new file mode 100755 index 0000000..ddb180d --- /dev/null +++ b/src/FUixVisionFaceRecognizer.cpp @@ -0,0 +1,621 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVisionFaceRecognizer.cpp + * @brief This file contains implementation of FaceRecognizer class. + * + * + * This file contains the implementation of FaceRecognizer class. + */ + +// includes +#include +#include +#include +#include +#include +#include "FUixVision_FaceRecognizerImpl.h" + +#define EYE_DISTANCE_SQUARE 11 * 11 + +// namespace +using namespace Tizen::Base; +//using namespace Tizen::Com; + +namespace Tizen { namespace Uix { namespace Vision +{ + +/////////////////////////////////////////////////////////////////// +// Life-time +FaceRecognizer::FaceRecognizer(void) + : __pFaceRecognizerImpl(null) +{ + +} + +FaceRecognizer::~FaceRecognizer(void) +{ + if (__pFaceRecognizerImpl != null) + { + delete __pFaceRecognizerImpl; + __pFaceRecognizerImpl = null; + } +} + +result +FaceRecognizer::Construct(void) +{ + SysAssertf(__pFaceRecognizerImpl == null, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class."); + + result r = E_SUCCESS; + + std::unique_ptr<_FaceRecognizerImpl> pFaceRecognizerImpl (new (std::nothrow) _FaceRecognizerImpl()); + SysTryReturn(NID_UIX, pFaceRecognizerImpl != null, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pFaceRecognizerImpl->Construct(); + SysTryReturn(NID_UIX, r == E_SUCCESS, r, r,"[%s] Construct failed",GetErrorMessage(r)); + + __pFaceRecognizerImpl = pFaceRecognizerImpl.release(); + + return r; +} + +result +FaceRecognizer::GetRange(FaceRecognizerConfigProperty configProperty, long& min, long& max, long& steppingDelta, + long& defaultVal) const +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + switch (configProperty) + { + case FACERECOGNIZER_MAXNUMBER_VIDEO: + // fall through + case FACERECOGNIZER_MAXNUMBER_IMAGE: + // fall through + case FACERECOGNIZER_SCALE_VIDEO: + // fall through + case FACERECOGNIZER_SCALE_IMAGE: + break; + + default: + SysLogException(NID_UIX, E_UNSUPPORTED_OPERATION, "[%s] The device does not support this property.", GetErrorMessage(E_UNSUPPORTED_OPERATION)); + return E_UNSUPPORTED_OPERATION; + } + + return __pFaceRecognizerImpl->GetRange(configProperty, min, max, steppingDelta, defaultVal); +} + +long +FaceRecognizer::GetProperty(FaceRecognizerConfigProperty configProperty) const +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + + SysTryCatch(NID_UIX, configProperty >= FACERECOGNIZER_MAXNUMBER_VIDEO && configProperty <= FACERECOGNIZER_SCALE_IMAGE, + r = E_UNSUPPORTED_OPERATION, E_UNSUPPORTED_OPERATION, + "[%s] The device does not support this property.", GetErrorMessage(E_UNSUPPORTED_OPERATION)); + + return __pFaceRecognizerImpl->GetProperty(configProperty); +CATCH: + SetLastResult(r); + return (long)-1; +} + +result +FaceRecognizer::SetProperty(FaceRecognizerConfigProperty configProperty, long value) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + switch (configProperty) + { + case FACERECOGNIZER_MAXNUMBER_VIDEO: + // fall through + case FACERECOGNIZER_MAXNUMBER_IMAGE: + // fall through + case FACERECOGNIZER_SCALE_VIDEO: + // fall through + case FACERECOGNIZER_SCALE_IMAGE: + break; + + default: + SysLogException(NID_UIX, E_UNSUPPORTED_OPERATION, "[%s] The device does not support this property.", GetErrorMessage(E_UNSUPPORTED_OPERATION)); + return E_UNSUPPORTED_OPERATION; + } + + return __pFaceRecognizerImpl->SetProperty(configProperty, value); +} + +Tizen::Base::Collection::IListT * +FaceRecognizer::GetSupportedFormatListN(void) const +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + return __pFaceRecognizerImpl->GetSupportedFormatListN(); +} + +Tizen::Base::Collection::IList* +FaceRecognizer::ExtractFaceInfoFromVideoStreamN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::PixelFormat format) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + float bytePerPixel = 0.0f; + + Tizen::Base::Collection::IListT * pList = null; + + pList = GetSupportedFormatListN(); + SysTryCatch(NID_UIX, pList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult())); + + SysTryCatch(NID_UIX, (pList->Contains(format) == true), r = E_INVALID_ARG, E_INVALID_ARG, "[%s] A specified format is invalid." + , GetErrorMessage(E_INVALID_ARG)); + + pList->RemoveAll(); + delete pList; + pList = null; + + SysTryCatch(NID_UIX, 0 < resolution.width, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width of the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryCatch(NID_UIX, 0 < resolution.height, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The height of the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + // Below check routine includes the Pixelformat. Therefore it is checked after verifying format is valid. + if (format == Tizen::Graphics::PIXEL_FORMAT_YCbCr420_PLANAR) + { + bytePerPixel = 1.5f; + } + else if (format == Tizen::Graphics::PIXEL_FORMAT_RGB565) + { + bytePerPixel = 2.0f; + } + SysTryCatch(NID_UIX, + !(Float::Compare((float)byteBuffer.GetLimit(), (float)(resolution.width * resolution.height * bytePerPixel))), r = E_INVALID_ARG, + E_INVALID_ARG, + "[%s] The specified @c byteBuffer does not have the size specified by the @c width, @c height, and @c format.", + GetErrorMessage(E_INVALID_ARG)); + + + return __pFaceRecognizerImpl->ExtractFaceFeaturesFromBufferN(byteBuffer, resolution, format); + +CATCH: + if (pList != null) + { + pList->RemoveAll(); + delete pList; + pList = null; + } + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IList* +FaceRecognizer::ExtractFaceInfoFromStillImageN(const Tizen::Graphics::Bitmap& bitmap) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + return __pFaceRecognizerImpl->ExtractFaceFeaturesFromBitmapN(bitmap); +} + +Tizen::Base::Collection::IList* +FaceRecognizer::ExtractFaceInfoFromStillImageN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::BitmapPixelFormat format) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + + SysTryCatch(NID_UIX, 0 < resolution.width, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryCatch(NID_UIX, 0 < resolution.height, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The height the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + SysTryCatch(NID_UIX, format > Tizen::Graphics::BITMAP_PIXEL_FORMAT_MIN && format < Tizen::Graphics::BITMAP_PIXEL_FORMAT_MAX, r = + E_INVALID_ARG, E_INVALID_ARG, "[%s] Propagating.", GetErrorMessage(E_INVALID_ARG)); + + return __pFaceRecognizerImpl->ExtractFaceFeaturesFromBitmapN(byteBuffer, resolution, format); +CATCH: + SetLastResult(r); + return null; +} + +bool +FaceRecognizer::IsMatching(const FaceRecognitionInfo& face1, const FaceRecognitionInfo& face2) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + const Tizen::Base::ByteBuffer* faceFeatures1 = null; + const Tizen::Base::ByteBuffer* faceFeatures2 = null; + + faceFeatures1 = face1.GetFaceFeatures(); + SysTryCatch(NID_UIX, faceFeatures1 != null, r = E_INVALID_ARG, E_INVALID_ARG, + ("[%s] A specified FaceRecognitionInfo is not constructed yet.", GetErrorMessage(E_INVALID_ARG))); + + faceFeatures2 = face2.GetFaceFeatures(); + SysTryCatch(NID_UIX, faceFeatures2 != null, r = E_INVALID_ARG, E_INVALID_ARG, + ("[%s] A specified FaceRecognitionInfo is not constructed yet.", GetErrorMessage(E_INVALID_ARG))); + + return __pFaceRecognizerImpl->IsMatching(*(faceFeatures1), *(faceFeatures2)); + +CATCH: + SetLastResult(r); + return false; +} + +int +FaceRecognizer::MeasureSimilarity(const FaceRecognitionInfo& face1, const FaceRecognitionInfo& face2) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + const Tizen::Base::ByteBuffer* faceFeatures1 = null; + const Tizen::Base::ByteBuffer* faceFeatures2 = null; + + faceFeatures1 = face1.GetFaceFeatures(); + SysTryCatch(NID_UIX, faceFeatures1 != null, r = E_INVALID_ARG, E_INVALID_ARG, + ("[%s] A specified FaceRecognitionInfo is not constructed yet.", GetErrorMessage(E_INVALID_ARG))); + + faceFeatures2 = face2.GetFaceFeatures(); + SysTryCatch(NID_UIX, faceFeatures2 != null, r = E_INVALID_ARG, E_INVALID_ARG, + ("[%s] A specified FaceRecognitionInfo is not constructed yet.", GetErrorMessage(E_INVALID_ARG))); + + return __pFaceRecognizerImpl->MeasureSimilarity(*(faceFeatures1), *(faceFeatures2)); + +CATCH: + SetLastResult(r); + return -1; +} + +/*** since 2.0 ***/ +Tizen::Base::ByteBuffer* +FaceRecognizer::ExtractFeatureN(const FaceBuffer& preprocessedFaceBuffer, const FaceComponentsPosition& faceComponentPos) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + Tizen::Graphics::Dimension resolution; + Tizen::Graphics::Point eyeRight; + Tizen::Graphics::Point eyeLeft; + Tizen::Graphics::Rectangle faceRect; + + resolution = preprocessedFaceBuffer.GetDimension(); + faceComponentPos.GetEyePosition(eyeLeft, eyeRight); + faceRect = faceComponentPos.GetFacePosition(); + SysTryCatch(NID_UIX, + eyeLeft.x >= 0 && eyeLeft.y >= 0 && eyeRight.x >= 0 && eyeRight.y >= 0 && + eyeRight.x <= resolution.width && eyeRight.y <= resolution.height && eyeLeft.y <= resolution.height, + r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The specified @c eyes's positions in the faceComponentPos should be withiin the @c preprocessedFaceBuffer.", + GetErrorMessage(E_INVALID_ARG)); + + SysTryCatch(NID_UIX, eyeLeft.x < eyeRight.x, + r = E_OPERATION_FAILED, E_OPERATION_FAILED, + "[%s] The value of the x position for the right eye should be greater than left one.", GetErrorMessage(E_OPERATION_FAILED)); + + if (eyeLeft.y != eyeRight.y) + { + SysTryCatch(NID_UIX, + ((eyeRight.x - eyeLeft.x) * (eyeRight.x - eyeLeft.x)) + ((eyeRight.y - eyeLeft.y) * (eyeRight.y - eyeLeft.y)) > + EYE_DISTANCE_SQUARE, + r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Fail to extract the facial information.", GetErrorMessage(E_OPERATION_FAILED)); + } + else + { + SysTryCatch(NID_UIX, (eyeRight.x - eyeLeft.x) * (eyeRight.x - eyeLeft.x) > EYE_DISTANCE_SQUARE, + r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Fail to extract the facial information.", GetErrorMessage(E_OPERATION_FAILED)); + } + + return __pFaceRecognizerImpl->ExtractFeatureN(*(preprocessedFaceBuffer.GetBuffer()), resolution, faceRect); + +CATCH: + SetLastResult(r); + return null; +} + +EyeState +FaceRecognizer::GetEyeState(const FaceBuffer& preprocessedFaceBuffer, const FaceComponentsPosition& faceComponentPos) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + Tizen::Graphics::Dimension resolution; + Tizen::Graphics::Rectangle faceRect; + Tizen::Graphics::Point eyeRight; + Tizen::Graphics::Point eyeLeft; + + resolution = preprocessedFaceBuffer.GetDimension(); + faceComponentPos.GetEyePosition(eyeLeft, eyeRight); + faceRect = faceComponentPos.GetFacePosition(); + SysTryCatch(NID_UIX, + eyeLeft.x >= 0 && eyeLeft.y >= 0 && eyeRight.x >= 0 && eyeRight.y >= 0 && + eyeRight.x <= resolution.width && eyeRight.y <= resolution.height && eyeLeft.y <= resolution.height, + r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The specified @c eyes's positions in the faceComponentPos should be withiin the @c preprocessedFaceBuffer.", GetErrorMessage(E_INVALID_ARG)); + + SysTryCatch(NID_UIX, eyeLeft.x < eyeRight.x, + r = E_OPERATION_FAILED, E_OPERATION_FAILED, + "[%s] The value of the x position for the right eye should be greater than left one.", GetErrorMessage(E_OPERATION_FAILED)); + + if (eyeLeft.y != eyeRight.y) + { + SysTryCatch(NID_UIX, + ((eyeRight.x - eyeLeft.x) * (eyeRight.x - eyeLeft.x)) + ((eyeRight.y - eyeLeft.y) * (eyeRight.y - eyeLeft.y)) > + EYE_DISTANCE_SQUARE, + r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Fail to detect the eye state.", GetErrorMessage(E_OPERATION_FAILED)); + } + else + { + SysTryCatch(NID_UIX, (eyeRight.x - eyeLeft.x) * (eyeRight.x - eyeLeft.x) > EYE_DISTANCE_SQUARE, + r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Fail to detect the eye state.", GetErrorMessage(E_OPERATION_FAILED)); + } + return __pFaceRecognizerImpl->DetectEyeState(*(preprocessedFaceBuffer.GetBuffer()), resolution, faceRect); + +CATCH: + SetLastResult(r); + return EYE_STATE_NONE; +} + +FacialExpression +FaceRecognizer::RecognizeExpression(const FaceBuffer& preprocessedFaceBuffer, const FaceComponentsPosition& faceComponentPos) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + Tizen::Graphics::Dimension resolution; + Tizen::Graphics::Rectangle faceRect; + Tizen::Graphics::Point eyeRight; + Tizen::Graphics::Point eyeLeft; + + resolution = preprocessedFaceBuffer.GetDimension(); + faceComponentPos.GetEyePosition(eyeLeft, eyeRight); + faceRect = faceComponentPos.GetFacePosition(); + SysTryCatch(NID_UIX, + eyeLeft.x >= 0 && eyeLeft.y >= 0 && eyeRight.x >= 0 && eyeRight.y >= 0 && + eyeRight.x <= resolution.width && eyeRight.y <= resolution.height && eyeLeft.y <= resolution.height, + r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The specified @c eyes's positions in the faceComponentPos should be withiin the @c preprocessedFaceBuffer.", GetErrorMessage(E_INVALID_ARG)); + + SysTryCatch(NID_UIX, eyeLeft.x < eyeRight.x, + r = E_OPERATION_FAILED, E_OPERATION_FAILED, + "[%s] The value of the x position for the right eye should be greater than left one.", GetErrorMessage(E_OPERATION_FAILED)); + + if (eyeLeft.y != eyeRight.y) + { + SysTryCatch(NID_UIX, + ((eyeRight.x - eyeLeft.x) * (eyeRight.x - eyeLeft.x)) + ((eyeRight.y - eyeLeft.y) * (eyeRight.y - eyeLeft.y)) > + EYE_DISTANCE_SQUARE, + r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Fail to recognize the facial expression.", GetErrorMessage(E_OPERATION_FAILED)); + } + else + { + SysTryCatch(NID_UIX, (eyeRight.x - eyeLeft.x) * (eyeRight.x - eyeLeft.x) > EYE_DISTANCE_SQUARE, + r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Fail to recognize the facial expression.", GetErrorMessage(E_OPERATION_FAILED)); + } + return __pFaceRecognizerImpl->RecognizeExpression(*(preprocessedFaceBuffer.GetBuffer()), resolution, faceRect); + +CATCH: + SetLastResult(r); + return FACIAL_EXPRESSION_NONE; +} + +Tizen::Base::Collection::IMapT * +FaceRecognizer::DetectBlinksFromStillImageN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::BitmapPixelFormat format) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + float bytePerPixel = 0.0f; + + SysTryCatch(NID_UIX, 0 < resolution.width, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryCatch(NID_UIX, 0 < resolution.height, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The height the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + SysTryCatch(NID_UIX, Tizen::Graphics::BITMAP_PIXEL_FORMAT_MIN < format && Tizen::Graphics::BITMAP_PIXEL_FORMAT_MAX > format, + r = E_INVALID_ARG, E_INVALID_ARG, "[%s] The specified @c format is not supported.", GetErrorMessage(E_INVALID_ARG)); + + SysTryCatch(NID_UIX, (format == Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888) || (format == Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565), + r = E_INVALID_ARG, E_INVALID_ARG, "[%s] A specified format(%d) is invalid.", GetErrorMessage(E_INVALID_ARG), format); + + if (format == Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888) + { + bytePerPixel = 4.0f; + } + else if (format == Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565) + { + bytePerPixel = 2.0f; + } + + SysTryCatch(NID_UIX, + !(Float::Compare((float)byteBuffer.GetLimit(), (float)(resolution.width * resolution.height * bytePerPixel))), + r = E_INVALID_ARG, E_INVALID_ARG, "[%s] The specified @c byteBuffer(%d) does not have the size specified by" + "the @c width(%d), @c height(%d), and @c format(%d).", + GetErrorMessage(E_INVALID_ARG), byteBuffer.GetLimit(), resolution.width, resolution.height, bytePerPixel); + + return __pFaceRecognizerImpl->DetectBlinksFromBitmapN(byteBuffer, resolution, format); + +CATCH: + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IMapT * +FaceRecognizer::DetectBlinksFromVideoStreamN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::PixelFormat format) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + float bytePerPixel = 0.0f; + Tizen::Base::Collection::IListT * pList = null; + + pList = GetSupportedFormatListN(); + SysTryCatch(NID_UIX, pList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult())); + + SysTryCatch(NID_UIX, (pList->Contains(format) == true), r = E_INVALID_ARG, E_INVALID_ARG, "[%s] A specified format is invalid." + , GetErrorMessage(E_INVALID_ARG)); + + pList->RemoveAll(); + delete pList; + pList = null; + + SysTryCatch(NID_UIX, 0 < resolution.width, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width of the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryCatch(NID_UIX, 0 < resolution.height, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The height of the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + // Below check routine includes the Pixelformat. Therefore it is checked after verifying format is valid. + if (format == Tizen::Graphics::PIXEL_FORMAT_YCbCr420_PLANAR) + { + bytePerPixel = 1.5f; + } + else if (format == Tizen::Graphics::PIXEL_FORMAT_RGB565) + { + bytePerPixel = 2.0f; + } + + SysTryCatch(NID_UIX, + !(Float::Compare((float)byteBuffer.GetLimit(), (float)(resolution.width * resolution.height * bytePerPixel))), r = E_INVALID_ARG, + E_INVALID_ARG, "[%s] The specified @c byteBuffer(%d) does not have the size specified by the @c width(%d), @c height(%d), and" + "@c format(%d).", GetErrorMessage(E_INVALID_ARG), byteBuffer.GetLimit(), resolution.width, resolution.height, bytePerPixel); + + return __pFaceRecognizerImpl->DetectBlinksFromBufferN(byteBuffer, resolution, format); +CATCH: + if (pList != null) + { + pList->RemoveAll(); + delete pList; + pList = null; + } + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IMapT * +FaceRecognizer::RecognizeExpressionsFromStillImageN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::BitmapPixelFormat format) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + float bytePerPixel = 0.0f; + + SysTryCatch(NID_UIX, 0 < resolution.width, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryCatch(NID_UIX, 0 < resolution.height, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The height the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + SysTryCatch(NID_UIX, Tizen::Graphics::BITMAP_PIXEL_FORMAT_MIN < format && Tizen::Graphics::BITMAP_PIXEL_FORMAT_MAX > format, r = + E_INVALID_ARG, E_INVALID_ARG, + "[%s] The specified @c format is not supported.", GetErrorMessage(E_INVALID_ARG)); + + SysTryCatch(NID_UIX, (format == Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888) || (format == Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565), + r = E_INVALID_ARG, E_INVALID_ARG, "[%s] A specified format(%d) is invalid.", GetErrorMessage(E_INVALID_ARG), format); + + if (format == Tizen::Graphics::BITMAP_PIXEL_FORMAT_ARGB8888) + { + bytePerPixel = 4.0f; + } + else if (format == Tizen::Graphics::BITMAP_PIXEL_FORMAT_RGB565) + { + bytePerPixel = 2.0f; + } + + SysTryCatch(NID_UIX, + !(Float::Compare((float)byteBuffer.GetLimit(), (float)(resolution.width * resolution.height * bytePerPixel))), r = E_INVALID_ARG, + E_INVALID_ARG, "[%s] The specified @c byteBuffer(%d) does not have the size specified by the @c width(%d), @c height(%d), and" + "@c format(%d).", GetErrorMessage(E_INVALID_ARG), byteBuffer.GetLimit(), resolution.width, resolution.height, bytePerPixel); + + return __pFaceRecognizerImpl->RecognizeExpressionsFromBitmapN(byteBuffer, resolution, format); +CATCH: + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IMapT * +FaceRecognizer::RecognizeExpressionsFromVideoStreamN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::PixelFormat format) +{ + SysAssertf(__pFaceRecognizerImpl != null, "Not yet constructed. Construct() should be called before use."); + + ClearLastResult(); + result r = E_SUCCESS; + float bytePerPixel = 0.0f; + Tizen::Base::Collection::IListT * pList = null; + + pList = GetSupportedFormatListN(); + SysTryCatch(NID_UIX, pList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Propagating.", GetErrorMessage(GetLastResult())); + + SysTryCatch(NID_UIX, (pList->Contains(format) == true), r = E_INVALID_ARG, E_INVALID_ARG, "[%s] A specified format is invalid.", + GetErrorMessage(E_INVALID_ARG)); + + pList->RemoveAll(); + delete pList; + pList = null; + + SysTryCatch(NID_UIX, 0 < resolution.width, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The width of the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + SysTryCatch(NID_UIX, 0 < resolution.height, r = E_INVALID_ARG, E_INVALID_ARG, + "[%s] The height of the resolution should be greater than 0.", GetErrorMessage(E_INVALID_ARG)); + + // Below check routine includes the Pixelformat. Therefore it is checked after verifying format is valid. + if (format == Tizen::Graphics::PIXEL_FORMAT_YCbCr420_PLANAR) + { + bytePerPixel = 1.5f; + } + else if (format == Tizen::Graphics::PIXEL_FORMAT_RGB565) + { + bytePerPixel = 2.0f; + } + + SysTryCatch(NID_UIX, + !(Float::Compare((float)byteBuffer.GetLimit(), (float)(resolution.width * resolution.height * bytePerPixel))), r = E_INVALID_ARG, + E_INVALID_ARG, "[%s] The specified @c byteBuffer(%d) does not have the size specified by the @c width(%d), @c height(%d), and" + " @c format(%d).", GetErrorMessage(E_INVALID_ARG), byteBuffer.GetLimit(), resolution.width, resolution.height, bytePerPixel); + + return __pFaceRecognizerImpl->RecognizeExpressionsFromBufferN(byteBuffer, resolution, format); +CATCH: + if (pList != null) + { + pList->RemoveAll(); + delete pList; + pList = null; + } + SetLastResult(r); + return null; +} + +} } } //Tizen::Uix::Vision diff --git a/src/FUixVision_FaceDetectorImpl.cpp b/src/FUixVision_FaceDetectorImpl.cpp new file mode 100755 index 0000000..1d6cee2 --- /dev/null +++ b/src/FUixVision_FaceDetectorImpl.cpp @@ -0,0 +1,1029 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVision_FaceDetectorImpl.cpp + * @brief This file contains internal implementation of FaceDetector class. + * + * + * This file contains the internal implementation of FaceDetector class. + */ + +#include +#include "FUixVision_FaceDetectorImpl.h" + +using namespace Tizen::Base; +using namespace Tizen::Graphics; +using namespace Tizen::Base::Collection; + +namespace Tizen { namespace Uix { namespace Vision +{ +long _FaceDetectorImpl::__maxFacesAtomic = 5; +long _FaceDetectorImpl::__scaleAtomic = 1; + +static const int _MAX_FD_VIDEO_DEFAULT = 1; +static const int _MAX_FD_IMAGE_DEFAULT = 5; +static const int _MAX_FD_VIDEO_MAXNUM = 5; +static const int _MAX_FD_IMAGE_MAXNUM = 10; +static const int _MIN_FD_VIDEO_MAXNUM = 1; +static const int _MIN_FD_IMAGE_MAXNUM = 1; +static const int _FD_SCALE_VIDEO_DEFAULT = 1; +static const int _FD_SCALE_IMAGE_DEFAULT = 1; +static const int _MAX_FD_SCALE_VIDEO = 3; +static const int _MAX_FD_SCALE_IMAGE = 3; +static const int _MIN_FD_SCALE_VIDEO = 1; +static const int _MIN_FD_SCALE_IMAGE = 1; +static const int _FT_INTERVAL_DEFAULT = 100; + +_FaceDetectorImpl::_FaceDetectorImpl(void) + : __maxFacesVideo(0) + , __scaleVideo(0) + , __maxFacesImage(0) + , __scaleImage(0) + , __faceHandleVideoMode(null) + , __isTrackingMode(false) +{ +} + +_FaceDetectorImpl::~_FaceDetectorImpl(void) +{ + face_destroy(__faceHandleVideoMode); +} + +result +_FaceDetectorImpl::Construct(void) +{ + result r = E_SUCCESS; + long min = 0; + long max = 0; + long steppingDelta = 0; + int engineError = 0; + + engineError = face_create(&__faceHandleVideoMode); + SysTryReturn(NID_UIX, engineError == FACE_ERROR_NONE, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + + GetRange(FACEDETECTOR_MAXNUMBER_VIDEO, min, max, steppingDelta, __maxFacesVideo); + GetRange(FACEDETECTOR_MAXNUMBER_IMAGE, min, max, steppingDelta, __maxFacesImage); + GetRange(FACEDETECTOR_SCALE_VIDEO, min, max, steppingDelta, __scaleVideo); + GetRange(FACEDETECTOR_SCALE_IMAGE, min, max, steppingDelta, __scaleImage); + GetRange(FACEDETECTOR_MAXNUMBER_FACES, min, max, steppingDelta, __maxFacesAtomic); + GetRange(FACEDETECTOR_SCALE_FACTOR, min, max, steppingDelta, __scaleAtomic); + return r; +} + +result +_FaceDetectorImpl::GetRange(FaceDetectorConfigProperty configProperty, long& min, long& max, long& steppingDelta, + long& defaultVal) const +{ + result res = E_SUCCESS; + + switch (configProperty) + { + case FACEDETECTOR_MAXNUMBER_VIDEO: + { + min = _MIN_FD_VIDEO_MAXNUM; + max = _MAX_FD_VIDEO_MAXNUM; + steppingDelta = 1; + defaultVal = _MAX_FD_VIDEO_DEFAULT; + } + break; + + case FACEDETECTOR_MAXNUMBER_IMAGE: + { + min = _MIN_FD_IMAGE_MAXNUM; + max = _MAX_FD_IMAGE_MAXNUM; + steppingDelta = 1; + defaultVal = _MAX_FD_IMAGE_DEFAULT; + } + break; + + case FACEDETECTOR_SCALE_VIDEO: + { + min = _MIN_FD_SCALE_VIDEO; + max = _MAX_FD_SCALE_VIDEO; + defaultVal = _FD_SCALE_VIDEO_DEFAULT; + steppingDelta = 1; + } + break; + + case FACEDETECTOR_SCALE_IMAGE: + { + min = _MIN_FD_SCALE_IMAGE; + max = _MAX_FD_SCALE_IMAGE; + defaultVal = _FD_SCALE_IMAGE_DEFAULT; + steppingDelta = 1; + } + break; + + case FACEDETECTOR_MAXNUMBER_FACES: + { + min = _MIN_FD_IMAGE_MAXNUM; + max = _MAX_FD_IMAGE_MAXNUM; + steppingDelta = 1; + defaultVal = _MAX_FD_IMAGE_DEFAULT; + } + break; + + case FACEDETECTOR_SCALE_FACTOR: + { + min = _MIN_FD_SCALE_IMAGE; + max = _MAX_FD_SCALE_IMAGE; + steppingDelta = 1; + defaultVal = _FD_SCALE_IMAGE_DEFAULT; + } + break; + + default: + { + min = 0; + max = 0; + steppingDelta = 1; + defaultVal = 0; + SysTryReturn(NID_UIX, false, E_UNSUPPORTED_OPERATION, E_UNSUPPORTED_OPERATION, "[%s] The device does not support this property.", + GetErrorMessage(E_UNSUPPORTED_OPERATION)); + break; + } + } + + return res; +} + +long +_FaceDetectorImpl::GetProperty(FaceDetectorConfigProperty configProperty) const +{ + ClearLastResult(); + switch (configProperty) + { + case FACEDETECTOR_MAXNUMBER_VIDEO: + return __maxFacesVideo; + + case FACEDETECTOR_MAXNUMBER_IMAGE: + return __maxFacesImage; + + case FACEDETECTOR_SCALE_VIDEO: + return __scaleVideo; + + case FACEDETECTOR_SCALE_IMAGE: + return __scaleImage; + + case FACEDETECTOR_MAXNUMBER_FACES: + return __maxFacesAtomic; + + case FACEDETECTOR_SCALE_FACTOR: + return __scaleAtomic; + + default: + SetLastResult(E_UNSUPPORTED_OPERATION); + SysTryReturn(NID_UIX, false, -1, -1, "[%s] The device does not support this property.", GetErrorMessage(E_UNSUPPORTED_OPERATION)); + break; + } + return (long)-1; +} + +result +_FaceDetectorImpl::SetProperty(FaceDetectorConfigProperty configProperty, long value) +{ + long min = 0; + long max = 0; + long steppingDelta = 0; + long defaultVal = 0; + + GetRange(configProperty, min, max, steppingDelta, defaultVal); + SysTryReturn(NID_UIX, value >= min && value <= max && value % steppingDelta == 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE, + "[%s] The specified value (%d) is out of range.", GetErrorMessage(E_OUT_OF_RANGE), value); + + switch (configProperty) + { + case FACEDETECTOR_MAXNUMBER_VIDEO: + __maxFacesVideo = value; + break; + + case FACEDETECTOR_MAXNUMBER_IMAGE: + __maxFacesImage = value; + break; + + case FACEDETECTOR_SCALE_VIDEO: + __scaleVideo = value; + break; + + case FACEDETECTOR_SCALE_IMAGE: + __scaleImage = value; + break; + + case FACEDETECTOR_MAXNUMBER_FACES: + __maxFacesAtomic = value; + break; + + case FACEDETECTOR_SCALE_FACTOR: + __scaleAtomic = value; + break; + + default: + SysTryReturn(NID_UIX, false, E_UNSUPPORTED_OPERATION, E_UNSUPPORTED_OPERATION, "[%s] The device does not support this property.", + GetErrorMessage(E_UNSUPPORTED_OPERATION)); + break; + } + + return E_SUCCESS; +} + +Tizen::Base::Collection::IListT * +_FaceDetectorImpl::GetSupportedFormatListN(void) const +{ + std::unique_ptr, CollectionAllElementDelete> + pFormatList (new (std::nothrow) Tizen::Base::Collection::LinkedListT ); + SysTryReturn(NID_UIX, pFormatList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + pFormatList->InsertAt(Tizen::Graphics::PIXEL_FORMAT_RGB565, 0); + pFormatList->InsertAt(Tizen::Graphics::PIXEL_FORMAT_YCbCr420_PLANAR, 0); + + return pFormatList.release(); +} + +Tizen::Base::Collection::IList* +_FaceDetectorImpl::DetectFacesFromBufferN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::PixelFormat format) +{ + result r = E_SUCCESS; + + int engineErr = 0; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + unsigned char* pImageBuffer = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + + ClearLastResult(); + std::unique_ptr pDetectList(new (std::nothrow) Tizen::Base::Collection::ArrayList()); + SysTryReturn(NID_UIX, pDetectList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + r = pDetectList->Construct(); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + if (format == PIXEL_FORMAT_YCbCr420_PLANAR) + { + imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + } + else if (format == PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + } + pImageBuffer = (unsigned char*)byteBuffer.GetPointer(); + + if (__isTrackingMode == true) + { + engineErr = face_destroy(__faceHandleVideoMode); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to destroy the handle.", + GetErrorMessage(E_OPERATION_FAILED)); + engineErr = face_create(&__faceHandleVideoMode); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to create the handle.", + GetErrorMessage(E_OPERATION_FAILED)); + } + + engineErr = face_attr_set_max_number_faces(__faceHandleVideoMode, __maxFacesVideo); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(__faceHandleVideoMode, __scaleVideo); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + faceCount = GetFaceRectsN(__faceHandleVideoMode, pImageBuffer, resolution.width, resolution.height, FACE_IMAGE_TYPE_CONTINUOUS, + imageColorspace, &pFaceRects); + SysTryCatch(NID_UIX, faceCount >= 0, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult())); + + __isTrackingMode = false; + + if (faceCount > 0) + { + for (int i = 0; i < faceCount; i++) + { + Tizen::Graphics::Rectangle* pRect = + new (std::nothrow) Tizen::Graphics::Rectangle(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + SysTryCatch(NID_UIX, pRect != null, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult())); + r = pDetectList->Add(*pRect); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + } + } + + free(pFaceRects); + + return pDetectList.release(); + +CATCH: + free(pFaceRects); + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IList* +_FaceDetectorImpl::DetectFacesFromBitmapN(const Tizen::Graphics::Bitmap& bitmap) +{ + result r = E_SUCCESS; + BufferInfo bitmapInfo; + + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + unsigned char* pImageBuffer = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + + ClearLastResult(); + + r = const_cast (&bitmap)->Lock(bitmapInfo); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + std::unique_ptr pBuffer(new (std::nothrow) unsigned char[bitmapInfo.width * bitmapInfo.height]); + SysTryReturn(NID_UIX, pBuffer != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + + std::unique_ptr pDetectList(new (std::nothrow) Tizen::Base::Collection::ArrayList()); + SysTryCatch(NID_UIX, pDetectList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pDetectList->Construct(); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + if (bitmapInfo.pixelFormat == PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + pImageBuffer = (unsigned char*)bitmapInfo.pPixels; + } + else if (bitmapInfo.pixelFormat == PIXEL_FORMAT_ARGB8888) + { + imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + pImageBuffer = pBuffer.get(); + SysTryCatch(NID_UIX, pImageBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Failed to create the Buffer." + , GetErrorMessage(E_OUT_OF_MEMORY)); + ConvertArgb8888ToGray(*((unsigned char*)bitmapInfo.pPixels), pImageBuffer, bitmapInfo.width, bitmapInfo.height); + } + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, __maxFacesImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, __scaleImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + faceCount = GetFaceRectsN(faceHandle, pImageBuffer, bitmapInfo.width, bitmapInfo.height, FACE_IMAGE_TYPE_SINGLE, + imageColorspace, &pFaceRects); + SysTryCatch(NID_UIX, faceCount >= 0, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult())); + + __isTrackingMode = false; + + if (faceCount > 0) + { + for (int i = 0; i < faceCount; i++) + { + ConvertVirtualToPhysicalCoordinates(bitmap.GetWidth(), bitmap.GetHeight(), bitmapInfo.width, bitmapInfo.height, &pFaceRects[i]); + Tizen::Graphics::Rectangle* pRect = + new (std::nothrow) Tizen::Graphics::Rectangle(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + SysTryCatch(NID_UIX, pRect != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + r = pDetectList->Add(*pRect); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + } + } + r = const_cast (&bitmap)->Unlock(); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + free(pFaceRects); + face_destroy(faceHandle); + + return pDetectList.release(); + +CATCH: + free(pFaceRects); + face_destroy(faceHandle); + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IList* +_FaceDetectorImpl::DetectFacesFromBitmapN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::BitmapPixelFormat format) +{ + result r = E_SUCCESS; + + ClearLastResult(); + + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + unsigned char* pImageBuffer = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + + std::unique_ptr pBuffer(new (std::nothrow) unsigned char[resolution.width * resolution.height]); + SysTryReturn(NID_UIX, pBuffer != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + + std::unique_ptr pDetectList(new (std::nothrow) Tizen::Base::Collection::ArrayList()); + SysTryCatch(NID_UIX, pDetectList != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pDetectList->Construct(); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + if (format == BITMAP_PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + pImageBuffer = (unsigned char*)byteBuffer.GetPointer(); + } + else if (format == BITMAP_PIXEL_FORMAT_ARGB8888) + { + imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + pImageBuffer = pBuffer.get(); + SysTryCatch(NID_UIX, pImageBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Failed to create the Buffer." + , GetErrorMessage(E_OUT_OF_MEMORY)); + ConvertArgb8888ToGray(*((unsigned char*)byteBuffer.GetPointer()), pImageBuffer, resolution.width, resolution.height); + } + + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, __maxFacesImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, __scaleImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + faceCount = GetFaceRectsN(faceHandle, pImageBuffer, resolution.width, resolution.height, FACE_IMAGE_TYPE_SINGLE, + imageColorspace, &pFaceRects); + SysTryCatch(NID_UIX, faceCount >= 0, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult())); + + __isTrackingMode = false; + + if (faceCount > 0) + { + for (int i = 0; i < faceCount; i++) + { + Tizen::Graphics::Rectangle* pRect = + new (std::nothrow) Tizen::Graphics::Rectangle(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + SysTryCatch(NID_UIX, pRect != null, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult())); + r = pDetectList->Add(*pRect); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + } + } + + free(pFaceRects); + face_destroy(faceHandle); + + return pDetectList.release(); + +CATCH: + free(pFaceRects); + face_destroy(faceHandle); + + SetLastResult(r); + return null; +} + +Tizen::Base::ByteBuffer* +_FaceDetectorImpl::ConvertToGrayN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::PixelFormat format) +{ + result r = E_SUCCESS; + + ClearLastResult(); + + std::unique_ptr pGrayBuf( new (std::nothrow) Tizen::Base::ByteBuffer()); + SysTryReturn(NID_UIX, pGrayBuf != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pGrayBuf->Construct(resolution.width * resolution.height); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + switch (format) + { + case PIXEL_FORMAT_RGB565: + ConvertRgb565ToGray(*((unsigned char*)byteBuffer.GetPointer()), (unsigned char*)pGrayBuf->GetPointer(), + resolution.width, resolution.height); + break; + + case PIXEL_FORMAT_ARGB8888: + ConvertArgb8888ToGray(*((unsigned char*)byteBuffer.GetPointer()), (unsigned char*)pGrayBuf->GetPointer(), + resolution.width, resolution.height); + break; + + case PIXEL_FORMAT_YCbCr420_PLANAR: + memcpy((unsigned char*) (pGrayBuf->GetPointer()), + (unsigned char*) byteBuffer.GetPointer(), sizeof(unsigned char) * resolution.width * resolution.height); + break; + default : + break; + } + + return pGrayBuf.release(); +} + + +Tizen::Base::Collection::IList* +_FaceDetectorImpl::DetectFacesN(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, + FaceDetectionOption mode) +{ + result r = E_SUCCESS; + ClearLastResult(); + + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + unsigned char* pImageBuffer = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + + std::unique_ptr pDetectList(new (std::nothrow) Tizen::Base::Collection::ArrayList()); + SysTryReturn(NID_UIX, pDetectList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pDetectList->Construct(); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + pImageBuffer = (unsigned char*)grayBuffer.GetPointer(); + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, __maxFacesAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, __scaleAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + if (mode == FACE_DETECTION_OPTION_FAST) + { + engineErr = face_attr_set_detect_mode(faceHandle, FACE_DETECT_MODE_FAST); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set detect mode to FAST", + GetErrorMessage(E_FAILURE)); + } + else + { + engineErr = face_attr_set_detect_mode(faceHandle, FACE_DETECT_MODE_ROBUST); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set detect mode to ROBUST", + GetErrorMessage(E_FAILURE)); + } + + faceCount = GetFaceRectsN(faceHandle, pImageBuffer, resolution.width, resolution.height, FACE_IMAGE_TYPE_SINGLE, + imageColorspace, &pFaceRects); + SysTryCatch(NID_UIX, faceCount >= 0, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult())); + + __isTrackingMode = false; + + if (faceCount > 0) + { + for (int i = 0; i < faceCount; i++) + { + Tizen::Graphics::Rectangle* pRect = + new (std::nothrow) Tizen::Graphics::Rectangle(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + SysTryCatch(NID_UIX, pRect != null, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(GetLastResult())); + r = pDetectList->Add(*pRect); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + } + } + + free(pFaceRects); + face_destroy(faceHandle); + + return pDetectList.release(); + +CATCH: + free(pFaceRects); + face_destroy(faceHandle); + + SetLastResult(r); + return null; +} + +result +_FaceDetectorImpl::ExtractFaceComponents(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::Rectangle& faceRect, Tizen::Graphics::Point& eyeRight, + Tizen::Graphics::Point& eyeLeft, Tizen::Graphics::Rectangle& mouthRect) +{ + result r = E_SUCCESS; + int engineErr = 0; + face_h faceHandle = null; + face_image_h faceImage = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + face_rect_s* pFaceRects = null; + face_rect_s tempFaceRect; + int faceCount = 0; + face_component_h faceComponent = null; + face_point_s eyeL; + face_point_s eyeR; + face_rect_s mouthR; + unsigned char* pImageBuffer = (unsigned char*)grayBuffer.GetPointer(); + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, __maxFacesAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, __scaleAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_image_create(imageColorspace, pImageBuffer, resolution.width, resolution.height, + (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + tempFaceRect.x = faceRect.x; + tempFaceRect.y = faceRect.y; + tempFaceRect.w = faceRect.width; + tempFaceRect.h = faceRect.height; + + engineErr = face_extract_component(faceHandle, faceImage, &tempFaceRect, &faceComponent); + + if(engineErr != FACE_ERROR_NONE) + { + engineErr = face_attr_set_detect_mode(faceHandle, FACE_DETECT_MODE_ROBUST); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set detect mode to ROBUST", + GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face at ROBUST mode", + GetErrorMessage(E_FAILURE)); + + tempFaceRect.x = faceRect.x; + tempFaceRect.y = faceRect.y; + tempFaceRect.w = faceRect.width; + tempFaceRect.h = faceRect.height; + + engineErr = face_extract_component(faceHandle, faceImage, &tempFaceRect, &faceComponent); + } + + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to extract the faceComponent.", + GetErrorMessage(E_OPERATION_FAILED)); + + engineErr = face_component_get_right_eye_point(faceComponent, &eyeR); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to extract the faceComponent.", + GetErrorMessage(E_OPERATION_FAILED)); + + engineErr = face_component_get_left_eye_point(faceComponent, &eyeL); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to extract the faceComponent.", + GetErrorMessage(E_OPERATION_FAILED)); + + engineErr = face_component_get_mouth_rect(faceComponent, &mouthR); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to extract the faceComponent.", + GetErrorMessage(E_OPERATION_FAILED)); + + eyeRight.x = eyeR.x; + eyeRight.y = eyeR.y; + eyeLeft.x = eyeL.x; + eyeLeft.y = eyeL.y; + mouthRect.x = mouthR.x; + mouthRect.y = mouthR.y; + mouthRect.width = mouthR.w; + mouthRect.height = mouthR.h; + + face_image_destroy(faceImage); + free(pFaceRects); + face_component_destroy(faceComponent); + face_destroy(faceHandle); + + return r; + +CATCH: + face_image_destroy(faceImage); + free(pFaceRects); + face_component_destroy(faceComponent); + face_destroy(faceHandle); + + SetLastResult(r); + return r; +} + + +result +_FaceDetectorImpl::GetPosDifference(const Tizen::Base::ByteBuffer& prevGrayBuffer, const Tizen::Base::ByteBuffer& curGrayBuffer, + const Tizen::Graphics::Dimension& resolution, const Tizen::Graphics::Rectangle& faceRect, + Tizen::Graphics::Point& posDiff) +{ + result r = E_SUCCESS; + + int engineErr = 0; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + face_image_h prevFaceImage = null; + face_image_h curFaceImage = null; + face_rect_s prevFaceRect; + face_rect_s curFaceRect; + face_rect_s* pFaceRects = null; + int faceCount = 0; + + if (__isTrackingMode == false) + { + engineErr = face_destroy(__faceHandleVideoMode); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to destroy the handle.", + GetErrorMessage(E_OPERATION_FAILED)); + engineErr = face_create(&__faceHandleVideoMode); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to create the handle.", + GetErrorMessage(E_OPERATION_FAILED)); + + engineErr = face_attr_set_max_number_faces(__faceHandleVideoMode, __maxFacesAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to set the property.", + GetErrorMessage(E_OPERATION_FAILED)); + engineErr = face_attr_set_scale_factor(__faceHandleVideoMode, __scaleAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to set the property.", + GetErrorMessage(E_OPERATION_FAILED)); + + engineErr = face_attr_set_detect_inteval(__faceHandleVideoMode, _FT_INTERVAL_DEFAULT); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to set the property.", + GetErrorMessage(E_OPERATION_FAILED)); + + face_rect_s* pFaceRectsTemp = null; + faceCount = GetFaceRectsN(__faceHandleVideoMode, (unsigned char*)prevGrayBuffer.GetPointer(), resolution.width, resolution.height, FACE_IMAGE_TYPE_CONTINUOUS, + imageColorspace, &pFaceRectsTemp); + SysTryCatch(NID_UIX, faceCount >= 0, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to get the FaceRects.", + GetErrorMessage(E_OPERATION_FAILED)); + free(pFaceRectsTemp); + + faceCount = GetFaceRectsN(__faceHandleVideoMode, (unsigned char*)curGrayBuffer.GetPointer(), resolution.width, resolution.height, FACE_IMAGE_TYPE_CONTINUOUS, + imageColorspace, &pFaceRects); + SysTryCatch(NID_UIX, faceCount >= 0, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to get the FaceRects.", + GetErrorMessage(E_OPERATION_FAILED)); + } + else + { + faceCount = GetFaceRectsN(__faceHandleVideoMode, (unsigned char*)curGrayBuffer.GetPointer(), resolution.width, resolution.height, FACE_IMAGE_TYPE_CONTINUOUS, + imageColorspace, &pFaceRects); + SysTryCatch(NID_UIX, faceCount >= 0, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to get the FaceRects.", + GetErrorMessage(E_OPERATION_FAILED)); + } + + __isTrackingMode = true; + + engineErr = face_image_create(imageColorspace, (unsigned char*)prevGrayBuffer.GetPointer(), resolution.width, resolution.height, + (resolution.width * resolution.height), &prevFaceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to create the faceImage.", + GetErrorMessage(E_OPERATION_FAILED)); + engineErr = face_image_create(imageColorspace, (unsigned char*)curGrayBuffer.GetPointer(), resolution.width, resolution.height, + (resolution.width * resolution.height), &curFaceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to create the faceImage.", + GetErrorMessage(E_OPERATION_FAILED)); + + prevFaceRect.x = faceRect.x; + prevFaceRect.y = faceRect.y; + prevFaceRect.w = faceRect.width; + prevFaceRect.h = faceRect.height; + + engineErr = face_get_movement(__faceHandleVideoMode, prevFaceImage, curFaceImage, &prevFaceRect, &curFaceRect); + + if(engineErr == FACE_ERROR_INVALID_PARAMTER) + { + __isTrackingMode = false; + + face_rect_s* pFaceRectsTemp = null; + + engineErr = face_destroy(__faceHandleVideoMode); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to destroy the handle.", + GetErrorMessage(E_OPERATION_FAILED)); + engineErr = face_create(&__faceHandleVideoMode); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to create the handle.", + GetErrorMessage(E_OPERATION_FAILED)); + + engineErr = face_attr_set_max_number_faces(__faceHandleVideoMode, __maxFacesAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to set the property.", + GetErrorMessage(E_OPERATION_FAILED)); + engineErr = face_attr_set_scale_factor(__faceHandleVideoMode, __scaleAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to set the property.", + GetErrorMessage(E_OPERATION_FAILED)); + + engineErr = face_attr_set_detect_inteval(__faceHandleVideoMode, _FT_INTERVAL_DEFAULT); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to set the property.", + GetErrorMessage(E_OPERATION_FAILED)); + + engineErr = face_attr_set_detect_mode(__faceHandleVideoMode, FACE_DETECT_MODE_ROBUST); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set detect mode to ROBUST", + GetErrorMessage(E_FAILURE)); + + faceCount = GetFaceRectsN(__faceHandleVideoMode, (unsigned char*)prevGrayBuffer.GetPointer(), resolution.width, resolution.height, FACE_IMAGE_TYPE_SINGLE, + imageColorspace, &pFaceRectsTemp); + + for(int i=0;i= 0, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to get the FaceRects.", + GetErrorMessage(E_OPERATION_FAILED)); + + faceCount = GetFaceRectsN(__faceHandleVideoMode, (unsigned char*)curGrayBuffer.GetPointer(), resolution.width, resolution.height, FACE_IMAGE_TYPE_CONTINUOUS, + imageColorspace, &pFaceRects); + SysTryCatch(NID_UIX, faceCount >= 0, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to get the FaceRects.", + GetErrorMessage(E_OPERATION_FAILED)); + + for(int i = 0;i< faceCount; i++) + { + nearDistance = sqrt((pFaceRectsTemp[i].x - faceRect.x)^2 + (pFaceRectsTemp[i].y - faceRect.y)^2) + + sqrt((pFaceRectsTemp[i].x + pFaceRectsTemp[i].w - faceRect.x - faceRect.width)^2 + (pFaceRectsTemp[i].y + pFaceRectsTemp[i].h - faceRect.y - faceRect.height)^2); + if(oldDistance > nearDistance) + { + oldDistance = nearDistance; + oldID = i; + } + } + + engineErr = face_get_movement(__faceHandleVideoMode, prevFaceImage, curFaceImage, &pFaceRectsTemp[oldID], &curFaceRect); + + if (curFaceRect.x == 0 && curFaceRect.y == 0 && curFaceRect.w == 0 && curFaceRect.h == 0) + { + engineErr = FACE_ERROR_OPERATION_FAILED; + } + + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to get the face movement.", + GetErrorMessage(E_OPERATION_FAILED)); + + posDiff.x = curFaceRect.x - prevFaceRect.x; + posDiff.y = curFaceRect.y - prevFaceRect.y; + + break; + } + } + } + else + { + if (curFaceRect.x == 0 && curFaceRect.y == 0 && curFaceRect.w == 0 && curFaceRect.h == 0) + { + engineErr = FACE_ERROR_OPERATION_FAILED; + } + + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_OPERATION_FAILED, E_OPERATION_FAILED, "[%s] Failed to get the face movement.", + GetErrorMessage(E_OPERATION_FAILED)); + + posDiff.x = curFaceRect.x - prevFaceRect.x; + posDiff.y = curFaceRect.y - prevFaceRect.y; + } + + face_image_destroy(prevFaceImage); + face_image_destroy(curFaceImage); + free(pFaceRects); + + return r; + +CATCH: + face_image_destroy(prevFaceImage); + face_image_destroy(curFaceImage); + free(pFaceRects); + + return r; +} + +void +_FaceDetectorImpl::ConvertArgb8888ToGray(const unsigned char& buf, unsigned char* pGrayBuf, int width, int height) +{ + SysAssert(pGrayBuf != null); + if (pGrayBuf == null) + { + return; + } + + unsigned long* pSrc = (unsigned long*) &buf; + unsigned char* pDSt = (unsigned char*) pGrayBuf; + unsigned char* pEnd = pDSt + height * width; + + while (pDSt < pEnd) + { + unsigned long r = (*pSrc >> 16) & 0xFF; + unsigned long g = (*pSrc >> 8) & 0xFF; + unsigned long b = (*pSrc++) & 0xFF; + + *pDSt++ = (308 * r + 600 * g + 116 * b) >> 10; + } +} + +void +_FaceDetectorImpl::ConvertRgb565ToGray(const unsigned char& buf, unsigned char* pGrayBuf, int width, int height) +{ + unsigned char* pDst = null; + unsigned char* pEnd = null; + unsigned short* pSrc = null; + + unsigned short r = 0; + unsigned short g = 0; + unsigned short b = 0; + long lt = 0; + + SysAssert(pGrayBuf != null); + if (pGrayBuf == null) + { + return; + } + + pSrc = (unsigned short*) &buf; + pDst = (unsigned char*) pGrayBuf; + pEnd = (unsigned char*) ((unsigned char*) pGrayBuf + height * width); + + while (pDst < pEnd) + { + r = (unsigned char) ((*pSrc >> 11) << 3); // R + g = (unsigned char) ((*pSrc & 0x07e0) >> 3); // +G + b = (unsigned char) ((*pSrc++ & 0x001f) << 3); // +B + + // Y = 0.299 R + 0.587 G + 0.114 B + lt = (306L * (long) r + 601L * (long) g + 117L * (long) b); + *pDst++ = (unsigned char) (lt >> 10); + //(BYTE)(((int)R+(int)G+(int)B) /3); + } +} + +void +_FaceDetectorImpl::ConvertVirtualToPhysicalCoordinates(int bitmapWidth, int bitmapHeight, int bufferWidth, int bufferHeight, face_rect_s* pFaceRects) +{ + // no need to convert if both are same + if (bufferWidth == bitmapWidth || bufferHeight == bitmapHeight) + { + return; + } + + // Avoid 'division by zero' + if (bufferWidth <= 0 || bufferHeight <= 0) + { + return; + } + + // convert physical coordinate to virtual coordinate + int x1 = pFaceRects->x; + int x2 = x1 + pFaceRects->w; + int y1 = pFaceRects->y; + int y2 = y1 + pFaceRects->h; + + x1 = x1 * bitmapWidth / bufferWidth; + x2 = x2 * bitmapWidth / bufferWidth; + y1 = y1 * bitmapHeight / bufferHeight; + y2 = y2 * bitmapHeight / bufferHeight; + + pFaceRects->x = x1; + pFaceRects->y = y1; + pFaceRects->w = x2 - x1; + pFaceRects->h = y2 - y1; + + return; +} + +int +_FaceDetectorImpl::GetFaceRectsN(face_h& faceHandle, unsigned char* pImageBuffer, int width, int height, + face_image_type_e mode, face_image_colorspace_e faceImageColorspace, face_rect_s** pFaceRects) +{ + result r = E_SUCCESS; + ClearLastResult(); + + int engineErr = 0; + face_image_h faceImage = null; + int faceCount = 0; + int bytePerPixel = 1; + if (faceImageColorspace == FACE_IMAGE_COLORSPACE_RGB565) + { + bytePerPixel = 2; + } + + engineErr = face_image_create(faceImageColorspace, pImageBuffer, width, height, (width * height * bytePerPixel), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, mode, faceImage, pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + face_image_destroy(faceImage); + SetLastResult(r); + + return faceCount; + +CATCH: + face_image_destroy(faceImage); + + SetLastResult(r); + return -1; +} + +_FaceDetectorImpl* +_FaceDetectorImpl::GetInstance(FaceDetector* pFaceDetector) +{ + return pFaceDetector->__pFaceDetectorImpl; +} + +const _FaceDetectorImpl* +_FaceDetectorImpl::GetInstance(const FaceDetector* pFaceDetector) +{ + return pFaceDetector->__pFaceDetectorImpl; +} + +} } } //Tizen::Uix::Vision diff --git a/src/FUixVision_FaceDetectorImpl.h b/src/FUixVision_FaceDetectorImpl.h new file mode 100755 index 0000000..ec3132d --- /dev/null +++ b/src/FUixVision_FaceDetectorImpl.h @@ -0,0 +1,280 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVision_FaceDetectorImpl.h + * @brief This file contains declaration of FUixVision_FaceDetectorImpl class. + * + * + * This header file contains the declarations of the FUixVision_FaceDetectorImpl class. + */ + +#ifndef _FUIX_VISION_INTERNAL_FACEDETECTOR_IMPL_H_ +#define _FUIX_VISION_INTERNAL_FACEDETECTOR_IMPL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "face.h" + +struct CollectionAllElementDelete +{ + template + void operator()(Collection* c) + { + c->RemoveAll(); + delete c; + } +}; + +namespace Tizen { namespace Uix { namespace Vision +{ + +class _FaceDetectorImpl + : public Tizen::Base::Object +{ + +public: + /** + * This is the default constructor for this class. + * The object is not fully constructed after this constructor is called. + * For full construction, the Construct() method must be called right after calling this constructor. + * + * @since 2.0 + */ + _FaceDetectorImpl(void); + + /** + * This is the destructor for this class. + * This destructor overrides Tizen::Base::Object::~Object(). + * + * @since 2.0 + */ + virtual ~_FaceDetectorImpl(void); + + /** + * Initializes this instance of FaceDetector. + * + * @return An error code + * @exception E_SUCCESS The method was successful. + * @exception E_OUT_OF_MEMORY Insufficient memory. + * @since 2.0 + */ + result Construct(void); + + /** + * Retrieves the range and default value of a specified configuration property. + * + * @return The error code. + * @param[in] configProperty Specifies the property to query. + * @param[out] min Receives the minimum value of the property. + * @param[out] max Receives the maximun value of the property. + * @param[out] steppingDelta Receives the step size for the property. The step size is the smallest increment by which the property can change. + * @param[out] defaultVal Receives the default value of the property. + * @exception E_SUCCESS - This method is successful. + * @exception E_UNSUPPORTED_OPERATION - The device does not support this property. + */ + result GetRange(FaceDetectorConfigProperty configProperty, long& min, long& max, long& steppingDelta, long& defaultVal) const; + + /** + * Retrieves the current setting of a specified configuration property. + * + * @return The value of the property. + * @param[in] configProperty Specifies the property to query. + * @exception E_SUCCESS - This method is successful. + * @exception E_UNSUPPORTED_OPERATION - The device does not support this property. + */ + long GetProperty(FaceDetectorConfigProperty configProperty) const; + + /** + * Sets the value of a specified property. + * + * @return The error code. + * @param[in] configProperty Specifies the property to query. + * @param[in] value Specifes the new value of the property. + * @exception E_SUCCESS - This method is successful. + * @exception E_UNSUPPORTED_OPERATION - The device does not support this property. + * @exception E_OUT_OF_RANGE - The specified value is out of range. + * @see GetRange + */ + result SetProperty(FaceDetectorConfigProperty configProperty, long value); + + /** + * Retrieves the supported format list. + * + * @return The list of the supported pixel format. + * @exception E_SUCCESS - This method is successful. + * @exception E_OUT_OF_MEMORY - Failed to allocate required/requested memory. + */ + Tizen::Base::Collection::IListT * GetSupportedFormatListN(void) const; + + /** + * Searches for faces from a video image. + * + * @return The the list of detected faces' position. + * @param[in] byteBuffer Specifies the pointer pointing to the buffer containing the input image data. + * @param[in] resolution Specifies the width and height of the input image. + * @param[in] format Specifies the format of input image. This should be one of the supported formats. + * @exception E_SUCCESS - This method is successful. + * @exception E_OUT_OF_MEMORY - Failed to allocate required/requested memory. + */ + Tizen::Base::Collection::IList* DetectFacesFromBufferN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, const Tizen::Graphics::PixelFormat format); + + /** + * Detects faces from still image. + * + * @return The the list of detected faces' position. + * @param[in] bitmap Specifies the bitmap file containing the input image data. + * @exception E_SUCCESS This method is successful. + * @exception E_OUT_OF_MEMORY Failed to allocate required/requested memory. + */ + Tizen::Base::Collection::IList* DetectFacesFromBitmapN(const Tizen::Graphics::Bitmap& bitmap); + + /** + * Detects faces from still image. + * + * @return The the list of detected faces' position. + * @param[in] byteBuffer Specifies the pointer pointing to the buffer containing the input image data. + * @param[in] resolution Specifies the width and height of the input image. + * @param[in] format The color format defined by Tizen::Graphics::BitmapPixelFormat @n + * @exception E_SUCCESS This method is successful. + * @exception E_OUT_OF_MEMORY Failed to allocate required/requested memory. + */ + Tizen::Base::Collection::IList* DetectFacesFromBitmapN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, Tizen::Graphics::BitmapPixelFormat format); + + /** + * Convert input image data to the gray scale. + * + * @return The gray scale data. + * @param[in] byteBuffer Specifies the buffer containing the input image data. + * @param[in] resolution Specifies the width and height of the input image. + * @param[in] format The color format defined by Tizen::Graphics::PixelFormat @n + * + * @exception E_SUCCESS The method was successful. + * @exception E_OUT_OF_MEMORY Insufficient memory. + * + * @since 2.0 + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::ByteBuffer* ConvertToGrayN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, Tizen::Graphics::PixelFormat format); + + /** + * Searches faces. + * + * @return The list of the detected face positions @n + * Each list's item has a pointer of Tizen::Graphics::Rectangle value. @n + * An empty list, if there are no detected faces and there is no error @n + * The faces are not detected when the faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + * @c null, if an exception occurs. @n + * @param[in] grayBuffer Specifies the grayscale buffer containing the input image data. + * @param[in] resolution Specifies the width and height of the input image. + * @param[in] mode Specifies the detection mode. + * @exception E_SUCCESS - This method is successful. + * @exception E_OUT_OF_MEMORY - Failed to allocate required/requested memory. + * @exception E_FAILURE A system error occurred. + * + * @since 2.0 + * @remarks The specific error code can be accessed using the GetLastResult() method. + */ + Tizen::Base::Collection::IList* DetectFacesN(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, FaceDetectionOption mode); + + /** + * Extracts eye position. + * + * @return An error code + * @param[in] grayBuffer Specifies the grayscale buffer containing the input image data. + * @param[in] resolution Specifies the width and height of the input image. + * @param[in] faceRect The face position + * @param[out] eyeRight The right eye position to be detected + * @param[out] eyeLeft The left eye position to be detected + * @param[out] mouthRect The mouth position + * @exception E_SUCCESS - This method is successful. + * @exception E_OUT_OF_MEMORY - Failed to allocate required/requested memory. + * @exception E_FAILURE A system error occurred. + * @exception E_OPERATION_FAILED There are no extracted eye position. But there is no error @n + * It can be happened when the detected faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + * @since 2.0 + */ + result ExtractFaceComponents(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::Rectangle& faceRect, Tizen::Graphics::Point& eyeRight, + Tizen::Graphics::Point& eyeLeft, Tizen::Graphics::Rectangle& mouthRect); + + /** + * Tracks the interest region. + * + * @return An error code + * @param[in] prevGrayBuffer The previous buffer containing the input image data + * @param[in] curGrayBuffer The current buffer containing the input image data + * @param[in] resolution Specifies the width and height of the input image. + * @param[in] faceRect The region which want to be traced.@n + * @param[out] posDiff The offset wich are moved from previous to current image. + * + * @exception E_SUCCESS The method was successful. + * @exception E_OPERATION_FAILED Failed to track the specified region. But there is no error @n + * It can be happened when the detected faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + * @since 2.0 + */ + result GetPosDifference(const Tizen::Base::ByteBuffer& prevGrayBuffer, const Tizen::Base::ByteBuffer& curGrayBuffer, const Tizen::Graphics::Dimension& resolution, const Tizen::Graphics::Rectangle& faceRect, Tizen::Graphics::Point& posDiff); + + static _FaceDetectorImpl* GetInstance(FaceDetector* pFaceDetector); + static const _FaceDetectorImpl* GetInstance(const FaceDetector* pFaceDetector); + +private: + /** + * The implementation of this copy constructor is intentionally blank and declared as private to prohibit copying of objects. + */ + _FaceDetectorImpl(const _FaceDetectorImpl& value); + /** + * The implementation of this copy assignment operator is intentionally blank and declared as private to prohibit copying of objects. + */ + _FaceDetectorImpl& operator =(const _FaceDetectorImpl& value); + + void ConvertArgb8888ToGray(const unsigned char& buf, unsigned char* pGrayBuf, int width, int height); + void ConvertRgb565ToGray(const unsigned char& buf, unsigned char* pGrayBuf, int width, int height); + int GetFaceRectsN(face_h& faceHandel, unsigned char* pImageBuffer, int width, int height, + face_image_type_e mode, face_image_colorspace_e faceImageColorspace, face_rect_s** pFaceRects); + void ConvertVirtualToPhysicalCoordinates(int bitmapWidth, int bitmapHeight, int bufferWidth, int bufferHeight, face_rect_s* pFaceRects); + + friend class _FaceRecognizerImpl; + +private: + static long __maxFacesAtomic; + static long __scaleAtomic; + long __maxFacesVideo; + long __scaleVideo; + long __maxFacesImage; + long __scaleImage; + face_h __faceHandleVideoMode; + bool __isTrackingMode; +}; + +} } } //Tizen::Uix::Vision + +#endif diff --git a/src/FUixVision_FaceRecognizerImpl.cpp b/src/FUixVision_FaceRecognizerImpl.cpp new file mode 100755 index 0000000..e2b2f74 --- /dev/null +++ b/src/FUixVision_FaceRecognizerImpl.cpp @@ -0,0 +1,1503 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVision_FaceRecognizerImpl.cpp + * @brief This file contains internal implementation of FaceRecognizer Implementation class. + * + * + * This file contains internal implementation of FaceRecognizer Implementation class. + */ + +#include +#include +#include +#include +#include "FUixVision_FaceRecognizerImpl.h" +#include "FUixVision_FaceDetectorImpl.h" + +using namespace Tizen::Base; +using namespace Tizen::Graphics; +using namespace Tizen::Base::Collection; + +namespace Tizen { namespace Uix { namespace Vision +{ +static const int _FR_MAXNUM_VIDEO_DEFAULT = 1; +static const int _FR_MAXNUM_IMAGE_DEFAULT = 10; +static const int _FR_MAXNUM_VIDEO_MAX = 5; +static const int _FR_MAXNUM_IMAGE_MAX = 10; +static const int _FR_MAXNUM_VIDEO_MIN = 1; +static const int _FR_MAXNUM_IMAGE_MIN = 1; +static const int _FR_SCALE_VIDEO_DEFAULT = 3; +static const int _FR_SCALE_IMAGE_DEFAULT = 1; +static const int _FR_SCALE_VIDEO_MAX = 3; +static const int _FR_SCALE_IMAGE_MAX = 3; +static const int _FR_SCALE_VIDEO_MIN = 1; +static const int _FR_SCALE_IMAGE_MIN = 1; + +class _RectHashCodeProvider + : public IHashCodeProviderT +{ +public: + _RectHashCodeProvider(void) {} + virtual ~_RectHashCodeProvider(void) {} + + int GetHashCode(const Tizen::Graphics::Rectangle& obj) const + { + return obj.x; + } +}; + +class _RectComparerT + : public virtual IComparerT + , public Object +{ +public: + _RectComparerT(void) {} + virtual ~_RectComparerT(void) {} + result Compare(const Tizen::Graphics::Rectangle& obj1, const Tizen::Graphics::Rectangle& obj2, int& cmp) const + { + if (obj1 == obj2) + { + cmp = 0; + return E_SUCCESS; + } + else + { + cmp = -1; + return E_INVALID_ARG; + } + } +}; + +result +_FaceRecognizerImpl::Construct(void) +{ + long min = 0; + long max = 0; + long steppingDelta = 0; + result res = E_SUCCESS; + int engineError = 0; + + engineError = face_create(&__faceHandleVideoMode); + SysTryReturn(NID_UIX, engineError == FACE_ERROR_NONE, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed." + , GetErrorMessage(E_OUT_OF_MEMORY)); + + GetRange(FACERECOGNIZER_MAXNUMBER_VIDEO, min, max, steppingDelta, __maxFacesVideo); + GetRange(FACERECOGNIZER_MAXNUMBER_IMAGE, min, max, steppingDelta, __maxFacesImage); + GetRange(FACERECOGNIZER_SCALE_VIDEO, min, max, steppingDelta, __scaleVideo); + GetRange(FACERECOGNIZER_SCALE_IMAGE, min, max, steppingDelta, __scaleImage); + return res; +} + +_FaceRecognizerImpl::_FaceRecognizerImpl(void) + : __scaleVideo(0) + , __scaleImage(0) + , __maxFacesVideo(0) + , __maxFacesImage(0) + , __faceHandleVideoMode(null) +{ +} + +_FaceRecognizerImpl::~_FaceRecognizerImpl(void) +{ + face_destroy(__faceHandleVideoMode); +} + +result +_FaceRecognizerImpl::GetRange(FaceRecognizerConfigProperty configProperty, long& min, long& max, long& steppingDelta, + long& defaultVal) const +{ + result res = E_SUCCESS; + + switch (configProperty) + { + case FACERECOGNIZER_MAXNUMBER_VIDEO: + { + min = _FR_MAXNUM_VIDEO_MIN; + max = _FR_MAXNUM_VIDEO_MAX; + steppingDelta = 1; + defaultVal = _FR_MAXNUM_VIDEO_DEFAULT; + } + break; + + case FACERECOGNIZER_MAXNUMBER_IMAGE: + { + min = _FR_MAXNUM_IMAGE_MIN; + max = _FR_MAXNUM_IMAGE_MAX; + steppingDelta = 1; + defaultVal = _FR_MAXNUM_IMAGE_DEFAULT; + } + break; + + case FACERECOGNIZER_SCALE_VIDEO: + { + min = _FR_SCALE_VIDEO_MIN; + max = _FR_SCALE_VIDEO_MAX; + defaultVal = _FR_SCALE_VIDEO_DEFAULT; + steppingDelta = 1; + } + break; + + case FACERECOGNIZER_SCALE_IMAGE: + { + min = _FR_SCALE_IMAGE_MIN; + max = _FR_SCALE_IMAGE_MAX; + defaultVal = _FR_SCALE_IMAGE_DEFAULT; + steppingDelta = 1; + } + break; + + default: + { + min = 0; + max = 0; + steppingDelta = 1; + defaultVal = 0; + SysLogException(NID_UIX, E_UNSUPPORTED_OPERATION, "[%s] The device does not support this property.", + GetErrorMessage(E_UNSUPPORTED_OPERATION)); + return E_UNSUPPORTED_OPERATION; + } + break; + } + + return res; +} + +long +_FaceRecognizerImpl::GetProperty(FaceRecognizerConfigProperty configProperty) const +{ + ClearLastResult(); + switch (configProperty) + { + case FACERECOGNIZER_MAXNUMBER_VIDEO: + return __maxFacesVideo; + + case FACERECOGNIZER_MAXNUMBER_IMAGE: + return __maxFacesImage; + + case FACERECOGNIZER_SCALE_VIDEO: + return __scaleVideo; + + case FACERECOGNIZER_SCALE_IMAGE: + return __scaleImage; + + default: + { + SysLogException(NID_UIX, E_UNSUPPORTED_OPERATION, "[%s] The device does not support this property.", + GetErrorMessage(E_UNSUPPORTED_OPERATION)); + } + break; + } + return long(-1); +} + +result +_FaceRecognizerImpl::SetProperty(FaceRecognizerConfigProperty configProperty, long value) +{ + long min = 0; + long max = 0; + long steppingDelta = 0; + long defaultVal = 0; + result res = E_SUCCESS; + + //configProperty is always available. Becuase this is checked before calling this function. + res = GetRange(configProperty, min, max, steppingDelta, defaultVal); + SysTryReturn(NID_UIX, value >= min && value <= max && value % steppingDelta == 0, E_OUT_OF_RANGE, E_OUT_OF_RANGE, + "[%s] The specified value (%d) is out of range.", GetErrorMessage(E_OUT_OF_RANGE), value); + + switch (configProperty) + { + case FACERECOGNIZER_MAXNUMBER_VIDEO: + __maxFacesVideo = value; + break; + + case FACERECOGNIZER_MAXNUMBER_IMAGE: + __maxFacesImage = value; + break; + + case FACERECOGNIZER_SCALE_VIDEO: + __scaleVideo = value; + break; + + case FACERECOGNIZER_SCALE_IMAGE: + __scaleImage = value; + break; + + default: + SysLogException(NID_UIX, E_UNSUPPORTED_OPERATION, "[%s] The device does not support this property.", + GetErrorMessage(E_UNSUPPORTED_OPERATION)); + return E_UNSUPPORTED_OPERATION; + } + + return res; +} + +Tizen::Base::Collection::IListT * +_FaceRecognizerImpl::GetSupportedFormatListN(void) const +{ + std::unique_ptr, CollectionAllElementDeleter> + pFormatList(new (std::nothrow) Tizen::Base::Collection::LinkedListT ); + SysTryReturn(NID_UIX, pFormatList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", + GetErrorMessage(E_OUT_OF_MEMORY)); + + pFormatList->InsertAt(Tizen::Graphics::PIXEL_FORMAT_RGB565, 0); + pFormatList->InsertAt(Tizen::Graphics::PIXEL_FORMAT_YCbCr420_PLANAR, 0); + + return pFormatList.release(); +} + +Tizen::Base::Collection::IList* +_FaceRecognizerImpl::ExtractFaceFeaturesFromBufferN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::PixelFormat format) +{ + ClearLastResult(); + result r = E_SUCCESS; + + int engineErr = 0; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + face_component_h faceComponent = null; + face_feature_h faceFeature = null; + std::unique_ptr pFaceInfo; + unsigned char *pFeatureBuffer = null; + int featureLength = 0; + + std::unique_ptr pDetectList(new (std::nothrow) Tizen::Base::Collection::ArrayList()); + SysTryReturn(NID_UIX, pDetectList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", + GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pDetectList->Construct(); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r)); + + if (format == PIXEL_FORMAT_YCbCr420_PLANAR) + { + imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + } + else if (format == PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + } + + engineErr = face_attr_set_max_number_faces(__faceHandleVideoMode, __maxFacesVideo); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(__faceHandleVideoMode, __scaleVideo); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_image_create(imageColorspace, (unsigned char*)byteBuffer.GetPointer(), resolution.width, + resolution.height, (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(__faceHandleVideoMode, FACE_IMAGE_TYPE_CONTINUOUS, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + for (int i = 0; i < faceCount; ++i) + { + engineErr = face_extract_component(__faceHandleVideoMode, faceImage, &pFaceRects[i], &faceComponent); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_feature(__faceHandleVideoMode, faceImage, faceComponent, &faceFeature); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the feature.", GetErrorMessage(E_FAILURE)); + + face_component_destroy(faceComponent); + + engineErr = face_feature_get_data(faceFeature, &pFeatureBuffer, &featureLength); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to get the feature data.", GetErrorMessage(E_FAILURE)); + + ByteBuffer buffer; + r = buffer.Construct(featureLength * sizeof(unsigned char)); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to construct Bytebuffer.", GetErrorMessage(E_FAILURE)); + + r = buffer.SetArray((byte*)pFeatureBuffer, 0, featureLength * sizeof(unsigned char)); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to set the array.", GetErrorMessage(E_FAILURE)); + + pFaceInfo = std::unique_ptr(new (std::nothrow) FaceRecognitionInfo); + SysTryCatch(NID_UIX, pFaceInfo != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + r = pFaceInfo->Construct(buffer); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Failed to construct the FaceRecognitionInfo.", GetErrorMessage(E_FAILURE)); + + pFaceInfo->SetFacePosition(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + r = pDetectList->Add(*(pFaceInfo.release())); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to add the FaceRecognitionInfo.", GetErrorMessage(E_FAILURE)); + + face_feature_destroy(faceFeature); + + } + free(pFaceRects); + face_image_destroy(faceImage); + + return pDetectList.release(); + +CATCH: + + free(pFaceRects); + face_image_destroy(faceImage); + face_component_destroy(faceComponent); + face_feature_destroy(faceFeature); + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IList* +_FaceRecognizerImpl::ExtractFaceFeaturesFromBitmapN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::BitmapPixelFormat format) +{ + ClearLastResult(); + result r = E_SUCCESS; + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + face_component_h faceComponent = null; + face_feature_h faceFeature = null; + std::unique_ptr pFaceInfo; + unsigned char *pFeatureBuffer = null; + int featureLength; + unsigned char* pImageBuffer = null; + + std::unique_ptr pDetectList(new (std::nothrow) Tizen::Base::Collection::ArrayList()); + SysTryReturn(NID_UIX, pDetectList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", + GetErrorMessage(E_OUT_OF_MEMORY)); + r = pDetectList->Construct(); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r)); + + if (format == BITMAP_PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + pImageBuffer = (unsigned char*)byteBuffer.GetPointer(); + engineErr = face_image_create(imageColorspace, pImageBuffer, resolution.width, resolution.height, + (resolution.width * resolution.height * 2), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + } + else if (format == BITMAP_PIXEL_FORMAT_ARGB8888) + { + imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + std::unique_ptr pBuffer(new (std::nothrow) unsigned char[resolution.width * resolution.height]); + SysTryCatch(NID_UIX, pBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + pImageBuffer = pBuffer.get(); + SysTryCatch(NID_UIX, pImageBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Failed to create the Buffer.", GetErrorMessage(E_OUT_OF_MEMORY)); + ConvertArgb8888ToGray(*((unsigned char*)byteBuffer.GetPointer()), pImageBuffer, resolution.width, resolution.height); + engineErr = face_image_create(imageColorspace, pImageBuffer, resolution.width, resolution.height, + (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + } + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, __maxFacesImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, __scaleImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + for (int i = 0; i < faceCount; ++i) + { + engineErr = face_extract_component(faceHandle, faceImage, &pFaceRects[i], &faceComponent); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_feature(faceHandle, faceImage, faceComponent, &faceFeature); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the feature.", GetErrorMessage(E_FAILURE)); + + face_component_destroy(faceComponent); + faceComponent = null; + + engineErr = face_feature_get_data(faceFeature, &pFeatureBuffer, &featureLength); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to get the feature data.", GetErrorMessage(E_FAILURE)); + + ByteBuffer buffer; + r = buffer.Construct(featureLength * sizeof(unsigned char)); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to construct Bytebuffer.", GetErrorMessage(E_FAILURE)); + + r = buffer.SetArray((byte*)pFeatureBuffer, 0, featureLength * sizeof(unsigned char)); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to set the array.", GetErrorMessage(E_FAILURE)); + + pFaceInfo = std::unique_ptr(new (std::nothrow) FaceRecognitionInfo); + SysTryCatch(NID_UIX, pFaceInfo != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pFaceInfo->Construct(buffer); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Failed to construct the FaceRecognitionInfo.", GetErrorMessage(E_FAILURE)); + + pFaceInfo->SetFacePosition(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + + r = pDetectList->Add(*(pFaceInfo.release())); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to add the FaceRecognitionInfo.", GetErrorMessage(E_FAILURE)); + + face_feature_destroy(faceFeature); + faceFeature = null; + + } + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + return pDetectList.release(); + +CATCH: + + free(pFaceRects); + face_image_destroy(faceImage); + if (faceComponent != null) + { + face_component_destroy(faceComponent); + } + if (faceFeature != null) + { + face_feature_destroy(faceFeature); + } + face_destroy(faceHandle); + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IList* +_FaceRecognizerImpl::ExtractFaceFeaturesFromBitmapN(const Tizen::Graphics::Bitmap& bitmap) +{ + ClearLastResult(); + result r = E_SUCCESS; + + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + face_component_h faceComponent = null; + face_feature_h faceFeature = null; + std::unique_ptr pFaceInfo; + unsigned char *pFeatureBuffer = null; + int featureLength; + unsigned char* pImageBuffer = null; + + BufferInfo bitmapInfo; + + r = const_cast (&bitmap)->Lock(bitmapInfo); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + std::unique_ptr pDetectList(new (std::nothrow) Tizen::Base::Collection::ArrayList()); + SysTryReturn(NID_UIX, pDetectList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + r = pDetectList->Construct(); + SysTryReturn(NID_UIX, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r)); + + if (bitmapInfo.pixelFormat == PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + pImageBuffer = (unsigned char*)bitmapInfo.pPixels; + engineErr = face_image_create(imageColorspace, pImageBuffer, bitmapInfo.width, bitmapInfo.height, + (bitmapInfo.width * bitmapInfo.height * 2), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + } + else if (bitmapInfo.pixelFormat == PIXEL_FORMAT_ARGB8888) + { + imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + std::unique_ptr pBuffer(new (std::nothrow) unsigned char[bitmapInfo.width * bitmapInfo.height]); + SysTryCatch(NID_UIX, pBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + pImageBuffer = pBuffer.get(); + SysTryCatch(NID_UIX, pImageBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Failed to create the Buffer.", + GetErrorMessage(E_OUT_OF_MEMORY)); + ConvertArgb8888ToGray(*((unsigned char*)bitmapInfo.pPixels), pImageBuffer, bitmapInfo.width, bitmapInfo.height); + engineErr = face_image_create(imageColorspace, pImageBuffer, bitmapInfo.width, bitmapInfo.height, + (bitmapInfo.width * bitmapInfo.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + } + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, __maxFacesImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, __scaleImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + for (int i = 0; i < faceCount; ++i) + { + engineErr = face_extract_component(faceHandle, faceImage, &pFaceRects[i], &faceComponent); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_feature(faceHandle, faceImage, faceComponent, &faceFeature); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the feature.", GetErrorMessage(E_FAILURE)); + + face_component_destroy(faceComponent); + faceComponent = null; + + engineErr = face_feature_get_data(faceFeature, &pFeatureBuffer, &featureLength); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to get the feature data.", GetErrorMessage(E_FAILURE)); + + ByteBuffer buffer; + r = buffer.Construct(featureLength * sizeof(unsigned char)); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to construct Bytebuffer.", GetErrorMessage(E_FAILURE)); + + r = buffer.SetArray((byte*)pFeatureBuffer, 0, featureLength * sizeof(unsigned char)); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to set the array.", GetErrorMessage(E_FAILURE)); + + pFaceInfo = std::unique_ptr(new (std::nothrow) FaceRecognitionInfo); + SysTryCatch(NID_UIX, pFaceInfo != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pFaceInfo->Construct(buffer); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Failed to construct the FaceRecognitionInfo.", GetErrorMessage(E_FAILURE)); + + ConvertVirtualToPhysicalCoordinates(bitmap.GetWidth(), bitmap.GetHeight(), bitmapInfo.width, bitmapInfo.height, &pFaceRects[i]); + pFaceInfo->SetFacePosition(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + + r = pDetectList->Add(*(pFaceInfo.release())); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to add the FaceRecognitionInfo.", GetErrorMessage(E_FAILURE)); + + face_feature_destroy(faceFeature); + faceFeature = null; + + } + r = const_cast (&bitmap)->Unlock(); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = GetLastResult(), GetLastResult(), "[%s] Propagating.", GetErrorMessage(r)); + + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + return pDetectList.release(); + +CATCH: + + free(pFaceRects); + face_image_destroy(faceImage); + if (faceComponent != null) + { + face_component_destroy(faceComponent); + } + if (faceFeature != null) + { + face_feature_destroy(faceFeature); + } + face_destroy(faceHandle); + + SetLastResult(r); + return null; +} + +int +_FaceRecognizerImpl::MeasureSimilarity(const Tizen::Base::ByteBuffer& face1, const Tizen::Base::ByteBuffer& face2) +{ + ClearLastResult(); + result r = E_SUCCESS; + face_feature_h faceFeature1 = null; + face_feature_h faceFeature2 = null; + int engineErr = 0; + float similarity = 0; + int length1 = face1.GetCapacity(); + int length2 = face2.GetCapacity(); + + engineErr = face_feature_create(&faceFeature1); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the feature data.", GetErrorMessage(E_FAILURE)); + engineErr = face_feature_create(&faceFeature2); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the feature data.", GetErrorMessage(E_FAILURE)); + + engineErr = face_feature_set_data(faceFeature1, (unsigned char*)face1.GetPointer(), length1); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the feature data.", GetErrorMessage(E_FAILURE)); + + engineErr = face_feature_set_data(faceFeature2, (unsigned char*)face2.GetPointer(), length2); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the feature data.", GetErrorMessage(E_FAILURE)); + + engineErr = face_compare_feature(faceFeature1, faceFeature2, &similarity); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to compare the feature data.", GetErrorMessage(E_FAILURE)); + + if (faceFeature1 != null) + { + face_feature_destroy(faceFeature1); + faceFeature1 = null; + } + if (faceFeature2 != null) + { + face_feature_destroy(faceFeature2); + faceFeature2 = null; + } + + SetLastResult(r); + return (int)(similarity * 100); + +CATCH: + if (faceFeature1 != null) + { + face_feature_destroy(faceFeature1); + } + if (faceFeature2 != null) + { + face_feature_destroy(faceFeature2); + } + SetLastResult(r); + return 0; +} + +bool +_FaceRecognizerImpl::IsMatching(const Tizen::Base::ByteBuffer& face1, const Tizen::Base::ByteBuffer& face2) +{ + if (MeasureSimilarity(face1, face2) > 65) + { + return true; + } + else + { + return false; + } +} + +Tizen::Base::Collection::IMapT * +_FaceRecognizerImpl::DetectBlinksFromBitmapN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::BitmapPixelFormat format) +{ + ClearLastResult(); + result r = E_SUCCESS; + + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + face_component_h faceComponent = null; + unsigned char* pImageBuffer = null; + face_eye_state_e leftEye; + face_eye_state_e rightEye; + + IHashCodeProviderT * pRectProvider = null; + std::unique_ptr<_RectHashCodeProvider> pUniqRectProvider(new (std::nothrow) _RectHashCodeProvider); + SysTryReturn(NID_UIX, pUniqRectProvider != null, null, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + IComparerT * pRectComparer = null; + std::unique_ptr<_RectComparerT> pUniqRectComparer(new (std::nothrow) _RectComparerT); + SysTryReturn(NID_UIX, pUniqRectComparer != null, null, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + std::unique_ptr, CollectionAllElementDeleter> + pDetectList (new (std::nothrow) HashMapT ); + SysTryReturn(NID_UIX, pDetectList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + pRectProvider = pUniqRectProvider.get(); + SysTryCatch(NID_UIX, pRectProvider != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Failed to create the IMapT.", GetErrorMessage(E_OUT_OF_MEMORY)); + pRectComparer = pUniqRectComparer.get(); + SysTryCatch(NID_UIX, pRectComparer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Failed to create the IMapT.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pDetectList->Construct(0, 0, *pRectProvider, *pRectComparer); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r)); + + + if (format == BITMAP_PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + pImageBuffer = (unsigned char*)byteBuffer.GetPointer(); + engineErr = face_image_create(imageColorspace, pImageBuffer, resolution.width, resolution.height, + (resolution.width * resolution.height * 2), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + } + else if (format == BITMAP_PIXEL_FORMAT_ARGB8888) + { + imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + std::unique_ptr pBuffer(new (std::nothrow) unsigned char[resolution.width * resolution.height]); + SysTryCatch(NID_UIX, pBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + pImageBuffer = pBuffer.get(); + SysTryCatch(NID_UIX, pImageBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Failed to create the Buffer.", + GetErrorMessage(E_OUT_OF_MEMORY)); + ConvertArgb8888ToGray(*((unsigned char*)byteBuffer.GetPointer()), pImageBuffer, resolution.width, resolution.height); + engineErr = face_image_create(imageColorspace, pImageBuffer, resolution.width, resolution.height, + (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + } + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, __maxFacesImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, __scaleImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + for (int i = 0; i < faceCount; ++i) + { + engineErr = face_extract_component(faceHandle, faceImage, &pFaceRects[i], &faceComponent); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_recognize_blink(faceHandle, faceImage, faceComponent, &leftEye, &rightEye); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to recognize the eye state.", GetErrorMessage(E_FAILURE)); + + EyeState eyeState; + if((leftEye == FACE_EYE_STATE_OPENED) && (rightEye == FACE_EYE_STATE_OPENED)) + { + eyeState = EYE_STATE_BOTH_OPEN; + } + else if((leftEye == FACE_EYE_STATE_CLOSED) && (rightEye == FACE_EYE_STATE_CLOSED)) + { + eyeState = EYE_STATE_BOTH_CLOSED; + } + else + { + eyeState = EYE_STATE_NONE; + } + + Rectangle rect(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + + r = pDetectList->Add(rect, eyeState); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r)); + + face_component_destroy(faceComponent); + faceComponent = null; + } + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + return pDetectList.release(); + +CATCH: + if (faceComponent != null) + { + face_component_destroy(faceComponent); + } + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IMapT * +_FaceRecognizerImpl::RecognizeExpressionsFromBitmapN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + Tizen::Graphics::BitmapPixelFormat format) +{ + ClearLastResult(); + result r = E_SUCCESS; + + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + face_component_h faceComponent = null; + unsigned char* pImageBuffer = null; + face_expression_e faceExpr; + + IHashCodeProviderT * pRectProvider = null; + std::unique_ptr<_RectHashCodeProvider> pUniqRectProvider(new (std::nothrow) _RectHashCodeProvider); + SysTryReturn(NID_UIX, pUniqRectProvider != null, null, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + IComparerT * pRectComparer = null; + std::unique_ptr<_RectComparerT> pUniqRectComparer(new (std::nothrow) _RectComparerT); + SysTryReturn(NID_UIX, pUniqRectComparer != null, null, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + std::unique_ptr, CollectionAllElementDeleter> + pDetectList (new (std::nothrow) HashMapT ); + SysTryReturn(NID_UIX, pDetectList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + pRectProvider = pUniqRectProvider.get(); + SysTryCatch(NID_UIX, pRectProvider != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Failed to create the IMapT.", GetErrorMessage(E_OUT_OF_MEMORY)); + pRectComparer = pUniqRectComparer.get(); + SysTryCatch(NID_UIX, pRectComparer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Failed to create the IMapT.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pDetectList->Construct(0, 0, *pRectProvider, *pRectComparer); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r)); + + if (format == BITMAP_PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + pImageBuffer = (unsigned char*)byteBuffer.GetPointer(); + engineErr = face_image_create(imageColorspace, pImageBuffer, resolution.width, resolution.height, + (resolution.width * resolution.height * 2), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + } + else if (format == BITMAP_PIXEL_FORMAT_ARGB8888) + { + imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + std::unique_ptr pBuffer(new (std::nothrow) unsigned char[resolution.width * resolution.height]); + SysTryCatch(NID_UIX, pBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + pImageBuffer = pBuffer.get(); + SysTryCatch(NID_UIX, pImageBuffer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Failed to create the Buffer.", + GetErrorMessage(E_OUT_OF_MEMORY)); + ConvertArgb8888ToGray(*((unsigned char*)byteBuffer.GetPointer()), pImageBuffer, resolution.width, resolution.height); + engineErr = face_image_create(imageColorspace, pImageBuffer, resolution.width, resolution.height, + (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + } + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, __maxFacesImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, __scaleImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + for (int i = 0; i < faceCount; ++i) + { + engineErr = face_extract_component(faceHandle, faceImage, &pFaceRects[i], &faceComponent); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_recognize_expression(faceHandle, faceImage, faceComponent, &faceExpr); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to recognize the expression.", GetErrorMessage(E_FAILURE)); + + FacialExpression expression = FACIAL_EXPRESSION_NONE; + + switch(faceExpr) + { + case FACE_EXPRESSION_NUETRAL: + expression = FACIAL_EXPRESSION_NEUTRAL; + break; + case FACE_EXPRESSION_ANGRY: + expression = FACIAL_EXPRESSION_ANGRY; + break; + case FACE_EXPRESSION_SMILE: + expression = FACIAL_EXPRESSION_HAPPY; + break; + case FACE_EXPRESSION_SURPRISE: + expression = FACIAL_EXPRESSION_SURPRISED; + break; + case FACE_EXPRESSION_UNKNOWN: + expression = FACIAL_EXPRESSION_NONE; + break; + default: + break; + } + Rectangle rect(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + + r = pDetectList->Add(rect, expression); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r)); + + face_component_destroy(faceComponent); + faceComponent = null; + } + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + return pDetectList.release(); + +CATCH: + if (faceComponent != null) + { + face_component_destroy(faceComponent); + } + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IMapT * +_FaceRecognizerImpl::DetectBlinksFromBufferN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::PixelFormat format) +{ + ClearLastResult(); + result r = E_SUCCESS; + + int engineErr = 0; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + face_component_h faceComponent = null; + face_eye_state_e leftEye; + face_eye_state_e rightEye; + + IHashCodeProviderT * pRectProvider = null; + std::unique_ptr<_RectHashCodeProvider> pUniqRectProvider(new (std::nothrow) _RectHashCodeProvider); + SysTryReturn(NID_UIX, pUniqRectProvider != null, null, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + IComparerT * pRectComparer = null; + std::unique_ptr<_RectComparerT> pUniqRectComparer(new (std::nothrow) _RectComparerT); + SysTryReturn(NID_UIX, pUniqRectComparer != null, null, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + std::unique_ptr, CollectionAllElementDeleter> + pDetectList (new (std::nothrow) HashMapT ); + SysTryReturn(NID_UIX, pDetectList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + pRectProvider = pUniqRectProvider.get(); + SysTryCatch(NID_UIX, pRectProvider != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Failed to create the IMapT.", GetErrorMessage(E_OUT_OF_MEMORY)); + pRectComparer = pUniqRectComparer.get(); + SysTryCatch(NID_UIX, pRectComparer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Failed to create the IMapT.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pDetectList->Construct(0, 0, *pRectProvider, *pRectComparer); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r)); + + if (format == PIXEL_FORMAT_YCbCr420_PLANAR) + { + imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + } + else if (format == PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + } + + engineErr = face_attr_set_max_number_faces(__faceHandleVideoMode, __maxFacesVideo); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(__faceHandleVideoMode, __scaleVideo); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_image_create(imageColorspace, (unsigned char*)byteBuffer.GetPointer(), resolution.width, + resolution.height, (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(__faceHandleVideoMode, FACE_IMAGE_TYPE_CONTINUOUS, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + for (int i = 0; i < faceCount; ++i) + { + engineErr = face_extract_component(__faceHandleVideoMode, faceImage, &pFaceRects[i], &faceComponent); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_recognize_blink(__faceHandleVideoMode, faceImage, faceComponent, &leftEye, &rightEye); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to recognize the eye state.", GetErrorMessage(E_FAILURE)); + + EyeState eyeState; + if((leftEye == FACE_EYE_STATE_OPENED) && (rightEye == FACE_EYE_STATE_OPENED)) + { + eyeState = EYE_STATE_BOTH_OPEN; + } + else if((leftEye == FACE_EYE_STATE_CLOSED) && (rightEye == FACE_EYE_STATE_CLOSED)) + { + eyeState = EYE_STATE_BOTH_CLOSED; + } + else + { + eyeState = EYE_STATE_NONE; + } + + Rectangle rect(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + + r = pDetectList->Add(rect, eyeState); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r)); + + face_component_destroy(faceComponent); + } + free(pFaceRects); + face_image_destroy(faceImage); + + return pDetectList.release(); +CATCH: + free(pFaceRects); + face_image_destroy(faceImage); + + SetLastResult(r); + return null; +} + +Tizen::Base::Collection::IMapT * +_FaceRecognizerImpl::RecognizeExpressionsFromBufferN(const Tizen::Base::ByteBuffer& byteBuffer, + const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::PixelFormat format) +{ + ClearLastResult(); + result r = E_SUCCESS; + + int engineErr = 0; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + int faceCount = 0; + face_component_h faceComponent = null; + face_expression_e faceExpr; + + IHashCodeProviderT * pRectProvider = null; + std::unique_ptr<_RectHashCodeProvider> pUniqRectProvider(new (std::nothrow) _RectHashCodeProvider); + SysTryReturn(NID_UIX, pUniqRectProvider != null, null, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + IComparerT * pRectComparer = null; + std::unique_ptr<_RectComparerT> pUniqRectComparer(new (std::nothrow) _RectComparerT); + SysTryReturn(NID_UIX, pUniqRectComparer != null, null, E_OUT_OF_MEMORY, + "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY)); + + std::unique_ptr, CollectionAllElementDeleter> + pDetectList (new (std::nothrow) HashMapT ); + SysTryReturn(NID_UIX, pDetectList != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", + GetErrorMessage(E_OUT_OF_MEMORY)); + + pRectProvider = pUniqRectProvider.get(); + SysTryCatch(NID_UIX, pRectProvider != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Failed to create the IMapT.", GetErrorMessage(E_OUT_OF_MEMORY)); + pRectComparer = pUniqRectComparer.get(); + SysTryCatch(NID_UIX, pRectComparer != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, + "[%s] Failed to create the IMapT.", GetErrorMessage(E_OUT_OF_MEMORY)); + + r = pDetectList->Construct(0, 0, *pRectProvider, *pRectComparer); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r)); + + if (format == PIXEL_FORMAT_YCbCr420_PLANAR) + { + imageColorspace = FACE_IMAGE_COLORSPACE_YUV420; + } + else if (format == PIXEL_FORMAT_RGB565) + { + imageColorspace = FACE_IMAGE_COLORSPACE_RGB565; + } + + engineErr = face_attr_set_max_number_faces(__faceHandleVideoMode, __maxFacesVideo); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(__faceHandleVideoMode, __scaleVideo); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_image_create(imageColorspace, (unsigned char*)byteBuffer.GetPointer(), resolution.width, + resolution.height, (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(__faceHandleVideoMode, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + for (int i = 0; i < faceCount; ++i) + { + engineErr = face_extract_component(__faceHandleVideoMode, faceImage, &pFaceRects[i], &faceComponent); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_recognize_expression(__faceHandleVideoMode, faceImage, faceComponent, &faceExpr); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to recognize the expression.", GetErrorMessage(E_FAILURE)); + + FacialExpression expression = FACIAL_EXPRESSION_NONE; + + switch(faceExpr) + { + case FACE_EXPRESSION_NUETRAL: + expression = FACIAL_EXPRESSION_NEUTRAL; + break; + + case FACE_EXPRESSION_ANGRY: + expression = FACIAL_EXPRESSION_ANGRY; + break; + + case FACE_EXPRESSION_SMILE: + expression = FACIAL_EXPRESSION_HAPPY; + break; + + case FACE_EXPRESSION_SURPRISE: + expression = FACIAL_EXPRESSION_SURPRISED; + break; + + case FACE_EXPRESSION_UNKNOWN: + expression = FACIAL_EXPRESSION_NONE; + break; + + default: + break; + } + Rectangle rect(pFaceRects[i].x, pFaceRects[i].y, pFaceRects[i].w, pFaceRects[i].h); + + r = pDetectList->Add(rect, expression); + SysTryCatch(NID_UIX, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r)); + + face_component_destroy(faceComponent); + faceComponent = null; + } + free(pFaceRects); + face_image_destroy(faceImage); + + return pDetectList.release(); +CATCH: + if (faceComponent != null) + { + face_component_destroy(faceComponent); + faceComponent = null; + } + + free(pFaceRects); + face_image_destroy(faceImage); + + SetLastResult(r); + return null; +} + +Tizen::Base::ByteBuffer* +_FaceRecognizerImpl::ExtractFeatureN(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::Rectangle& faceRect) +{ + ClearLastResult(); + result r = E_SUCCESS; + + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + face_rect_s interestFaceRect; + int faceCount = 0; + face_component_h faceComponent = null; + face_feature_h faceFeature = null; + unsigned char *pFeatureBuffer = null; + int featureLength = 0; + + std::unique_ptr pBuffer(new (std::nothrow) Tizen::Base::ByteBuffer()); + SysTryReturn(NID_UIX, pBuffer != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", + GetErrorMessage(E_OUT_OF_MEMORY)); + + interestFaceRect.x = faceRect.x; + interestFaceRect.y = faceRect.y; + interestFaceRect.w = faceRect.width; + interestFaceRect.h = faceRect.height; + + engineErr = face_image_create(imageColorspace, (unsigned char*)grayBuffer.GetPointer(), resolution.width, + resolution.height, (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, _FaceDetectorImpl::__maxFacesAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, _FaceDetectorImpl::__scaleAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_component(faceHandle, faceImage, &interestFaceRect, &faceComponent); + + if(engineErr != FACE_ERROR_NONE) + { + engineErr = face_attr_set_detect_mode(faceHandle, FACE_DETECT_MODE_ROBUST); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set detect mode to ROBUST", + GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face at ROBUST mode", + GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_component(faceHandle, faceImage, &interestFaceRect, &faceComponent); + } + + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_feature(faceHandle, faceImage, faceComponent, &faceFeature); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the feature.", GetErrorMessage(E_FAILURE)); + + engineErr = face_feature_get_data(faceFeature, &pFeatureBuffer, &featureLength); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to get the feature data.", GetErrorMessage(E_FAILURE)); + + r = pBuffer->Construct(featureLength * sizeof(unsigned char)); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to construct Bytebuffer.", GetErrorMessage(E_FAILURE)); + + r = pBuffer->SetArray((byte*)pFeatureBuffer, 0, featureLength * sizeof(unsigned char)); + SysTryCatch(NID_UIX, r == E_SUCCESS, r = E_FAILURE, r, "[%s] Failed to set the array.", GetErrorMessage(E_FAILURE)); + + face_component_destroy(faceComponent); + face_feature_destroy(faceFeature); + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + return pBuffer.release(); + +CATCH: + face_component_destroy(faceComponent); + face_feature_destroy(faceFeature); + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + SetLastResult(r); + return null; +} + +EyeState +_FaceRecognizerImpl::DetectEyeState(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::Rectangle& faceRect) +{ + ClearLastResult(); + result r = E_SUCCESS; + EyeState eyeState = EYE_STATE_NONE; + + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + face_rect_s interestFaceRect; + int faceCount = 0; + face_component_h faceComponent = null; + face_eye_state_e leftEye; + face_eye_state_e rightEye; + + interestFaceRect.x = faceRect.x; + interestFaceRect.y = faceRect.y; + interestFaceRect.w = faceRect.width; + interestFaceRect.h = faceRect.height; + + engineErr = face_image_create(imageColorspace, (unsigned char*)grayBuffer.GetPointer(), resolution.width, + resolution.height, (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, _FaceDetectorImpl::__maxFacesAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, _FaceDetectorImpl::__scaleAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_component(faceHandle, faceImage, &interestFaceRect, &faceComponent); + + if(engineErr != FACE_ERROR_NONE) + { + engineErr = face_attr_set_detect_mode(faceHandle, FACE_DETECT_MODE_ROBUST); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set detect mode to ROBUST", + GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face at ROBUST mode", + GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_component(faceHandle, faceImage, &interestFaceRect, &faceComponent); + } + + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_recognize_blink(faceHandle, faceImage, faceComponent, &leftEye, &rightEye); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to recognize the eye state.", GetErrorMessage(E_FAILURE)); + + if((leftEye == FACE_EYE_STATE_OPENED) && (rightEye == FACE_EYE_STATE_OPENED)) + { + eyeState = EYE_STATE_BOTH_OPEN; + } + else if((leftEye == FACE_EYE_STATE_CLOSED) && (rightEye == FACE_EYE_STATE_CLOSED)) + { + eyeState = EYE_STATE_BOTH_CLOSED; + } + else + { + eyeState = EYE_STATE_NONE; + } + face_component_destroy(faceComponent); + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + return eyeState; + +CATCH: + face_component_destroy(faceComponent); + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + SetLastResult(r); + return eyeState; +} + +FacialExpression +_FaceRecognizerImpl::RecognizeExpression(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, + const Tizen::Graphics::Rectangle& faceRect) +{ + ClearLastResult(); + result r = E_SUCCESS; + FacialExpression expression = FACIAL_EXPRESSION_NONE; + int engineErr = 0; + face_h faceHandle = null; + face_image_colorspace_e imageColorspace = FACE_IMAGE_COLORSPACE_LUMINANCE_ONLY; + face_image_h faceImage = null; + face_rect_s* pFaceRects = null; + face_rect_s interestFaceRect; + int faceCount = 0; + face_component_h faceComponent = null; + face_expression_e faceExpr; + + interestFaceRect.x = faceRect.x; + interestFaceRect.y = faceRect.y; + interestFaceRect.w = faceRect.width; + interestFaceRect.h = faceRect.height; + + engineErr = face_image_create(imageColorspace, (unsigned char*)grayBuffer.GetPointer(), resolution.width, + resolution.height, (resolution.width * resolution.height), &faceImage); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceImage.", GetErrorMessage(E_FAILURE)); + + engineErr = face_create(&faceHandle); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to create the faceHandle.", GetErrorMessage(E_FAILURE)); + + engineErr = face_attr_set_max_number_faces(faceHandle, _FaceDetectorImpl::__maxFacesAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + engineErr = face_attr_set_scale_factor(faceHandle, _FaceDetectorImpl::__scaleAtomic); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set the property.", GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face.", GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_component(faceHandle, faceImage, &interestFaceRect, &faceComponent); + + if(engineErr != FACE_ERROR_NONE) + { + engineErr = face_attr_set_detect_mode(faceHandle, FACE_DETECT_MODE_ROBUST); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to set detect mode to ROBUST", + GetErrorMessage(E_FAILURE)); + + engineErr = face_detect_faces(faceHandle, FACE_IMAGE_TYPE_SINGLE, faceImage, &pFaceRects, &faceCount); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to detect the Face at ROBUST mode", + GetErrorMessage(E_FAILURE)); + + engineErr = face_extract_component(faceHandle, faceImage, &interestFaceRect, &faceComponent); + } + + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to extract the components.", GetErrorMessage(E_FAILURE)); + + engineErr = face_recognize_expression(faceHandle, faceImage, faceComponent, &faceExpr); + SysTryCatch(NID_UIX, engineErr == FACE_ERROR_NONE, r = E_FAILURE, E_FAILURE, "[%s] Failed to recognize the eye state.", GetErrorMessage(E_FAILURE)); + + switch(faceExpr) + { + case FACE_EXPRESSION_NUETRAL: + expression = FACIAL_EXPRESSION_NEUTRAL; + break; + + case FACE_EXPRESSION_ANGRY: + expression = FACIAL_EXPRESSION_ANGRY; + break; + + case FACE_EXPRESSION_SMILE: + expression = FACIAL_EXPRESSION_HAPPY; + break; + + case FACE_EXPRESSION_SURPRISE: + expression = FACIAL_EXPRESSION_SURPRISED; + break; + + case FACE_EXPRESSION_UNKNOWN: + expression = FACIAL_EXPRESSION_NONE; + break; + + default: + break; + } + + face_component_destroy(faceComponent); + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + return expression; + +CATCH: + face_component_destroy(faceComponent); + free(pFaceRects); + face_image_destroy(faceImage); + face_destroy(faceHandle); + + SetLastResult(r); + return expression; +} + +void +_FaceRecognizerImpl::ConvertArgb8888ToGray(const unsigned char& buf, unsigned char* pGrayBuf, int width, int height) +{ + SysAssert(pGrayBuf != null); + if (pGrayBuf == null) + { + return; + } + unsigned long* pSrc = (unsigned long*) &buf; + unsigned char* pDSt = (unsigned char*) pGrayBuf; + unsigned char* pEnd = pDSt + height * width; + + while (pDSt < pEnd) + { + unsigned long r = (*pSrc >> 16) & 0xFF; + unsigned long g = (*pSrc >> 8) & 0xFF; + unsigned long b = (*pSrc++) & 0xFF; + + *pDSt++ = (308 * r + 600 * g + 116 * b) >> 10; + } +} + +void +_FaceRecognizerImpl::ConvertVirtualToPhysicalCoordinates(int bitmapWidth, int bitmapHeight, int bufferWidth, int bufferHeight, face_rect_s* pFaceRects) +{ + // no need to convert if both are same + if (bufferWidth == bitmapWidth || bufferHeight == bitmapHeight) + { + return; + } + + // Avoid 'division by zero' + if (bufferWidth <= 0 || bufferHeight <= 0) + { + return; + } + + // convert physical coordinate to virtual coordinate + int x1 = pFaceRects->x; + int x2 = x1 + pFaceRects->w; + int y1 = pFaceRects->y; + int y2 = y1 + pFaceRects->h; + + x1 = x1 * bitmapWidth / bufferWidth; + x2 = x2 * bitmapWidth / bufferWidth; + y1 = y1 * bitmapHeight / bufferHeight; + y2 = y2 * bitmapHeight / bufferHeight; + + pFaceRects->x = x1; + pFaceRects->y = y1; + pFaceRects->w = x2 - x1; + pFaceRects->h = y2 - y1; + + return; +} + +_FaceRecognizerImpl* +_FaceRecognizerImpl::GetInstance(FaceRecognizer* pFaceRecognizer) +{ + return pFaceRecognizer->__pFaceRecognizerImpl; +} + +const _FaceRecognizerImpl* +_FaceRecognizerImpl::GetInstance(const FaceRecognizer* pFaceRecognizer) +{ + return pFaceRecognizer->__pFaceRecognizerImpl; +} + +} } } //Tizen::Uix::Vision diff --git a/src/FUixVision_FaceRecognizerImpl.h b/src/FUixVision_FaceRecognizerImpl.h new file mode 100755 index 0000000..dff4ac1 --- /dev/null +++ b/src/FUixVision_FaceRecognizerImpl.h @@ -0,0 +1,348 @@ +// +// Open Service Platform +// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the License); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/** + * @file FUixVision_FaceRecognizerImpl.h + * @brief This file contains declaration of the FUixVision_FaceRecognizerImpl class. + * + * + * This header file contains the declarations of the FUixVision_FaceRecognizerImpl class. + */ + +#ifndef _FUIX_VISION_INTERNAL_FACE_RECOGNIZER_IMPL_H_ +#define _FUIX_VISION_INTERNAL_FACE_RECOGNIZER_IMPL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct CollectionAllElementDeleter +{ + template + void operator()(Collection* c) + { + c->RemoveAll(); + delete c; + } +}; + +namespace Tizen { namespace Uix { namespace Vision +{ + +class _FaceRecognizerImpl + : public Tizen::Base::Object +{ + +public: + /** + * This is the default constructor for this class. + * The object is not fully constructed after this constructor is called. + * For full construction, the Construct() method must be called right after calling this constructor. + * + * @since 2.0 + */ + _FaceRecognizerImpl(void); + + /** + * This is the destructor for this class. + * This destructor overrides Tizen::Base::Object::~Object(). + * + * @since 2.0 + */ + virtual ~_FaceRecognizerImpl(void); + + result Construct(void); + + /** + * Retrieves the supported format list. + * + * @return The list of the supported pixel format. + * @exception E_SUCCESS - This method is successful. + * @exception E_OUT_OF_MEMORY - Failed to allocate required/requested memory. + */ + Tizen::Base::Collection::IListT * GetSupportedFormatListN(void) const; + + /** + * Extracts the facial template that represents the face from the video image. + * + * @return The list of the FaceRecognitionInfo objects which contain the extracted facial features. + * @param[in] byteBuffer Specifies the pointer pointing to the buffer containing the input image data. + * @param[in] resolution Specifies the width and height of the input image. + * @param[in] format Specifies the format of input image. This should be one of the supported formats. + * @exception E_SUCCESS - This method is successful. + * @exception E_OUT_OF_MEMORY - Failed to allocate required/requested memory. + * @see FaceRecognitionInfo + */ + Tizen::Base::Collection::IList* ExtractFaceFeaturesFromBufferN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, const Tizen::Graphics::PixelFormat format); + + /** + * Extracts the facial template that represents the face from the still image. + * + * @return The list of the FaceInfo objects which contain the extracted facial features. + * @param[in] bitmap Specifies the bitmap file containing the input image data. + * @exception E_SUCCESS - This method is successful. + * @exception E_OUT_OF_MEMORY - Failed to allocate required/requested memory. + * @see FaceRecognitionInfo + */ + Tizen::Base::Collection::IList* ExtractFaceFeaturesFromBitmapN(const Tizen::Graphics::Bitmap& bitmap); + + /** + * Extracts the facial template that represents the face from the still image. + * + * @return The list of the FaceRecognitionInfo objects which contain the extracted facial features. + * @param[in] byteBuffer The buffer containing the input image data + * @param[in] resolution The width and height of the input image @n + * @param[in] format The color format defined by Tizen::Graphics:: BitmapPixelFormat @n + * @exception E_SUCCESS - This method is successful. + * @exception E_OUT_OF_MEMORY - Failed to allocate required/requested memory. + * @see FaceRecognitionInfo + */ + Tizen::Base::Collection::IList* ExtractFaceFeaturesFromBitmapN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, Tizen::Graphics::BitmapPixelFormat format); + + /** + * Recognizes whether two given faces are matching or not. + * + * @return The result of match, if two faces are matching it return true; otherwise false. + * @param[in] face1 Specifies the face features of the first face. + * @param[in] face2 Specifies the face features of the second face. + * @see FaceRecognitionInfo + */ + bool IsMatching(const Tizen::Base::ByteBuffer& face1, const Tizen::Base::ByteBuffer& face2); + + /** + * Get the similarity of the two specified faces. + * + * @return The similarity. + * @param[in] face1 Specifies the face features of the first face. + * @param[in] face2 Specifies the face features of the second face. + * @exception E_SUCCESS - This method is successful. + */ + int MeasureSimilarity(const Tizen::Base::ByteBuffer& face1, const Tizen::Base::ByteBuffer& face2); + + + /** + * Retrieves the range and default value of a specified configuration property. + * + * @return The error code. + * @param[in] configProperty Specifies the property to query. + * @param[out] min Receives the minimum value of the property. + * @param[out] max Receives the maximun value of the property. + * @param[out] steppingDelta Receives the step size for the property. The step size is the smallest increment by which the property can change. + * @param[out] defaultVal Receives the default value of the property. + * @exception E_SUCCESS This method is successful. + * @exception E_INVALID_ARG The device does not support this property. + */ + result GetRange(FaceRecognizerConfigProperty configProperty, long& min, long& max, long& steppingDelta, long& defaultVal) const; + + /** + * Retrieves the current setting of a specified configuration property. + * + * @return The value of the property. + * @param[in] configProperty Specifies the property to query. + * @exception E_SUCCESS This method is successful. + * @exception E_INVALID_ARG The device does not support this property. + */ + long GetProperty(FaceRecognizerConfigProperty configProperty) const; + + /** + * Sets the value for a specified property.. + * + * @return The error code. + * @param[in] configProperty Specifies the property to query. + * @param[in] value Specifes the new value of the property. + * @exception E_SUCCESS This method is successful. + * @exception E_INVALID_ARG The argument passed to a method contains an invalid value. @n + *   The @c value is out of range. @n + *   The @c configProperty is not supported property. + */ + result SetProperty(FaceRecognizerConfigProperty configProperty, long value); + + + /** + * Extracts the eye state from the still image. + * + * @return The list of eye state @n + * Each list's item has EyeState value. @n + * EYE_STATE_NONE, if there are no detected eye states and there is no error @n + * The eyes' states are not detected when the faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + * @c null, if an exception occurs. @n + * + * @param[in] byteBuffer The buffer containing the input image data + * @param[in] resolution The width and height of the input image @n + * @param[in] format The color format defined by Tizen::Graphics:: BitmapPixelFormat @n + * @exception E_SUCCESS This method is successful. + * @exception E_OUT_OF_MEMORY Failed to allocate required/requested memory. + * @exception E_FAILURE A system error occurred. + * @see EyeState + */ + Tizen::Base::Collection::IMapT * DetectBlinksFromBitmapN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, Tizen::Graphics::BitmapPixelFormat format); + + + /** + * Extracts the eye state from the video image. + * + * @return The list of eye state @n + * Each list's item has EyeState value. @n + * EYE_STATE_NONE, if there are no detected eye states and there is no error @n + * The eyes' states are not detected when the faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + * @c null, if an exception occurs. @n + * + * @param[in] byteBuffer The buffer containing the input image data. + * @param[in] resolution The width and height of the input image @n + * @param[in] format Specifies the format of input image. This should be one of the supported formats. + * @exception E_SUCCESS This method is successful. + * @exception E_OUT_OF_MEMORY Failed to allocate required/requested memory. + * @exception E_FAILURE A system error occurred. + * @see EyeState + */ + Tizen::Base::Collection::IMapT * DetectBlinksFromBufferN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, const Tizen::Graphics::PixelFormat format); + + /** + * Extracts the facial expression the face from the still image. + * + * @return The list of facial expression @n + * Each list's item has FacialExpression value. @n + * FACIAL_EXPRESSION_NONE, if there are no detected eye states and there is no error @n + * The expressions are not detected when the faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + * @c null, if an exception occurs. @n + * + * @param[in] byteBuffer The buffer containing the input image data + * @param[in] resolution The width and height of the input image @n + * @param[in] format The color format defined by Tizen::Graphics:: BitmapPixelFormat @n + * @exception E_SUCCESS This method is successful. + * @exception E_OUT_OF_MEMORY Failed to allocate required/requested memory. + * @exception E_FAILURE A system error occurred. + * @see FacialExpression + */ + Tizen::Base::Collection::IMapT * RecognizeExpressionsFromBitmapN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, Tizen::Graphics::BitmapPixelFormat format); + + /** + * Extracts the facial expression from the video image. + * + * @return The list of facial expression @n + * Each list's item has FacialExpression value. @n + * FACIAL_EXPRESSION_NONE, if there are no detected eye states and there is no error @n + * The expressions are not recognized when the faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + * @c null, if an exception occurs. @n + * + * @param[in] byteBuffer The buffer containing the input image data + * @param[in] resolution The width and height of the input image @n + * @param[in] format Specifies the format of input image. This should be one of the supported formats. + * @exception E_SUCCESS This method is successful. + * @exception E_OUT_OF_MEMORY Failed to allocate required/requested memory. + * @exception E_FAILURE A system error occurred. + * @see EyeState + */ + Tizen::Base::Collection::IMapT * RecognizeExpressionsFromBufferN(const Tizen::Base::ByteBuffer& byteBuffer, const Tizen::Graphics::Dimension& resolution, const Tizen::Graphics::PixelFormat format); + + /** + * Extracts the facial template that represents the face + * + * @return The facial template that represents the face + * @c null, if an exception occurs. @n + * @param[in] grayBuffer The buffer containing the input image data + * @param[in] resolution The width and height of the input image @n + * @param[in] eyeRight The right eye position + * @param[in] eyeLeft The left eye position + * @exception E_SUCCESS This method is successful. + * @exception E_OUT_OF_MEMORY Failed to allocate required/requested memory. + * @exception E_FAILURE A system error occurred. + * @exception E_OPERATION_FAILED There are no extracted facial information. But there is no error @n + * It can be happened when the detected faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + */ + Tizen::Base::ByteBuffer* ExtractFeatureN(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, const Tizen::Graphics::Rectangle& faceRect); + + /** + * Extracts the eye state. + * + * @return The EyeState + * @c EYE_STATE_NONE, if an exception occurs. @n + * @param[in] grayBuffer The buffer containing the input image data + * @param[in] resolution The width and height of the input image @n + * @param[in] eyeRight The right eye position + * @param[in] eyeLeft The left eye position + * @exception E_SUCCESS This method is successful. + * @exception E_OUT_OF_MEMORY Failed to allocate required/requested memory. + * @exception E_FAILURE A system error occurred. + * @exception E_OPERATION_FAILED There are no detected eye state. But there is no error @n + * It can be happened when the detected faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + * @see EyeState + */ + EyeState DetectEyeState(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, const Tizen::Graphics::Rectangle& faceRect); + + /** + * Extracts the facial expression. + * + * @return The FacialExpression + * @c FACIAL_EXPRESSION_NONE, if an exception occurs. @n + * @param[in] grayBuffer The buffer containing the input image data + * @param[in] resolution The width and height of the input image @n + * @param[in] eyeRight The right eye position + * @param[in] eyeLeft The left eye position + * @exception E_SUCCESS This method is successful. + * @exception E_OUT_OF_MEMORY Failed to allocate required/requested memory. + * @exception E_FAILURE A system error occurred. + * @exception E_OPERATION_FAILED There are no recognized facial expression. But there is no error @n + * It can be happened when the detected faces are too small or the image is not clear. @n + * This is the result of a normal operation. @n + * @see FacialExpression + */ + FacialExpression RecognizeExpression(const Tizen::Base::ByteBuffer& grayBuffer, const Tizen::Graphics::Dimension& resolution, const Tizen::Graphics::Rectangle& faceRect); + + static _FaceRecognizerImpl* GetInstance(FaceRecognizer* pFaceRecognizer); + static const _FaceRecognizerImpl* GetInstance(const FaceRecognizer* pFaceRecognizer); + +private: + /** + * The implementation of this copy assignment operator is intentionally blank and declared as private to prohibit copying of objects. + */ + _FaceRecognizerImpl& operator =(const _FaceRecognizerImpl& faceImpl); + /** + * The implementation of this copy constructor is intentionally blank and declared as private to prohibit copying of objects. + */ + _FaceRecognizerImpl(const _FaceRecognizerImpl& faceImpl); + + void ConvertArgb8888ToGray(const unsigned char& buf, unsigned char* pGrayBuf, int width, int height); + void ConvertVirtualToPhysicalCoordinates(int bitmapWidth, int bitmapHeight, int bufferWidth, int bufferHeight, face_rect_s* pFaceRects); + + +private: + long __scaleVideo; + long __scaleImage; + long __maxFacesVideo; + long __maxFacesImage; + face_h __faceHandleVideoMode; +}; + +} } } //Tizen::Uix::Vision +#endif