Merging newest master branch in.
This commit is contained in:
commit
bd0cebbef0
61 changed files with 5794 additions and 316 deletions
26
.gitignore
vendored
26
.gitignore
vendored
|
@ -6,7 +6,7 @@ lib/local/LandmarkDetector/x64/
|
|||
exe/FaceLandmarkImg/x64/
|
||||
exe/FaceLandmarkVid/x64/
|
||||
exe/FeatureExtraction/x64/
|
||||
x64/Release/
|
||||
/x64/Release/
|
||||
OpenFace.VC.opendb
|
||||
OpenFace.sdf
|
||||
matlab_runners/Action Unit Experiments/AU_preds/
|
||||
|
@ -21,13 +21,14 @@ matlab_runners/Feature Point Experiments/yt_features_clm/
|
|||
matlab_runners/Gaze Experiments/mpii_out/
|
||||
build/
|
||||
Release/AU_predictors/
|
||||
Release/
|
||||
/Debug/
|
||||
/Release/
|
||||
exe/Recording/recording/
|
||||
ipch/
|
||||
exe/FeatureExtraction/out_bp4d/
|
||||
matlab_runners/Action Unit Experiments/out_bp4d/
|
||||
matlab_runners/Action Unit Experiments/out_SEMAINE/
|
||||
x64/Debug/
|
||||
/x64/Debug/
|
||||
matlab_runners/Action Unit Experiments/out_unbc/
|
||||
matlab_runners/Action Unit Experiments/out_bosph/
|
||||
matlab_runners/Action Unit Experiments/out_DISFA/
|
||||
|
@ -51,5 +52,22 @@ lib/local/LandmarkDetector/Debug/
|
|||
OpenFaceDemo/bin/
|
||||
OpenFaceDemo/obj/
|
||||
Debug/model/
|
||||
Debug/
|
||||
*.suo
|
||||
lib/3rdParty/dlib/Debug/
|
||||
lib/local/FaceAnalyser/Debug/
|
||||
lib/local/LandmarkDetector/Debug/
|
||||
matlab_runners/Head Pose Experiments/experiments/biwi_out/
|
||||
matlab_runners/Head Pose Experiments/experiments/bu_out/
|
||||
matlab_runners/Head Pose Experiments/experiments/ict_out/
|
||||
exe/FaceLandmarkImg/Release/
|
||||
exe/FaceLandmarkVid/Release/
|
||||
exe/FaceLandmarkVidMulti/Release/
|
||||
exe/FeatureExtraction/Release/
|
||||
exe/Recording/Release/
|
||||
gui/OpenFaceDemo/obj/
|
||||
lib/3rdParty/dlib/Release/
|
||||
lib/local/CamCom/Release/
|
||||
lib/local/CppInerop/Release/
|
||||
lib/local/CppInerop/x64/
|
||||
lib/local/FaceAnalyser/Release/
|
||||
lib/local/LandmarkDetector/Release/
|
||||
|
|
76
.travis.yml
76
.travis.yml
|
@ -14,50 +14,57 @@ os:
|
|||
- linux
|
||||
|
||||
before_install:
|
||||
|
||||
# OpenCV dependencies and boost
|
||||
- if [ ${TRAVIS_OS_NAME} = linux ]; then
|
||||
sudo apt-get install git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev;
|
||||
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev checkinstall;
|
||||
sudo add-apt-repository -y ppa:boost-latest/ppa;
|
||||
sudo apt-get update;
|
||||
sudo apt-get install libboost1.55-all-dev;
|
||||
wget https://github.com/Itseez/opencv/archive/3.1.0.zip;
|
||||
sudo unzip 3.1.0.zip;
|
||||
cd opencv-3.1.0;
|
||||
sudo mkdir build;
|
||||
cd build;
|
||||
fi
|
||||
|
||||
# g++4.8.1
|
||||
- if [ "$CXX" == "g++" ]; then
|
||||
if [[ ${TRAVIS_OS_NAME} = linux ]]; then
|
||||
- if [ "$CXX" = "g++" ]; then
|
||||
if [ ${TRAVIS_OS_NAME} = linux ]; then
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test;
|
||||
sudo apt-get update -qq;
|
||||
sudo apt-get install -qq g++-4.8;
|
||||
export CXX="g++-4.8";
|
||||
sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D WITH_V4L=ON -D WITH_OPENCL=OFF -D INSTALL_C_EXAMPLES=OFF -D BUILD_EXAMPLES=OFF -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D INSTALL_PYTHON_EXAMPLES=OFF ..;
|
||||
fi
|
||||
fi
|
||||
|
||||
# clang 3.4
|
||||
- if [ "$CXX" == "clang++" ]; then
|
||||
if [[ ${TRAVIS_OS_NAME} = linux ]]; then
|
||||
sudo add-apt-repository -y ppa:h-rayflood/llvm;
|
||||
- if [ "$CXX" = "clang++" ]; then
|
||||
if [ ${TRAVIS_OS_NAME} = linux ]; then
|
||||
$CXX --version;
|
||||
sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers;
|
||||
sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D WITH_V4L=ON -D WITH_OPENCL=OFF -D INSTALL_C_EXAMPLES=OFF -D BUILD_EXAMPLES=OFF -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D INSTALL_PYTHON_EXAMPLES=OFF ..;
|
||||
fi
|
||||
fi
|
||||
|
||||
- if [[ ${TRAVIS_OS_NAME} = linux ]]; then sudo apt-get update -qq; fi
|
||||
|
||||
install:
|
||||
- if [ "$CXX" == "g++" ]; then if [[ ${TRAVIS_OS_NAME} = linux ]]; then sudo apt-get install -qq g++-4.8; fi fi
|
||||
- if [ "$CXX" == "g++" ]; then if [[ ${TRAVIS_OS_NAME} = linux ]]; then export CXX="g++-4.8"; fi fi
|
||||
- if [ "$CXX" == "clang++" ]; then if [[ ${TRAVIS_OS_NAME} = linux ]]; then sudo apt-get install -qq clang-3.4; fi fi
|
||||
- if [ "$CXX" == "clang++" ]; then if [[ ${TRAVIS_OS_NAME} = linux ]]; then export CXX="clang++-3.4"; fi fi
|
||||
- if [ ${TRAVIS_OS_NAME} = osx ]; then
|
||||
brew update;
|
||||
brew install tbb;
|
||||
wget https://github.com/Itseez/opencv/archive/3.1.0.zip;
|
||||
sudo unzip 3.1.0.zip;
|
||||
cd opencv-3.1.0;
|
||||
sudo mkdir build;
|
||||
cd build;
|
||||
sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D WITH_V4L=ON ..;
|
||||
fi
|
||||
|
||||
- if [[ ${TRAVIS_OS_NAME} = linux ]]; then sudo apt-get install git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} = linux ]]; then sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev checkinstall; fi
|
||||
|
||||
# Getting newest boost
|
||||
- if [[ ${TRAVIS_OS_NAME} = linux ]]; then sudo add-apt-repository -y ppa:boost-latest/ppa; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} = linux ]]; then sudo apt-get update; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} = linux ]]; then sudo apt-get install libboost1.55-all-dev; fi
|
||||
|
||||
- if [[ ${TRAVIS_OS_NAME} = osx ]]; then brew update; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} = osx ]]; then brew tap homebrew/science; fi
|
||||
- if [[ ${TRAVIS_OS_NAME} = osx ]]; then brew install tbb opencv3; fi
|
||||
|
||||
before_script:
|
||||
- git clone https://github.com/Itseez/opencv.git
|
||||
- cd opencv
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- make -j2
|
||||
- sudo make -j2 install
|
||||
- cd ../..
|
||||
|
||||
- sudo make -j4
|
||||
- sudo make install
|
||||
- cd ../..
|
||||
|
||||
script:
|
||||
- $CXX --version
|
||||
- mkdir build
|
||||
|
@ -68,4 +75,5 @@ script:
|
|||
- ../build/bin/FaceLandmarkImg -inroot ../videos -f Obama.jpg -outroot data -of obama.txt -op obama.3d -oi obama.bmp -multi_view 1 -wild -q
|
||||
- ../build/bin/FaceLandmarkVidMulti -inroot ../videos -f multi_face.avi -outroot output -ov multi_face.avi -q
|
||||
- ../build/bin/FeatureExtraction -f "../videos/1815_01_008_tony_blair.avi" -outroot output_features -ov blair.avi -of "1815_01_008_tony_blair.txt" -simalign aligned -ov feat_test.avi -hogalign hog_test.dat -q
|
||||
- ../build/bin/FaceLandmarkVid -inroot ../videos -f 1815_01_008_tony_blair.avi -f 0188_03_021_al_pacino.avi -f 0217_03_006_alanis_morissette.avi -outroot output_data -ov 1.avi -ov 2.avi -ov 3.avi -q
|
||||
- ../build/bin/FeatureExtraction -f "../videos/1815_01_008_tony_blair.avi" -outroot output_features -simsize 200 -simscale 0.5 -ov blair.avi -of "1815_01_008_tony_blair.txt" -simalign aligned -ov feat_test.avi -hogalign hog_test.dat -q
|
||||
- ../build/bin/FaceLandmarkVid -inroot ../videos -f 1815_01_008_tony_blair.avi -f 0188_03_021_al_pacino.avi -f 0217_03_006_alanis_morissette.avi -outroot output_data -ov 1.avi -ov 2.avi -ov 3.avi -q
|
||||
|
|
|
@ -5,7 +5,12 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/)
|
|||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
|
||||
|
||||
set(CMAKE_CONFIG_DIR etc/OpenFace)
|
||||
set(CONFIG_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_CONFIG_DIR}")
|
||||
add_definitions(-DCONFIG_DIR="${CONFIG_DIR}")
|
||||
|
||||
find_package( OpenCV REQUIRED )
|
||||
|
||||
MESSAGE("OpenCV information:")
|
||||
MESSAGE(" OpenCV_INCLUDE_DIRS: ${OpenCV_INCLUDE_DIRS}")
|
||||
MESSAGE(" OpenCV_LIBRARIES: ${OpenCV_LIBRARIES}")
|
||||
|
@ -33,6 +38,8 @@ foreach(file ${files})
|
|||
else(MSVC)
|
||||
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/bin/model)
|
||||
endif(MSVC)
|
||||
|
||||
install(FILES ${file} DESTINATION ${CMAKE_CONFIG_DIR}/model)
|
||||
endforeach()
|
||||
|
||||
# Move the hierarchical LandmarkDetector models
|
||||
|
@ -44,6 +51,8 @@ foreach(file ${files})
|
|||
else(MSVC)
|
||||
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/bin/model)
|
||||
endif(MSVC)
|
||||
|
||||
install(DIRECTORY ${file} DESTINATION ${CMAKE_CONFIG_DIR}/model)
|
||||
endforeach()
|
||||
|
||||
file(GLOB files "lib/local/LandmarkDetector/model/detection_validation/*.txt")
|
||||
|
@ -54,6 +63,8 @@ foreach(file ${files})
|
|||
else(MSVC)
|
||||
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/bin/model/detection_validation)
|
||||
endif(MSVC)
|
||||
|
||||
install(FILES ${file} DESTINATION ${CMAKE_CONFIG_DIR}/model/detection_validation)
|
||||
endforeach()
|
||||
|
||||
file(GLOB files "lib/local/LandmarkDetector/model/patch_experts/*.txt")
|
||||
|
@ -64,6 +75,8 @@ foreach(file ${files})
|
|||
else(MSVC)
|
||||
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/bin/model/patch_experts)
|
||||
endif(MSVC)
|
||||
|
||||
install(FILES ${file} DESTINATION ${CMAKE_CONFIG_DIR}/model/patch_experts)
|
||||
endforeach()
|
||||
|
||||
file(GLOB files "lib/local/LandmarkDetector/model/pdms/*.txt")
|
||||
|
@ -74,6 +87,8 @@ foreach(file ${files})
|
|||
else(MSVC)
|
||||
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/bin/model/pdms)
|
||||
endif(MSVC)
|
||||
|
||||
install(FILES ${file} DESTINATION ${CMAKE_CONFIG_DIR}/model/pdms)
|
||||
endforeach()
|
||||
|
||||
# Move OpenCV classifiers
|
||||
|
@ -85,6 +100,8 @@ foreach(file ${files})
|
|||
else(MSVC)
|
||||
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/bin/classifiers)
|
||||
endif(MSVC)
|
||||
|
||||
install(FILES ${file} DESTINATION ${CMAKE_CONFIG_DIR}/classifiers)
|
||||
endforeach()
|
||||
|
||||
# Move AU prediction modules
|
||||
|
@ -96,6 +113,8 @@ foreach(file ${files})
|
|||
else(MSVC)
|
||||
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/bin/AU_predictors)
|
||||
endif(MSVC)
|
||||
|
||||
install(FILES ${file} DESTINATION ${CMAKE_CONFIG_DIR}/AU_predictors)
|
||||
endforeach()
|
||||
|
||||
# Move AU prediction modules
|
||||
|
@ -107,6 +126,8 @@ foreach(file ${files})
|
|||
else(MSVC)
|
||||
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/bin/AU_predictors)
|
||||
endif(MSVC)
|
||||
|
||||
install(DIRECTORY ${file} DESTINATION ${CMAKE_CONFIG_DIR}/AU_predictors)
|
||||
endforeach()
|
||||
|
||||
# Move AU prediction modules
|
||||
|
@ -118,6 +139,8 @@ foreach(file ${files})
|
|||
else(MSVC)
|
||||
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/bin/AU_predictors)
|
||||
endif(MSVC)
|
||||
|
||||
install(DIRECTORY ${file} DESTINATION ${CMAKE_CONFIG_DIR}/AU_predictors)
|
||||
endforeach()
|
||||
|
||||
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
|
||||
|
|
|
@ -9,7 +9,8 @@ The code was written mainly by Tadas Baltrusaitis during his time at the Languag
|
|||
|
||||
Special thanks goes to Louis-Philippe Morency and his MultiComp Lab at Institute for Creative Technologies for help in writing and testing the code, and Erroll Wood for the gaze estimation work.
|
||||
|
||||
**For instructions of how to install/compile/use the project please see [wiki](https://github.com/TadasBaltrusaitis/OpenFace/wiki)**
|
||||
## WIKI
|
||||
**For instructions of how to install/compile/use the project please see [WIKI](https://github.com/TadasBaltrusaitis/OpenFace/wiki)**
|
||||
|
||||
More details about the project - http://www.cl.cam.ac.uk/research/rainbow/projects/openface/
|
||||
|
||||
|
|
|
@ -25,4 +25,5 @@ test_script:
|
|||
- cmd: if exist "../videos" (FaceLandmarkImg.exe -inroot ../videos -f obama.jpg -outroot out_data -of obama.pts -op obama.3d -oi obama.bmp -q) else (FaceLandmarkImg.exe -inroot ../../videos -f obama.jpg -outroot out_data -of obama.pts -op obama.3d -oi obama.bmp -q)
|
||||
- cmd: if exist "../videos" (FaceLandmarkVidMulti.exe -inroot ../videos -f multi_face.avi -ov multi_face.avi -q) else (FaceLandmarkVidMulti.exe -inroot ../../videos -f multi_face.avi -ov multi_face.avi -q)
|
||||
- cmd: if exist "../videos" (FeatureExtraction.exe -f "../videos/1815_01_008_tony_blair.avi" -outroot output_features -of "1815_01_008_tony_blair.txt" -simalign aligned -ov feat_track.avi -hogalign hog_test.dat -q) else (FeatureExtraction.exe -f "../../videos/1815_01_008_tony_blair.avi" -outroot output_features -of "1815_01_008_tony_blair.txt" -simalign aligned -ov feat_track.avi -hogalign hog_test.dat -q)
|
||||
- cmd: if exist "../videos" (FeatureExtraction.exe -f "../videos/1815_01_008_tony_blair.avi" -outroot output_features -of "1815_01_008_tony_blair.txt" -simalign aligned -simsize 200 -simscale 0.5 -ov feat_track.avi -hogalign hog_test.dat -q) else (FeatureExtraction.exe -f "../../videos/1815_01_008_tony_blair.avi" -outroot output_features -of "1815_01_008_tony_blair.txt" -simalign aligned -simsize 200 -simscale 0.5 -ov feat_track.avi -hogalign hog_test.dat -q)
|
||||
- cmd: if exist "../videos" (FaceLandmarkVid.exe -f "../videos/1815_01_008_tony_blair.avi" -ov track.avi -q) else (FaceLandmarkVid.exe -f "../../videos/1815_01_008_tony_blair.avi" -ov track.avi -q)
|
||||
|
|
|
@ -78,6 +78,10 @@
|
|||
#include <FaceAnalyser.h>
|
||||
#include <GazeEstimation.h>
|
||||
|
||||
#ifndef CONFIG_DIR
|
||||
#define CONFIG_DIR "~"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
vector<string> get_arguments(int argc, char **argv)
|
||||
|
@ -317,6 +321,10 @@ int main (int argc, char **argv)
|
|||
//Convert arguments to more convenient vector form
|
||||
vector<string> arguments = get_arguments(argc, argv);
|
||||
|
||||
// Search paths
|
||||
boost::filesystem::path config_path = boost::filesystem::path(CONFIG_DIR);
|
||||
boost::filesystem::path parent_path = boost::filesystem::path(arguments[0]).parent_path();
|
||||
|
||||
// Some initial parameters that can be overriden from command line
|
||||
vector<string> files, depth_files, output_images, output_landmark_locations, output_pose_locations;
|
||||
|
||||
|
@ -356,38 +364,44 @@ int main (int argc, char **argv)
|
|||
// Loading the AU prediction models
|
||||
string au_loc = "AU_predictors/AU_all_static.txt";
|
||||
|
||||
if (!boost::filesystem::exists(boost::filesystem::path(au_loc)))
|
||||
boost::filesystem::path au_loc_path = boost::filesystem::path(au_loc);
|
||||
if (boost::filesystem::exists(au_loc_path))
|
||||
{
|
||||
boost::filesystem::path loc = boost::filesystem::path(arguments[0]).parent_path() / au_loc;
|
||||
|
||||
if (boost::filesystem::exists(loc))
|
||||
{
|
||||
au_loc = loc.string();
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Can't find AU prediction files, exiting" << endl;
|
||||
return 1;
|
||||
}
|
||||
au_loc = au_loc_path.string();
|
||||
}
|
||||
else if (boost::filesystem::exists(parent_path/au_loc_path))
|
||||
{
|
||||
au_loc = (parent_path/au_loc_path).string();
|
||||
}
|
||||
else if (boost::filesystem::exists(config_path/au_loc_path))
|
||||
{
|
||||
au_loc = (config_path/au_loc_path).string();
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Can't find AU prediction files, exiting" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Used for image masking for AUs
|
||||
string tri_loc;
|
||||
if (boost::filesystem::exists(boost::filesystem::path("model/tris_68_full.txt")))
|
||||
boost::filesystem::path tri_loc_path = boost::filesystem::path("model/tris_68_full.txt");
|
||||
if (boost::filesystem::exists(tri_loc_path))
|
||||
{
|
||||
std::ifstream triangulation_file("model/tris_68_full.txt");
|
||||
tri_loc = "model/tris_68_full.txt";
|
||||
tri_loc = tri_loc_path.string();
|
||||
}
|
||||
else if (boost::filesystem::exists(parent_path/tri_loc_path))
|
||||
{
|
||||
tri_loc = (parent_path/tri_loc_path).string();
|
||||
}
|
||||
else if (boost::filesystem::exists(config_path/tri_loc_path))
|
||||
{
|
||||
tri_loc = (config_path/tri_loc_path).string();
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::filesystem::path loc = boost::filesystem::path(arguments[0]).parent_path() / "model/tris_68_full.txt";
|
||||
tri_loc = loc.string();
|
||||
|
||||
if (!exists(loc))
|
||||
{
|
||||
cout << "Can't find triangulation files, exiting" << endl;
|
||||
return 1;
|
||||
}
|
||||
cout << "Can't find triangulation files, exiting" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
FaceAnalysis::FaceAnalyser face_analyser(vector<cv::Vec3d>(), 0.7, 112, 112, au_loc, tri_loc);
|
||||
|
|
|
@ -14,3 +14,5 @@ target_link_libraries(FeatureExtraction FaceAnalyser)
|
|||
target_link_libraries(FeatureExtraction dlib)
|
||||
|
||||
target_link_libraries(FeatureExtraction ${OpenCV_LIBS} ${Boost_LIBRARIES} ${TBB_LIBRARIES})
|
||||
|
||||
install (TARGETS FeatureExtraction DESTINATION bin)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
|
||||
// all rights reserved.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
|
||||
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
|
||||
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
|
@ -15,13 +15,13 @@
|
|||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
|
||||
// of the Software may be covered by so-called “open source” software licenses (“Open Source
|
||||
// Components”), which means any software licenses approved as open source licenses by the
|
||||
// of the Software may be covered by so-called “open source” software licenses (“Open Source
|
||||
// Components”), which means any software licenses approved as open source licenses by the
|
||||
// Open Source Initiative or any substantially similar licenses, including without limitation any
|
||||
// license that, as a condition of distribution of the software licensed under such license,
|
||||
// requires that the distributor make the software available in source code format. Licensor shall
|
||||
// provide a list of Open Source Components for a particular version of the Software upon
|
||||
// Licensee’s request. Licensee will comply with the applicable terms of such licenses and to
|
||||
// Licensee’s request. Licensee will comply with the applicable terms of such licenses and to
|
||||
// the extent required by the licenses covering Open Source Components, the terms of such
|
||||
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
|
||||
// licenses applicable to Open Source Components prohibit any of the restrictions in this
|
||||
|
@ -38,20 +38,20 @@
|
|||
// reports and manuals, must cite at least one of the following works:
|
||||
//
|
||||
// OpenFace: an open source facial behavior analysis toolkit
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
|
||||
// in IEEE Winter Conference on Applications of Computer Vision, 2016
|
||||
//
|
||||
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
|
||||
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
|
||||
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
|
||||
// in IEEE International. Conference on Computer Vision (ICCV), 2015
|
||||
//
|
||||
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
|
||||
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
|
||||
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
|
||||
// in Facial Expression Recognition and Analysis Challenge,
|
||||
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
|
||||
//
|
||||
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
|
||||
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -81,6 +81,9 @@
|
|||
#include <FaceAnalyser.h>
|
||||
#include <GazeEstimation.h>
|
||||
|
||||
#ifndef CONFIG_DIR
|
||||
#define CONFIG_DIR "~"
|
||||
#endif
|
||||
|
||||
#define INFO_STREAM( stream ) \
|
||||
std::cout << stream << std::endl
|
||||
|
@ -239,6 +242,10 @@ int main (int argc, char **argv)
|
|||
|
||||
vector<string> arguments = get_arguments(argc, argv);
|
||||
|
||||
// Search paths
|
||||
boost::filesystem::path config_path = boost::filesystem::path(CONFIG_DIR);
|
||||
boost::filesystem::path parent_path = boost::filesystem::path(arguments[0]).parent_path();
|
||||
|
||||
// Some initial parameters that can be overriden from command line
|
||||
vector<string> input_files, depth_directories, output_files, tracked_videos_output;
|
||||
|
||||
|
@ -299,7 +306,7 @@ int main (int argc, char **argv)
|
|||
|
||||
double sim_scale = -1;
|
||||
int sim_size = 112;
|
||||
bool grayscale = false;
|
||||
bool grayscale = false;
|
||||
bool video_output = false;
|
||||
bool dynamic = true; // Indicates if a dynamic AU model should be used (dynamic is useful if the video is long enough to include neutral expressions)
|
||||
int num_hog_rows;
|
||||
|
@ -310,32 +317,33 @@ int main (int argc, char **argv)
|
|||
bool output_2D_landmarks = true;
|
||||
bool output_3D_landmarks = true;
|
||||
bool output_model_params = true;
|
||||
bool output_pose = true;
|
||||
bool output_pose = true;
|
||||
bool output_AUs = true;
|
||||
bool output_gaze = true;
|
||||
|
||||
get_output_feature_params(output_similarity_align, output_hog_align_files, sim_scale, sim_size, grayscale, verbose, dynamic,
|
||||
output_2D_landmarks, output_3D_landmarks, output_model_params, output_pose, output_AUs, output_gaze, arguments);
|
||||
|
||||
|
||||
// Used for image masking
|
||||
|
||||
string tri_loc;
|
||||
if(boost::filesystem::exists(path("model/tris_68_full.txt")))
|
||||
boost::filesystem::path tri_loc_path = boost::filesystem::path("model/tris_68_full.txt");
|
||||
if (boost::filesystem::exists(tri_loc_path))
|
||||
{
|
||||
tri_loc = "model/tris_68_full.txt";
|
||||
tri_loc = tri_loc_path.string();
|
||||
}
|
||||
else if (boost::filesystem::exists(parent_path/tri_loc_path))
|
||||
{
|
||||
tri_loc = (parent_path/tri_loc_path).string();
|
||||
}
|
||||
else if (boost::filesystem::exists(config_path/tri_loc_path))
|
||||
{
|
||||
tri_loc = (config_path/tri_loc_path).string();
|
||||
}
|
||||
else
|
||||
{
|
||||
path loc = path(arguments[0]).parent_path() / "model/tris_68_full.txt";
|
||||
tri_loc = loc.string();
|
||||
|
||||
if(!exists(loc))
|
||||
{
|
||||
cout << "Can't find triangulation files, exiting" << endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
cout << "Can't find triangulation files, exiting" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// If multiple video files are tracked, use this to indicate if we are done
|
||||
bool done = false;
|
||||
|
@ -354,24 +362,24 @@ int main (int argc, char **argv)
|
|||
au_loc_local = "AU_predictors/AU_all_static.txt";
|
||||
}
|
||||
|
||||
if(boost::filesystem::exists(path(au_loc_local)))
|
||||
boost::filesystem::path au_loc_path = boost::filesystem::path(au_loc_local);
|
||||
if (boost::filesystem::exists(au_loc_path))
|
||||
{
|
||||
au_loc = au_loc_local;
|
||||
au_loc = au_loc_path.string();
|
||||
}
|
||||
else if (boost::filesystem::exists(parent_path/au_loc_path))
|
||||
{
|
||||
au_loc = (parent_path/au_loc_path).string();
|
||||
}
|
||||
else if (boost::filesystem::exists(config_path/au_loc_path))
|
||||
{
|
||||
au_loc = (config_path/au_loc_path).string();
|
||||
}
|
||||
else
|
||||
{
|
||||
path loc = path(arguments[0]).parent_path() / au_loc_local;
|
||||
|
||||
if(exists(loc))
|
||||
{
|
||||
au_loc = loc.string();
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Can't find AU prediction files, exiting" << endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
cout << "Can't find AU prediction files, exiting" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Creating a face analyser that will be used for AU extraction
|
||||
|
||||
|
@ -597,13 +605,13 @@ int main (int argc, char **argv)
|
|||
}
|
||||
|
||||
|
||||
if(hog_output_file.is_open())
|
||||
if (hog_output_file.is_open())
|
||||
{
|
||||
output_HOG_frame(&hog_output_file, detection_success, hog_descriptor, num_hog_rows, num_hog_cols);
|
||||
}
|
||||
|
||||
// Write the similarity normalised output
|
||||
if(!output_similarity_align.empty())
|
||||
if (!output_similarity_align.empty())
|
||||
{
|
||||
|
||||
if (sim_warped_img.channels() == 3 && grayscale)
|
||||
|
@ -612,18 +620,18 @@ int main (int argc, char **argv)
|
|||
}
|
||||
|
||||
char name[100];
|
||||
|
||||
|
||||
// Filename is based on frame number
|
||||
std::sprintf(name, "frame_det_%06d.bmp", frame_count + 1);
|
||||
|
||||
// Construct the output filename
|
||||
boost::filesystem::path slash("/");
|
||||
|
||||
|
||||
std::string preferredSlash = slash.make_preferred().string();
|
||||
|
||||
|
||||
string out_file = output_similarity_align[f_n] + preferredSlash + string(name);
|
||||
bool write_success = imwrite(out_file, sim_warped_img);
|
||||
|
||||
|
||||
if (!write_success)
|
||||
{
|
||||
cout << "Could not output similarity aligned image image" << endl;
|
||||
|
@ -662,20 +670,24 @@ int main (int argc, char **argv)
|
|||
captured_image = cv::Mat();
|
||||
}
|
||||
}
|
||||
// detect key presses
|
||||
char character_press = cv::waitKey(1);
|
||||
|
||||
// restart the tracker
|
||||
if(character_press == 'r')
|
||||
if (!det_parameters.quiet_mode)
|
||||
{
|
||||
face_model.Reset();
|
||||
// detect key presses
|
||||
char character_press = cv::waitKey(1);
|
||||
|
||||
// restart the tracker
|
||||
if(character_press == 'r')
|
||||
{
|
||||
face_model.Reset();
|
||||
}
|
||||
// quit the application
|
||||
else if(character_press=='q')
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
// quit the application
|
||||
else if(character_press=='q')
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
// Update the frame count
|
||||
frame_count++;
|
||||
|
||||
|
@ -692,7 +704,7 @@ int main (int argc, char **argv)
|
|||
|
||||
output_file.close();
|
||||
|
||||
if(output_files.size() > 0 && output_AUs)
|
||||
if (output_files.size() > 0 && output_AUs)
|
||||
{
|
||||
cout << "Postprocessing the Action Unit predictions" << endl;
|
||||
face_analyser.PostprocessOutputFile(output_files[f_n], dynamic);
|
||||
|
@ -1113,6 +1125,7 @@ void get_output_feature_params(vector<string> &output_similarity_aligned, vector
|
|||
|
||||
}
|
||||
|
||||
|
||||
// Can process images via directories creating a separate output file per directory
|
||||
void get_image_input_output_params_feats(vector<vector<string> > &input_image_files, bool& as_video, vector<string> &arguments)
|
||||
{
|
||||
|
|
BIN
imgs/frame_det_000000_112x112_0.7.bmp
Normal file
BIN
imgs/frame_det_000000_112x112_0.7.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
BIN
imgs/frame_det_000001_112x112_0.5.bmp
Normal file
BIN
imgs/frame_det_000001_112x112_0.5.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
BIN
imgs/frame_det_000001_200x200_0.7.bmp
Normal file
BIN
imgs/frame_det_000001_200x200_0.7.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 117 KiB |
86
install.sh
Executable file
86
install.sh
Executable file
|
@ -0,0 +1,86 @@
|
|||
#!/bin/bash
|
||||
#==============================================================================
|
||||
# Title: install.sh
|
||||
# Description: Install everything necessary for OpenFace to compile.
|
||||
# Author: Daniyal Shahrokhian <daniyal@kth.se>
|
||||
# Date: 20170310
|
||||
# Version : 1.0
|
||||
# Usage: bash install.sh <directory in which you want the project to be installed>
|
||||
# NOTES: There are certain steps to be taken in the system before installing
|
||||
# via this script (refer to README): Run
|
||||
# `sudo gedit /etc/apt/sources.list` and change the line
|
||||
# `deb http://us.archive.ubuntu.com/ubuntu/ xenial main restricted` to
|
||||
# `deb http://us.archive.ubuntu.com/ubuntu/ xenial main universe`
|
||||
#==============================================================================
|
||||
|
||||
# Exit script if any command fails
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [ $# -ne 1 ]
|
||||
then
|
||||
echo "Usage: install.sh <directory in which you want the project to be installed>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DIRECTORY="$1"
|
||||
cd "$DIRECTORY"
|
||||
echo "Installation under ${DIRECTORY}"
|
||||
|
||||
# Essential Dependencies
|
||||
echo "Installing Essential dependencies..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential
|
||||
sudo apt-get install llvm
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install clang-3.7 libc++-dev libc++abi-dev
|
||||
sudo apt-get install cmake
|
||||
sudo apt-get install libopenblas-dev liblapack-dev
|
||||
sudo apt-get install git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
|
||||
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev checkinstall
|
||||
echo "Essential dependencies installed."
|
||||
|
||||
# OpenCV Dependency
|
||||
echo "Downloading OpenCV..."
|
||||
if [ -d "opencv-3.1.0" ]; then
|
||||
sudo rm -r "opencv-3.1.0"
|
||||
fi
|
||||
|
||||
wget https://github.com/Itseez/opencv/archive/3.1.0.zip
|
||||
unzip 3.1.0.zip
|
||||
rm 3.1.0.zip
|
||||
cd opencv-3.1.0
|
||||
mkdir build
|
||||
cd build
|
||||
echo "Installing OpenCV..."
|
||||
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D BUILD_SHARED_LIBS=OFF ..
|
||||
make -j4
|
||||
sudo make install
|
||||
cd "../.."
|
||||
echo "OpenCV installed."
|
||||
|
||||
# Boost C++ Dependency
|
||||
echo "Installing Boost..."
|
||||
sudo apt-get install libboost-all-dev
|
||||
echo "Boost installed."
|
||||
|
||||
# OpenFace installation
|
||||
echo "Downloading OpenFace..."
|
||||
if [ -d "OpenFace" ]; then
|
||||
sudo rm -r "OpenFace"
|
||||
fi
|
||||
|
||||
git clone https://github.com/TadasBaltrusaitis/OpenFace.git
|
||||
cd OpenFace
|
||||
mkdir build
|
||||
cd build
|
||||
echo "Installing OpenFace..."
|
||||
cmake -D CMAKE_BUILD_TYPE=RELEASE ..
|
||||
make
|
||||
echo "OpenFace installed."
|
||||
|
||||
# Installation test
|
||||
echo "Testing installation..."
|
||||
./bin/FaceLandmarkVid -f "../videos/changeLighting.wmv"
|
||||
echo "Installation tested."
|
|
@ -29,5 +29,5 @@ include_directories(../LandmarkDetector/include)
|
|||
|
||||
add_library( FaceAnalyser ${SOURCE} ${HEADERS})
|
||||
|
||||
install (TARGETS FaceAnalyser DESTINATION bin)
|
||||
install (FILES ${HEADERS} DESTINATION include)
|
||||
install (TARGETS FaceAnalyser DESTINATION lib)
|
||||
install (FILES ${HEADERS} DESTINATION include/OpenFace)
|
||||
|
|
|
@ -221,19 +221,19 @@ namespace FaceAnalysis
|
|||
destination_landmarks.col(1) = destination_landmarks.col(1) + warp_matrix(1,2);
|
||||
|
||||
// Move the eyebrows up to include more of upper face
|
||||
destination_landmarks.at<double>(0,1) -= 30;
|
||||
destination_landmarks.at<double>(16,1) -= 30;
|
||||
destination_landmarks.at<double>(0,1) -= (30/0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(16,1) -= (30 / 0.7)*sim_scale;
|
||||
|
||||
destination_landmarks.at<double>(17,1) -= 30;
|
||||
destination_landmarks.at<double>(18,1) -= 30;
|
||||
destination_landmarks.at<double>(19,1) -= 30;
|
||||
destination_landmarks.at<double>(20,1) -= 30;
|
||||
destination_landmarks.at<double>(21,1) -= 30;
|
||||
destination_landmarks.at<double>(22,1) -= 30;
|
||||
destination_landmarks.at<double>(23,1) -= 30;
|
||||
destination_landmarks.at<double>(24,1) -= 30;
|
||||
destination_landmarks.at<double>(25,1) -= 30;
|
||||
destination_landmarks.at<double>(26,1) -= 30;
|
||||
destination_landmarks.at<double>(17,1) -= (30 / 0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(18,1) -= (30 / 0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(19,1) -= (30 / 0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(20,1) -= (30 / 0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(21,1) -= (30 / 0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(22,1) -= (30 / 0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(23,1) -= (30 / 0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(24,1) -= (30 / 0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(25,1) -= (30 / 0.7)*sim_scale;
|
||||
destination_landmarks.at<double>(26,1) -= (30 / 0.7)*sim_scale;
|
||||
|
||||
destination_landmarks = cv::Mat(destination_landmarks.t()).reshape(1, 1).t();
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ SET(HEADERS
|
|||
include_directories(./include)
|
||||
include_directories(${LandmarkDetector_SOURCE_DIR}/include)
|
||||
|
||||
add_library( LandmarkDetector ${SOURCE} ${HEADERS})
|
||||
add_library( LandmarkDetector ${SOURCE} ${HEADERS} )
|
||||
|
||||
install (TARGETS LandmarkDetector DESTINATION bin)
|
||||
install (FILES ${HEADERS} DESTINATION include)
|
||||
install (TARGETS LandmarkDetector DESTINATION lib)
|
||||
install (FILES ${HEADERS} DESTINATION include/OpenFace)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
|
||||
// all rights reserved.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
|
||||
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
|
||||
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
|
@ -15,13 +15,13 @@
|
|||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
|
||||
// of the Software may be covered by so-called “open source” software licenses (“Open Source
|
||||
// Components”), which means any software licenses approved as open source licenses by the
|
||||
// of the Software may be covered by so-called “open source” software licenses (“Open Source
|
||||
// Components”), which means any software licenses approved as open source licenses by the
|
||||
// Open Source Initiative or any substantially similar licenses, including without limitation any
|
||||
// license that, as a condition of distribution of the software licensed under such license,
|
||||
// requires that the distributor make the software available in source code format. Licensor shall
|
||||
// provide a list of Open Source Components for a particular version of the Software upon
|
||||
// Licensee’s request. Licensee will comply with the applicable terms of such licenses and to
|
||||
// Licensee’s request. Licensee will comply with the applicable terms of such licenses and to
|
||||
// the extent required by the licenses covering Open Source Components, the terms of such
|
||||
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
|
||||
// licenses applicable to Open Source Components prohibit any of the restrictions in this
|
||||
|
@ -38,20 +38,20 @@
|
|||
// reports and manuals, must cite at least one of the following works:
|
||||
//
|
||||
// OpenFace: an open source facial behavior analysis toolkit
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
|
||||
// in IEEE Winter Conference on Applications of Computer Vision, 2016
|
||||
//
|
||||
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
|
||||
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
|
||||
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
|
||||
// in IEEE International. Conference on Computer Vision (ICCV), 2015
|
||||
//
|
||||
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
|
||||
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
|
||||
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
|
||||
// in Facial Expression Recognition and Analysis Challenge,
|
||||
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
|
||||
//
|
||||
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
|
||||
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
double detection_certainty;
|
||||
|
||||
// Indicator if eye model is there for eye detection
|
||||
bool eye_model = false;
|
||||
bool eye_model;
|
||||
|
||||
// the triangulation per each view (for drawing purposes only)
|
||||
vector<cv::Mat_<int> > triangulations;
|
||||
|
|
|
@ -408,7 +408,7 @@ bool LandmarkDetector::DetectLandmarksInVideo(const cv::Mat_<uchar> &grayscale_i
|
|||
|
||||
bool LandmarkDetector::DetectLandmarksInVideo(const cv::Mat_<uchar> &grayscale_image, const cv::Rect_<double> bounding_box, CLNF& clnf_model, FaceModelParameters& params)
|
||||
{
|
||||
return DetectLandmarksInVideo(grayscale_image, cv::Mat_<float>(), clnf_model, params);
|
||||
return DetectLandmarksInVideo(grayscale_image, cv::Mat_<float>(), bounding_box, clnf_model, params);
|
||||
}
|
||||
|
||||
//================================================================================================================
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
|
||||
// all rights reserved.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
|
||||
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
|
||||
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
|
||||
|
@ -15,13 +15,13 @@
|
|||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
|
||||
// of the Software may be covered by so-called “open source” software licenses (“Open Source
|
||||
// Components”), which means any software licenses approved as open source licenses by the
|
||||
// of the Software may be covered by so-called “open source” software licenses (“Open Source
|
||||
// Components”), which means any software licenses approved as open source licenses by the
|
||||
// Open Source Initiative or any substantially similar licenses, including without limitation any
|
||||
// license that, as a condition of distribution of the software licensed under such license,
|
||||
// requires that the distributor make the software available in source code format. Licensor shall
|
||||
// provide a list of Open Source Components for a particular version of the Software upon
|
||||
// Licensee’s request. Licensee will comply with the applicable terms of such licenses and to
|
||||
// Licensee’s request. Licensee will comply with the applicable terms of such licenses and to
|
||||
// the extent required by the licenses covering Open Source Components, the terms of such
|
||||
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
|
||||
// licenses applicable to Open Source Components prohibit any of the restrictions in this
|
||||
|
@ -38,20 +38,20 @@
|
|||
// reports and manuals, must cite at least one of the following works:
|
||||
//
|
||||
// OpenFace: an open source facial behavior analysis toolkit
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
|
||||
// in IEEE Winter Conference on Applications of Computer Vision, 2016
|
||||
//
|
||||
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
|
||||
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
|
||||
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
|
||||
// in IEEE International. Conference on Computer Vision (ICCV), 2015
|
||||
//
|
||||
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
|
||||
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
|
||||
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
|
||||
// in Facial Expression Recognition and Analysis Challenge,
|
||||
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
|
||||
//
|
||||
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
|
||||
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
|
||||
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -378,6 +378,9 @@ void CLNF::Read(string main_location)
|
|||
detect_Z_max = -1;
|
||||
detect_ROI = cv::Rect_<double>(0, 0, 1, 1);
|
||||
|
||||
// Assume no eye model, unless read-in
|
||||
eye_model = false;
|
||||
|
||||
// The main file contains the references to other files
|
||||
while (!locations.eof())
|
||||
{
|
||||
|
@ -399,6 +402,7 @@ void CLNF::Read(string main_location)
|
|||
location = location.substr(0, location.size()-1);
|
||||
}
|
||||
|
||||
|
||||
// append to root
|
||||
location = (root / location).string();
|
||||
if (module.compare("LandmarkDetector") == 0)
|
||||
|
|
|
@ -67,6 +67,11 @@
|
|||
// System includes
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
#ifndef CONFIG_DIR
|
||||
#define CONFIG_DIR "~"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -200,15 +205,25 @@ FaceModelParameters::FaceModelParameters(vector<string> &arguments)
|
|||
}
|
||||
|
||||
// Make sure model_location is valid
|
||||
if (!boost::filesystem::exists(boost::filesystem::path(model_location)))
|
||||
// First check working directory, then the executable's directory, then the config path set by the build process.
|
||||
boost::filesystem::path config_path = boost::filesystem::path(CONFIG_DIR);
|
||||
boost::filesystem::path model_path = boost::filesystem::path(model_location);
|
||||
if (boost::filesystem::exists(model_path))
|
||||
{
|
||||
model_location = (root / model_location).string();
|
||||
if (!boost::filesystem::exists(boost::filesystem::path(model_location)))
|
||||
{
|
||||
std::cout << "Could not find the landmark detection model to load" << std::endl;
|
||||
}
|
||||
model_location = model_path.string();
|
||||
}
|
||||
else if (boost::filesystem::exists(root/model_path))
|
||||
{
|
||||
model_location = (root/model_path).string();
|
||||
}
|
||||
else if (boost::filesystem::exists(config_path/model_path))
|
||||
{
|
||||
model_location = (config_path/model_path).string();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Could not find the landmark detection model to load" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FaceModelParameters::init()
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
|
||||
% Function ParseSEMAINEAnnotations is intended to demonstrate example usage
|
||||
% of SEMAINE Action Unit annotations made with ELAN annotation toolbox.
|
||||
% This function loads the XML structure from an ELAN annotation file with
|
||||
% ".eaf" extension, parses it and returns a numerical matrix called
|
||||
% "activations" of size NUMBER OF FRAMES X NUMBER OF ACTION UNITS. The
|
||||
% matrix holds binary activation status for each frame / AU combination.
|
||||
% The matrix also has a row header showing which AU corresponds to which
|
||||
% row as well as a column header displaying original frame indexes.
|
||||
|
||||
% The function takes 1 compulsory and 2 optional arguments:
|
||||
|
||||
% - "filepath" (compulsory) - complete path to an annotation file to parse.
|
||||
% For example, "/matlab/annotation.eaf" or "C:\matlab\annotation.eaf" on
|
||||
% Windows.
|
||||
|
||||
% - "startFrame" (optional) - ignore all annotations before "startFrame".
|
||||
% Default is 1.
|
||||
|
||||
% - "endFrame" (optional) - ignore all annotations after "endFrame".
|
||||
% Default is the last frame of a video.
|
||||
|
||||
% The function requires XML IO Toolbox
|
||||
% (http://www.mathworks.com/matlabcentral/fileexchange/12907-xml-io-tools)
|
||||
% to run properly (supplied).
|
||||
|
||||
function activations = ParseSEMAINEAnnotations (filepath, startFrame, endFrame)
|
||||
activations = [];
|
||||
|
||||
% Framerate value used to convert ELAN millisecond time slots to more
|
||||
% usual frames. 50 is a valid framerate for all SEMAINE videos.
|
||||
framerate = 50;
|
||||
|
||||
% A fixed set of 6 Action Units selected for the challenge from the
|
||||
% SEMAINE annotations
|
||||
aus = [2 12 17 25 28 45];
|
||||
|
||||
% Total number of AUs.
|
||||
naus = length(aus);
|
||||
|
||||
% Load XML structure from the file, return in case of a problem.
|
||||
[success, XML] = OpenXML(filepath);
|
||||
if ~success
|
||||
return
|
||||
end
|
||||
|
||||
% Parse annotation time slots
|
||||
tslots = ParseTimeSlots(XML);
|
||||
|
||||
% Init start and end frames with default values
|
||||
if nargin < 2
|
||||
startFrame = 1;
|
||||
end
|
||||
|
||||
if nargin < 3
|
||||
% Get total number of time slots
|
||||
ntslots = length(tslots);
|
||||
% Get last slot ID
|
||||
lastID = strcat('ts', num2str(ntslots));
|
||||
% Get last time slot value in ms
|
||||
lastValue = tslots(lastID);
|
||||
% Convert last time slot value in ms to frames
|
||||
endFrame = floor((lastValue / 1000) * framerate);
|
||||
end
|
||||
|
||||
% Get total number of tiers. There are 65 of them, 1 for speech, 32 for
|
||||
% activations (1 per AU) and 32 for intensities. We are going to ignore
|
||||
% intensity tiers.
|
||||
ntiers = length(XML.TIER);
|
||||
|
||||
% Compose vector of frame indexes to extract annotations from
|
||||
frames = (startFrame:endFrame);
|
||||
|
||||
% Preallocate activations matrix
|
||||
activations = zeros(length(frames), naus);
|
||||
|
||||
indx = 1;
|
||||
% Go through all tiers skipping the first one (speech) as well as every
|
||||
% intensity tier. A single activation tier is processed at every
|
||||
% iteration.
|
||||
for k = 2:2:ntiers
|
||||
tier = XML.TIER(k);
|
||||
% Only extract annotations of selected AUs, skip the rest
|
||||
au = strcat('AU', num2str(aus(indx)));
|
||||
if strcmp(au, tier.ATTRIBUTE.TIER_ID)
|
||||
% Read all activation periods from the current tier
|
||||
activationTier = ParseActivationTier(tier, tslots);
|
||||
% Convert of all activation periods into frame level numerical
|
||||
% representation
|
||||
activations(:, indx) = ParseOccurrences(activationTier, frames, framerate);
|
||||
|
||||
indx = indx + 1;
|
||||
end
|
||||
|
||||
if indx > naus
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
activations = [frames' activations];
|
||||
activations = [[0 aus]; activations];
|
||||
end
|
||||
|
||||
function occurrences = ParseOccurrences (activations, frames, framerate)
|
||||
% Preallocate activations vector
|
||||
occurrences = zeros(length(frames), 1);
|
||||
% Go through all activation periods, convert ms into frames and init
|
||||
% corresponding values of activations vector with 1 leaving the rest be 0
|
||||
for i = 1:length(activations)
|
||||
% Convert ms into frames
|
||||
sframe = floor((activations(i).start / 1000) * framerate);
|
||||
eframe = floor((activations(i).end / 1000) * framerate);
|
||||
|
||||
% Determine indexes of frames vector corresponding to the above
|
||||
% time frame
|
||||
sindx = find(frames == sframe);
|
||||
eindx = find(frames == eframe);
|
||||
|
||||
% Mark active set of frames with 1
|
||||
occurrences(sindx:eindx) = 1;
|
||||
end
|
||||
end
|
||||
|
||||
function activationTier = ParseActivationTier (tier, tslots)
|
||||
% Get total number of activation periods
|
||||
nactivations = length(tier.ANNOTATION);
|
||||
% Preallocate activation tier structure holding start and end time
|
||||
% stamps of all activation periods for the given AU
|
||||
activationTier = repmat(struct('start', 0, 'end', 0), nactivations, 1);
|
||||
% Go through all activation periods and init activation tier
|
||||
% structure array
|
||||
for i = 1:nactivations
|
||||
% Read start time slot ID of the current activation period
|
||||
t = tier.ANNOTATION(i).ALIGNABLE_ANNOTATION.ATTRIBUTE.TIME_SLOT_REF1;
|
||||
% Read time in ms corresponding to the time slot ID
|
||||
activationTier(i).start = tslots(t);
|
||||
|
||||
% Read end time slot ID of the current activation period
|
||||
t = tier.ANNOTATION(i).ALIGNABLE_ANNOTATION.ATTRIBUTE.TIME_SLOT_REF2;
|
||||
% Read time in ms corresponding to the time slot ID
|
||||
activationTier(i).end = tslots(t);
|
||||
end
|
||||
end
|
||||
|
||||
function tslots = ParseTimeSlots (xmlObject)
|
||||
% Get total number of time slots
|
||||
nslots = length(xmlObject.TIME_ORDER.TIME_SLOT);
|
||||
% Preallocate cell arrays of time slot IDs and values
|
||||
tids = cell(nslots, 1);
|
||||
tvalues = zeros(nslots, 1);
|
||||
% Read all time slot IDs and numerical values (in ms)
|
||||
for i = 1:nslots
|
||||
tids{i} = xmlObject.TIME_ORDER.TIME_SLOT(i).ATTRIBUTE.TIME_SLOT_ID;
|
||||
tvalues(i) = xmlObject.TIME_ORDER.TIME_SLOT(i).ATTRIBUTE.TIME_VALUE;
|
||||
end
|
||||
% Map time slot IDs and values together so that values are accessible
|
||||
% by their IDs
|
||||
tslots = containers.Map(tids, tvalues);
|
||||
end
|
||||
|
||||
function [success, xmlObject] = OpenXML (xmlPath)
|
||||
fprintf(' *** Attempting to load \"%s\" ... ', xmlPath);
|
||||
xmlObject = [];
|
||||
success = false;
|
||||
% Check if the specified file exists and return error otherwise
|
||||
if exist(xmlPath, 'file')
|
||||
% Load XML structure
|
||||
xmlObject = xml_read(xmlPath);
|
||||
% Check if XML object loaded correctly, return error otherwise
|
||||
if isempty(xmlObject)
|
||||
fprintf(' ERROR - unable to read xml tree *** \n');
|
||||
return
|
||||
else
|
||||
success = true;
|
||||
end
|
||||
else
|
||||
fprintf(' ERROR - specified path does not exist *** \n');
|
||||
return
|
||||
end
|
||||
fprintf(' Done *** \n');
|
||||
end
|
|
@ -26,14 +26,9 @@ function [ labels, valid_ids, vid_ids ] = extract_SEMAINE_labels( SEMAINE_dir,
|
|||
|
||||
xml_file = [SEMAINE_dir, recs{i}, '\' file.name];
|
||||
[root_xml, name_xml, ~] = fileparts(xml_file);
|
||||
m_file = [root_xml, name_xml, '.mat'];
|
||||
|
||||
if(~exist(m_file, 'file'))
|
||||
activations = ParseSEMAINEAnnotations([SEMAINE_dir, recs{i}, '\' file.name]);
|
||||
save(m_file, 'activations');
|
||||
else
|
||||
load(m_file);
|
||||
end
|
||||
activations = ParseSEMAINEAnnotations([SEMAINE_dir, recs{i}, '/' file.name]);
|
||||
|
||||
if(size(activations,1) < vid_ids(i,2))
|
||||
vid_ids(i,2) = size(activations,1);
|
||||
if(vid_ids(i,2) > 2999)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
if(exist('D:\Datasets\fera/au_training', 'file'))
|
||||
FERA2011_dir = 'D:\Datasets\fera/au_training/';
|
||||
hog_data_dir = 'D:\Datasets\face_datasets\hog_aligned_rigid/';
|
||||
elseif(exist('/multicomp/datasets/fera2011/', 'file'))
|
||||
FERA2011_dir = '/multicomp/datasets/fera2011/au_training/';
|
||||
else
|
||||
fprintf('FERA2011 location not found (or not defined)\n');
|
||||
end
|
||||
|
|
|
@ -10,8 +10,10 @@ elseif(exist('D:\Datasets\FERA_2015\semaine\SEMAINE-Sessions/', 'file'))
|
|||
SEMAINE_dir = 'D:\Datasets\FERA_2015\semaine\SEMAINE-Sessions/';
|
||||
elseif(exist('D:/fera_2015/semaine/SEMAINE-Sessions/', 'file'))
|
||||
SEMAINE_dir = 'D:/fera_2015/semaine/SEMAINE-Sessions/';
|
||||
elseif(exist('/multicomp/datasets/face_datasets/FERA_2015/Semaine/SEMAINE-Sessions/', 'file'))
|
||||
SEMAINE_dir = '/multicomp/datasets/face_datasets/FERA_2015/Semaine/SEMAINE-Sessions/';
|
||||
else
|
||||
fprintf('DISFA location not found (or not defined)\n');
|
||||
fprintf('SEMAINE location not found (or not defined)\n');
|
||||
end
|
||||
|
||||
if(exist('SEMAINE_dir', 'var'))
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
function y = base64decode(x, outfname, alg)
|
||||
%BASE64DECODE Perform base64 decoding on a string.
|
||||
%
|
||||
% INPUT:
|
||||
% x - block of data to be decoded. Can be a string or a numeric
|
||||
% vector containing integers in the range 0-255. Any character
|
||||
% not part of the 65-character base64 subset set is silently
|
||||
% ignored. Characters occuring after a '=' padding character are
|
||||
% never decoded. If the length of the string to decode (after
|
||||
% ignoring non-base64 chars) is not a multiple of 4, then a
|
||||
% warning is generated.
|
||||
%
|
||||
% outfname - if provided the binary date from decoded string will be
|
||||
% saved into a file. Since Base64 coding is often used to embbed
|
||||
% binary data in xml files, this option can be used to extract and
|
||||
% save them.
|
||||
%
|
||||
% alg - Algorithm to use: can take values 'java' or 'matlab'. Optional
|
||||
% variable defaulting to 'java' which is a little faster. If
|
||||
% 'java' is chosen than core of the code is performed by a call to
|
||||
% a java library. Optionally all operations can be performed using
|
||||
% matleb code.
|
||||
%
|
||||
% OUTPUT:
|
||||
% y - array of binary data returned as uint8
|
||||
%
|
||||
% This function is used to decode strings from the Base64 encoding specified
|
||||
% in RFC 2045 - MIME (Multipurpose Internet Mail Extensions). The Base64
|
||||
% encoding is designed to represent arbitrary sequences of octets in a form
|
||||
% that need not be humanly readable. A 65-character subset ([A-Za-z0-9+/=])
|
||||
% of US-ASCII is used, enabling 6 bits to be represented per printable
|
||||
% character.
|
||||
%
|
||||
% See also BASE64ENCODE.
|
||||
%
|
||||
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
|
||||
%
|
||||
% Matlab version based on 2004 code by Peter J. Acklam
|
||||
% E-mail: pjacklam@online.no
|
||||
% URL: http://home.online.no/~pjacklam
|
||||
% http://home.online.no/~pjacklam/matlab/software/util/datautil/base64encode.m
|
||||
|
||||
if nargin<3, alg='java'; end
|
||||
if nargin<2, outfname=''; end
|
||||
|
||||
%% if x happen to be a filename than read the file
|
||||
if (numel(x)<256)
|
||||
if (exist(x, 'file')==2)
|
||||
fid = fopen(x,'rb');
|
||||
x = fread(fid, 'uint8');
|
||||
fclose(fid);
|
||||
end
|
||||
end
|
||||
x = uint8(x(:)); % unify format
|
||||
|
||||
%% Perform conversion
|
||||
switch (alg)
|
||||
case 'java'
|
||||
base64 = org.apache.commons.codec.binary.Base64;
|
||||
y = base64.decode(x);
|
||||
y = mod(int16(y),256); % convert from int8 to uint8
|
||||
case 'matlab'
|
||||
%% Perform the mapping
|
||||
% A-Z -> 0 - 25
|
||||
% a-z -> 26 - 51
|
||||
% 0-9 -> 52 - 61
|
||||
% + - -> 62 '-' is URL_SAFE alternative
|
||||
% / _ -> 63 '_' is URL_SAFE alternative
|
||||
map = uint8(zeros(1,256)+65);
|
||||
map(uint8(['A':'Z', 'a':'z', '0':'9', '+/=']))= 0:64;
|
||||
map(uint8('-_'))= 62:63; % URL_SAFE alternatives
|
||||
x = map(x); % mapping
|
||||
|
||||
x(x>64)=[]; % remove non-base64 chars
|
||||
if rem(numel(x), 4)
|
||||
warning('Length of base64 data not a multiple of 4; padding input.');
|
||||
end
|
||||
x(x==64)=[]; % remove padding characters
|
||||
|
||||
%% add padding and reshape
|
||||
nebytes = length(x); % number of encoded bytes
|
||||
nchunks = ceil(nebytes/4); % number of chunks/groups
|
||||
if rem(nebytes, 4)>0
|
||||
x(end+1 : 4*nchunks) = 0; % add padding
|
||||
end
|
||||
x = reshape(uint8(x), 4, nchunks);
|
||||
y = repmat(uint8(0), 3, nchunks); % for the decoded data
|
||||
|
||||
%% Rearrange every 4 bytes into 3 bytes
|
||||
% 00aaaaaa 00bbbbbb 00cccccc 00dddddd
|
||||
% to form
|
||||
% aaaaaabb bbbbcccc ccdddddd
|
||||
y(1,:) = bitshift(x(1,:), 2); % 6 highest bits of y(1,:)
|
||||
y(1,:) = bitor(y(1,:), bitshift(x(2,:), -4)); % 2 lowest bits of y(1,:)
|
||||
y(2,:) = bitshift(x(2,:), 4); % 4 highest bits of y(2,:)
|
||||
y(2,:) = bitor(y(2,:), bitshift(x(3,:), -2)); % 4 lowest bits of y(2,:)
|
||||
y(3,:) = bitshift(x(3,:), 6); % 2 highest bits of y(3,:)
|
||||
y(3,:) = bitor(y(3,:), x(4,:)); % 6 lowest bits of y(3,:)
|
||||
|
||||
%% remove extra padding
|
||||
switch rem(nebytes, 4)
|
||||
case 2
|
||||
y = y(1:end-2);
|
||||
case 3
|
||||
y = y(1:end-1);
|
||||
end
|
||||
end
|
||||
|
||||
%% reshape to a row vector and make it a character array
|
||||
y = uint8(reshape(y, 1, numel(y)));
|
||||
|
||||
%% save to file if needed
|
||||
if ~isempty(outfname)
|
||||
fid = fopen(outfname,'wb');
|
||||
fwrite(fid, y, 'uint8');
|
||||
fclose(fid);
|
||||
end
|
|
@ -0,0 +1,138 @@
|
|||
function y = base64encode(x, alg, isChunked, url_safe)
|
||||
%BASE64ENCODE Perform base64 encoding on a string.
|
||||
% INPUT:
|
||||
% x - block of data to be encoded. Can be a string or a numeric
|
||||
% vector containing integers in the range 0-255.
|
||||
% alg - Algorithm to use: can take values 'java' or 'matlab'. Optional
|
||||
% variable defaulting to 'java' which is a little faster. If
|
||||
% 'java' is chosen than core of the code is performed by a call to
|
||||
% a java library. Optionally all operations can be performed using
|
||||
% matleb code.
|
||||
% isChunked - encode output into 76 character blocks. The returned
|
||||
% encoded string is broken into lines of no more than
|
||||
% 76 characters each, and each line will end with EOL. Notice that
|
||||
% if resulting string is saved as part of an xml file, those EOL's
|
||||
% are often stripped by xmlwrite funtrion prior to saving.
|
||||
% url_safe - use Modified Base64 for URL applications ('base64url'
|
||||
% encoding) "Base64 alphabet" ([A-Za-z0-9-_=]).
|
||||
%
|
||||
%
|
||||
% OUTPUT:
|
||||
% y - character array using only "Base64 alphabet" characters
|
||||
%
|
||||
% This function may be used to encode strings into the Base64 encoding
|
||||
% specified in RFC 2045 - MIME (Multipurpose Internet Mail Extensions).
|
||||
% The Base64 encoding is designed to represent arbitrary sequences of
|
||||
% octets in a form that need not be humanly readable. A 65-character
|
||||
% subset ([A-Za-z0-9+/=]) of US-ASCII is used, enabling 6 bits to be
|
||||
% represented per printable character.
|
||||
%
|
||||
% See also BASE64DECODE.
|
||||
%
|
||||
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
|
||||
%
|
||||
% Matlab version based on 2004 code by Peter J. Acklam
|
||||
% E-mail: pjacklam@online.no
|
||||
% URL: http://home.online.no/~pjacklam
|
||||
% http://home.online.no/~pjacklam/matlab/software/util/datautil/base64encode.m
|
||||
|
||||
if nargin<2, alg='java'; end
|
||||
if nargin<3, isChunked=false; end
|
||||
if ~islogical(isChunked)
|
||||
if isnumeric(isChunked)
|
||||
isChunked=(isChunked>0);
|
||||
else
|
||||
isChunked=false;
|
||||
end
|
||||
end
|
||||
if nargin<4, url_safe=false; end
|
||||
if ~islogical(url_safe)
|
||||
if isnumeric(url_safe)
|
||||
url_safe=(url_safe>0);
|
||||
else
|
||||
url_safe=false;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
%% if x happen to be a filename than read the file
|
||||
if (numel(x)<256)
|
||||
if (exist(x, 'file')==2)
|
||||
fid = fopen(x,'rb');
|
||||
x = fread(fid, 'uint8'); % read image file as a raw binary
|
||||
fclose(fid);
|
||||
end
|
||||
end
|
||||
|
||||
%% Perform conversion
|
||||
switch (alg)
|
||||
case 'java'
|
||||
base64 = org.apache.commons.codec.binary.Base64;
|
||||
y = base64.encodeBase64(x, isChunked);
|
||||
if url_safe
|
||||
y = strrep(y,'=','-');
|
||||
y = strrep(y,'/','_');
|
||||
end
|
||||
|
||||
case 'matlab'
|
||||
|
||||
%% add padding if necessary, to make the length of x a multiple of 3
|
||||
x = uint8(x(:));
|
||||
ndbytes = length(x); % number of decoded bytes
|
||||
nchunks = ceil(ndbytes / 3); % number of chunks/groups
|
||||
if rem(ndbytes, 3)>0
|
||||
x(end+1 : 3*nchunks) = 0; % add padding
|
||||
end
|
||||
x = reshape(x, [3, nchunks]); % reshape the data
|
||||
y = repmat(uint8(0), 4, nchunks); % for the encoded data
|
||||
|
||||
%% Split up every 3 bytes into 4 pieces
|
||||
% aaaaaabb bbbbcccc ccdddddd
|
||||
% to form
|
||||
% 00aaaaaa 00bbbbbb 00cccccc 00dddddd
|
||||
y(1,:) = bitshift(x(1,:), -2); % 6 highest bits of x(1,:)
|
||||
y(2,:) = bitshift(bitand(x(1,:), 3), 4); % 2 lowest bits of x(1,:)
|
||||
y(2,:) = bitor(y(2,:), bitshift(x(2,:), -4)); % 4 highest bits of x(2,:)
|
||||
y(3,:) = bitshift(bitand(x(2,:), 15), 2); % 4 lowest bits of x(2,:)
|
||||
y(3,:) = bitor(y(3,:), bitshift(x(3,:), -6)); % 2 highest bits of x(3,:)
|
||||
y(4,:) = bitand(x(3,:), 63); % 6 lowest bits of x(3,:)
|
||||
|
||||
%% Perform the mapping
|
||||
% 0 - 25 -> A-Z
|
||||
% 26 - 51 -> a-z
|
||||
% 52 - 61 -> 0-9
|
||||
% 62 -> +
|
||||
% 63 -> /
|
||||
map = ['A':'Z', 'a':'z', '0':'9', '+/'];
|
||||
if (url_safe), map(63:64)='-_'; end
|
||||
y = map(y(:)+1);
|
||||
|
||||
%% Add padding if necessary.
|
||||
npbytes = 3 * nchunks - ndbytes; % number of padding bytes
|
||||
if npbytes>0
|
||||
y(end-npbytes+1 : end) = '='; % '=' is used for padding
|
||||
end
|
||||
|
||||
%% break into lines with length LineLength
|
||||
if (isChunked)
|
||||
eol = sprintf('\n');
|
||||
nebytes = numel(y);
|
||||
nlines = ceil(nebytes / 76); % number of lines
|
||||
neolbytes = length(eol); % number of bytes in eol string
|
||||
|
||||
% pad data so it becomes a multiple of 76 elements
|
||||
y(nebytes + 1 : 76 * nlines) = 0;
|
||||
y = reshape(y, 76, nlines);
|
||||
|
||||
% insert eol strings
|
||||
y(end + 1 : end + neolbytes, :) = eol(:, ones(1, nlines));
|
||||
|
||||
% remove padding, but keep the last eol string
|
||||
m = nebytes + neolbytes * (nlines - 1);
|
||||
n = (76+neolbytes)*nlines - neolbytes;
|
||||
y(m+1 : n) = [];
|
||||
end
|
||||
end
|
||||
|
||||
%% reshape to a row vector and make it a character array
|
||||
y = char(reshape(y, 1, numel(y)));
|
|
@ -0,0 +1,143 @@
|
|||
function gen_object_display( obj_struct,indent )
|
||||
%
|
||||
% gen_object_display - general function to display an object's content
|
||||
%
|
||||
% format: gen_object_display( obj_struct,indent )
|
||||
%
|
||||
% input: obj_struct - a copy of the object stored inside a structure
|
||||
% indent - amount of "indent" when printing to the screen
|
||||
%
|
||||
% output: to the screen
|
||||
%
|
||||
% example: gen_object_display( struct( my_object_handle) );
|
||||
% gen_object_display( ny_structure );
|
||||
%
|
||||
% Correction History:
|
||||
% 2006-11-01 - Jarek Tuszynski - added support for struct arrays
|
||||
|
||||
%% handle insufficient input
|
||||
if ( nargin == 0 )
|
||||
help gen_object_display;
|
||||
return;
|
||||
elseif (nargin == 1)
|
||||
indent = 1;
|
||||
end
|
||||
|
||||
%% check input for errors
|
||||
% if ~isstruct( obj_struct )
|
||||
% fprintf( '\n\n\tMake sure that ''obj_struct'' is a struct type\n' );
|
||||
% return
|
||||
% end
|
||||
|
||||
% if (iscell( obj_struct ))
|
||||
% for i =1:length(obj_struct)
|
||||
% gen_object_display( obj_struct{i},indent + 2 );
|
||||
% end
|
||||
% return
|
||||
% end
|
||||
if ~isstruct( obj_struct )
|
||||
space = sprintf( sprintf( '%%%ds',indent ),' ' );
|
||||
fprintf( ' %s', space);
|
||||
disp(obj_struct);
|
||||
return
|
||||
end
|
||||
|
||||
% find the longest name
|
||||
field_list = fieldnames( obj_struct );
|
||||
max_strlen = 0;
|
||||
for idx = 1:length( field_list )
|
||||
max_strlen = max( max_strlen,length(field_list{idx}) );
|
||||
end
|
||||
|
||||
%% setup the display format (spacing)
|
||||
space = sprintf( sprintf( '%%%ds',indent ),' ' );
|
||||
name_format = sprintf( ' %s%%%ds: ', space, max_strlen );
|
||||
name_format2= sprintf( ' %s%%%ds', space, max_strlen );
|
||||
max_displen = 110 - max_strlen - indent;
|
||||
|
||||
%% display each field, if it is not too long
|
||||
for iItem = 1:length( obj_struct ) % loop added by JT
|
||||
for idx = 1:length( field_list )
|
||||
|
||||
% prepare field name to be displayed
|
||||
name = sprintf( name_format,field_list{idx} );
|
||||
%temp = getfield( obj_struct,field_list{idx} ); % original by OG
|
||||
temp = obj_struct(iItem).(field_list{idx}); % modification by JT
|
||||
|
||||
% proceed according the variable's type
|
||||
switch (1)
|
||||
case islogical( temp ), % case added by JT
|
||||
if isscalar(temp)
|
||||
if (temp)
|
||||
fprintf( '%strue\n',name );
|
||||
else
|
||||
fprintf( '%sfalse\n',name );
|
||||
end
|
||||
else
|
||||
fprintf( '%s[%dx%d logical]\n',name,size(temp,1),size(temp,2) );
|
||||
end
|
||||
case ischar( temp ),
|
||||
if (length(temp)<max_displen )
|
||||
fprintf( '%s''%s''\n',name,temp' );
|
||||
else
|
||||
fprintf( '%s[%dx%d char]\n',name,size(temp,1),size(temp,2) );
|
||||
end
|
||||
case isnumeric( temp ),
|
||||
if (size( temp,1 )==1 )
|
||||
temp_b = num2str( temp );
|
||||
if (length(temp_b)<max_displen )
|
||||
fprintf( '%s[%s]\n',name,temp_b );
|
||||
else
|
||||
fprintf( '%s[%dx%d double]\n',name,size(temp,1),size(temp,2) );
|
||||
end
|
||||
else
|
||||
fprintf( '%s[%dx%d double]\n',name,size(temp,1),size(temp,2) );
|
||||
end
|
||||
case iscell( temp ),
|
||||
if (numel(temp)<10 && (isvector(temp) || isscalar(temp)))
|
||||
fprintf( '%s[%dx%d cell] = \n',name,size(temp,1),size(temp,2) );
|
||||
%disp(temp)
|
||||
for r =1:numel(temp)
|
||||
gen_object_display( temp{r},indent + max_strlen + 2 );
|
||||
fprintf('\n');
|
||||
end
|
||||
elseif (numel(temp)<10)
|
||||
fprintf( '%s[%dx%d cell] = \n',name,size(temp,1),size(temp,2) );
|
||||
for r =1:size(temp,1)
|
||||
gen_object_display( temp(r,:),indent + max_strlen + 2 );
|
||||
end
|
||||
else
|
||||
fprintf( '%s[%dx%d cell]\n',name,size(temp,1),size(temp,2) );
|
||||
end
|
||||
case isstruct( temp ),
|
||||
fprintf( '%s[%dx%d struct]\n',name,size(temp,1),size(temp,2) );
|
||||
if (indent<80)
|
||||
if (numel(temp)<10 && (isvector(temp) || isscalar(temp)))
|
||||
gen_object_display( temp,indent + max_strlen + 2 );
|
||||
elseif (numel(temp)<10)
|
||||
name2 = sprintf( name_format2,field_list{idx} );
|
||||
for r =1:size(temp,1)
|
||||
for c =1:size(temp,2)
|
||||
fprintf( '%s(%d,%d) =\n',name2,r,c );
|
||||
gen_object_display( temp(r,c),indent + max_strlen + 3 );
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
case isobject( temp ), fprintf( '%s[inherent object]\n',name );
|
||||
if (indent<80)
|
||||
cmd = sprintf( 'display( obj_struct.%s,%d );',field_list{idx},indent + max_strlen + 2 );
|
||||
eval( cmd );
|
||||
end
|
||||
otherwise,
|
||||
fprintf( '%s',name );
|
||||
try
|
||||
fprintf( temp );
|
||||
catch %#ok<CTCH>
|
||||
fprintf( '[No method to display type]' );
|
||||
end
|
||||
fprintf( '\n' );
|
||||
end
|
||||
end
|
||||
if (length(obj_struct)>1), fprintf('\n'); end % added by JT
|
||||
end % added by JT
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<MyTree>
|
||||
<table border="1">
|
||||
<tr>
|
||||
<td>Apples</td>
|
||||
<td>44%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bannanas</td>
|
||||
<td>23%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Oranges</td>
|
||||
<td>13%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Other</td>
|
||||
<td>10%</td>
|
||||
</tr>
|
||||
</table>
|
||||
</MyTree>
|
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 156 KiB |
|
@ -0,0 +1,24 @@
|
|||
Copyright (c) 2007, Jaroslaw Tuszynski
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml-stylesheet type="text/css" href="foo.css"?>
|
||||
<!-- This is a Global Comment -->
|
||||
<aaa xmlns:xsi="http://www.foo.org">
|
||||
<?ProcInst type="local processing instruction"?>
|
||||
<!-- local comment 1 -->
|
||||
bbb
|
||||
<!-- local comment 2 -->
|
||||
ccc
|
||||
<matrix bad-name='fff'>
|
||||
5e3+2*i, Inf
|
||||
NaN, pi
|
||||
</matrix>
|
||||
<ee_e> ee_e </ee_e>
|
||||
<ff-f> ff-f </ff-f>
|
||||
<ggög> ggög </ggög>
|
||||
<![CDATA[
|
||||
Here <ddd>xml</ddd> tags are treated as ...
|
||||
... text
|
||||
]]>
|
||||
</aaa>
|
||||
|
|
@ -0,0 +1,550 @@
|
|||
function [tree, RootName, DOMnode] = xml_read(xmlfile, Pref)
|
||||
%XML_READ reads xml files and converts them into Matlab's struct tree.
|
||||
%
|
||||
% DESCRIPTION
|
||||
% tree = xml_read(xmlfile) reads 'xmlfile' into data structure 'tree'
|
||||
%
|
||||
% tree = xml_read(xmlfile, Pref) reads 'xmlfile' into data structure 'tree'
|
||||
% according to your preferences
|
||||
%
|
||||
% [tree, RootName, DOMnode] = xml_read(xmlfile) get additional information
|
||||
% about XML file
|
||||
%
|
||||
% INPUT:
|
||||
% xmlfile URL or filename of xml file to read
|
||||
% Pref Preferences:
|
||||
% Pref.ItemName - default 'item' - name of a special tag used to itemize
|
||||
% cell arrays
|
||||
% Pref.ReadAttr - default true - allow reading attributes
|
||||
% Pref.ReadSpec - default true - allow reading special nodes
|
||||
% Pref.Str2Num - default 'smart' - convert strings that look like numbers
|
||||
% to numbers. Options: "always", "never", and "smart"
|
||||
% Pref.KeepNS - default true - keep or strip namespace info
|
||||
% Pref.NoCells - default true - force output to have no cell arrays
|
||||
% Pref.Debug - default false - show mode specific error messages
|
||||
% Pref.NumLevels- default infinity - how many recursive levels are
|
||||
% allowed. Can be used to speed up the function by prunning the tree.
|
||||
% Pref.RootOnly - default true - output variable 'tree' corresponds to
|
||||
% xml file root element, otherwise it correspond to the whole file.
|
||||
% Pref.CellItem - default 'true' - leave 'item' nodes in cell notation.
|
||||
% OUTPUT:
|
||||
% tree tree of structs and/or cell arrays corresponding to xml file
|
||||
% RootName XML tag name used for root (top level) node.
|
||||
% Optionally it can be a string cell array storing: Name of
|
||||
% root node, document "Processing Instructions" data and
|
||||
% document "comment" string
|
||||
% DOMnode output of xmlread
|
||||
%
|
||||
% DETAILS:
|
||||
% Function xml_read first calls MATLAB's xmlread function and than
|
||||
% converts its output ('Document Object Model' tree of Java objects)
|
||||
% to tree of MATLAB struct's. The output is in format of nested structs
|
||||
% and cells. In the output data structure field names are based on
|
||||
% XML tags, except in cases when tags produce illegal variable names.
|
||||
%
|
||||
% Several special xml node types result in special tags for fields of
|
||||
% 'tree' nodes:
|
||||
% - node.CONTENT - stores data section of the node if other fields are
|
||||
% present. Usually data section is stored directly in 'node'.
|
||||
% - node.ATTRIBUTE.name - stores node's attribute called 'name'.
|
||||
% - node.COMMENT - stores node's comment section (string). For global
|
||||
% comments see "RootName" output variable.
|
||||
% - node.CDATA_SECTION - stores node's CDATA section (string).
|
||||
% - node.PROCESSING_INSTRUCTIONS - stores "processing instruction" child
|
||||
% node. For global "processing instructions" see "RootName" output variable.
|
||||
% - other special node types like: document fragment nodes, document type
|
||||
% nodes, entity nodes, notation nodes and processing instruction nodes
|
||||
% will be treated like regular nodes
|
||||
%
|
||||
% EXAMPLES:
|
||||
% MyTree=[];
|
||||
% MyTree.MyNumber = 13;
|
||||
% MyTree.MyString = 'Hello World';
|
||||
% xml_write('test.xml', MyTree);
|
||||
% [tree treeName] = xml_read ('test.xml');
|
||||
% disp(treeName)
|
||||
% gen_object_display()
|
||||
% % See also xml_examples.m
|
||||
%
|
||||
% See also:
|
||||
% xml_write, xmlread, xmlwrite
|
||||
%
|
||||
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
|
||||
% References:
|
||||
% - Function inspired by Example 3 found in xmlread function.
|
||||
% - Output data structures inspired by xml_toolbox structures.
|
||||
|
||||
%% default preferences
|
||||
DPref.TableName = {'tr','td'}; % name of a special tags used to itemize 2D cell arrays
|
||||
DPref.ItemName = 'item'; % name of a special tag used to itemize 1D cell arrays
|
||||
DPref.CellItem = false; % leave 'item' nodes in cell notation
|
||||
DPref.ReadAttr = true; % allow reading attributes
|
||||
DPref.ReadSpec = true; % allow reading special nodes: comments, CData, etc.
|
||||
DPref.KeepNS = true; % Keep or strip namespace info
|
||||
DPref.Str2Num = 'smart';% convert strings that look like numbers to numbers
|
||||
DPref.NoCells = true; % force output to have no cell arrays
|
||||
DPref.NumLevels = 1e10; % number of recurence levels
|
||||
DPref.PreserveSpace = false; % Preserve or delete spaces at the beggining and the end of stings?
|
||||
RootOnly = true; % return root node with no top level special nodes
|
||||
Debug = false; % show specific errors (true) or general (false)?
|
||||
tree = [];
|
||||
RootName = [];
|
||||
|
||||
%% Check Matlab Version
|
||||
v = ver('MATLAB');
|
||||
version = str2double(regexp(v.Version, '\d.\d','match','once'));
|
||||
if (version<7.1)
|
||||
error('Your MATLAB version is too old. You need version 7.1 or newer.');
|
||||
end
|
||||
|
||||
%% read user preferences
|
||||
if (nargin>1)
|
||||
if (isfield(Pref, 'TableName')), DPref.TableName = Pref.TableName; end
|
||||
if (isfield(Pref, 'ItemName' )), DPref.ItemName = Pref.ItemName; end
|
||||
if (isfield(Pref, 'CellItem' )), DPref.CellItem = Pref.CellItem; end
|
||||
if (isfield(Pref, 'Str2Num' )), DPref.Str2Num = Pref.Str2Num ; end
|
||||
if (isfield(Pref, 'NoCells' )), DPref.NoCells = Pref.NoCells ; end
|
||||
if (isfield(Pref, 'NumLevels')), DPref.NumLevels = Pref.NumLevels; end
|
||||
if (isfield(Pref, 'ReadAttr' )), DPref.ReadAttr = Pref.ReadAttr; end
|
||||
if (isfield(Pref, 'ReadSpec' )), DPref.ReadSpec = Pref.ReadSpec; end
|
||||
if (isfield(Pref, 'KeepNS' )), DPref.KeepNS = Pref.KeepNS; end
|
||||
if (isfield(Pref, 'RootOnly' )), RootOnly = Pref.RootOnly; end
|
||||
if (isfield(Pref, 'Debug' )), Debug = Pref.Debug ; end
|
||||
if (isfield(Pref, 'PreserveSpace')), DPref.PreserveSpace = Pref.PreserveSpace; end
|
||||
end
|
||||
if ischar(DPref.Str2Num), % convert from character description to numbers
|
||||
DPref.Str2Num = find(strcmpi(DPref.Str2Num, {'never', 'smart', 'always'}))-1;
|
||||
if isempty(DPref.Str2Num), DPref.Str2Num=1; end % 1-smart by default
|
||||
end
|
||||
|
||||
%% read xml file using Matlab function
|
||||
if isa(xmlfile, 'org.apache.xerces.dom.DeferredDocumentImpl');
|
||||
% if xmlfile is a DOMnode than skip the call to xmlread
|
||||
try
|
||||
try
|
||||
DOMnode = xmlfile;
|
||||
catch ME
|
||||
error('Invalid DOM node: \n%s.', getReport(ME));
|
||||
end
|
||||
catch %#ok<CTCH> catch for mablab versions prior to 7.5
|
||||
error('Invalid DOM node. \n');
|
||||
end
|
||||
else % we assume xmlfile is a filename
|
||||
if (Debug) % in debuging mode crashes are allowed
|
||||
DOMnode = xmlread(xmlfile);
|
||||
else % in normal mode crashes are not allowed
|
||||
try
|
||||
try
|
||||
DOMnode = xmlread(xmlfile);
|
||||
catch ME
|
||||
error('Failed to read XML file %s: \n%s',xmlfile, getReport(ME));
|
||||
end
|
||||
catch %#ok<CTCH> catch for mablab versions prior to 7.5
|
||||
error('Failed to read XML file %s\n',xmlfile);
|
||||
end
|
||||
end
|
||||
end
|
||||
Node = DOMnode.getFirstChild;
|
||||
|
||||
%% Find the Root node. Also store data from Global Comment and Processing
|
||||
% Instruction nodes, if any.
|
||||
GlobalTextNodes = cell(1,3);
|
||||
GlobalProcInst = [];
|
||||
GlobalComment = [];
|
||||
GlobalDocType = [];
|
||||
while (~isempty(Node))
|
||||
if (Node.getNodeType==Node.ELEMENT_NODE)
|
||||
RootNode=Node;
|
||||
elseif (Node.getNodeType==Node.PROCESSING_INSTRUCTION_NODE)
|
||||
data = strtrim(char(Node.getData));
|
||||
target = strtrim(char(Node.getTarget));
|
||||
GlobalProcInst = [target, ' ', data];
|
||||
GlobalTextNodes{2} = GlobalProcInst;
|
||||
elseif (Node.getNodeType==Node.COMMENT_NODE)
|
||||
GlobalComment = strtrim(char(Node.getData));
|
||||
GlobalTextNodes{3} = GlobalComment;
|
||||
% elseif (Node.getNodeType==Node.DOCUMENT_TYPE_NODE)
|
||||
% GlobalTextNodes{4} = GlobalDocType;
|
||||
end
|
||||
Node = Node.getNextSibling;
|
||||
end
|
||||
|
||||
%% parse xml file through calls to recursive DOMnode2struct function
|
||||
if (Debug) % in debuging mode crashes are allowed
|
||||
[tree RootName] = DOMnode2struct(RootNode, DPref, 1);
|
||||
else % in normal mode crashes are not allowed
|
||||
try
|
||||
try
|
||||
[tree RootName] = DOMnode2struct(RootNode, DPref, 1);
|
||||
catch ME
|
||||
error('Unable to parse XML file %s: \n %s.',xmlfile, getReport(ME));
|
||||
end
|
||||
catch %#ok<CTCH> catch for mablab versions prior to 7.5
|
||||
error('Unable to parse XML file %s.',xmlfile);
|
||||
end
|
||||
end
|
||||
|
||||
%% If there were any Global Text nodes than return them
|
||||
if (~RootOnly)
|
||||
if (~isempty(GlobalProcInst) && DPref.ReadSpec)
|
||||
t.PROCESSING_INSTRUCTION = GlobalProcInst;
|
||||
end
|
||||
if (~isempty(GlobalComment) && DPref.ReadSpec)
|
||||
t.COMMENT = GlobalComment;
|
||||
end
|
||||
if (~isempty(GlobalDocType) && DPref.ReadSpec)
|
||||
t.DOCUMENT_TYPE = GlobalDocType;
|
||||
end
|
||||
t.(RootName) = tree;
|
||||
tree=t;
|
||||
end
|
||||
if (~isempty(GlobalTextNodes))
|
||||
GlobalTextNodes{1} = RootName;
|
||||
RootName = GlobalTextNodes;
|
||||
end
|
||||
|
||||
|
||||
%% =======================================================================
|
||||
% === DOMnode2struct Function ===========================================
|
||||
% =======================================================================
|
||||
function [s TagName LeafNode] = DOMnode2struct(node, Pref, level)
|
||||
|
||||
%% === Step 1: Get node name and check if it is a leaf node ==============
|
||||
[TagName LeafNode] = NodeName(node, Pref.KeepNS);
|
||||
s = []; % initialize output structure
|
||||
|
||||
%% === Step 2: Process Leaf Nodes (nodes with no children) ===============
|
||||
if (LeafNode)
|
||||
if (LeafNode>1 && ~Pref.ReadSpec), LeafNode=-1; end % tags only so ignore special nodes
|
||||
if (LeafNode>0) % supported leaf node types
|
||||
try
|
||||
try % use try-catch: errors here are often due to VERY large fields (like images) that overflow java memory
|
||||
s = char(node.getData);
|
||||
if (isempty(s)), s = ' '; end % make it a string
|
||||
% for some reason current xmlread 'creates' a lot of empty text
|
||||
% fields with first chatacter=10 - those will be deleted.
|
||||
if (~Pref.PreserveSpace || s(1)==10)
|
||||
if (isspace(s(1)) || isspace(s(end))), s = strtrim(s); end % trim speces is any
|
||||
end
|
||||
if (LeafNode==1), s=str2var(s, Pref.Str2Num, 0); end % convert to number(s) if needed
|
||||
catch ME % catch for mablab versions 7.5 and higher
|
||||
warning('xml_io_tools:read:LeafRead', ...
|
||||
'This leaf node could not be read and was ignored. ');
|
||||
getReport(ME)
|
||||
end
|
||||
catch %#ok<CTCH> catch for mablab versions prior to 7.5
|
||||
warning('xml_io_tools:read:LeafRead', ...
|
||||
'This leaf node could not be read and was ignored. ');
|
||||
end
|
||||
end
|
||||
if (LeafNode==3) % ProcessingInstructions need special treatment
|
||||
target = strtrim(char(node.getTarget));
|
||||
s = [target, ' ', s];
|
||||
end
|
||||
return % We are done the rest of the function deals with nodes with children
|
||||
end
|
||||
if (level>Pref.NumLevels+1), return; end % if Pref.NumLevels is reached than we are done
|
||||
|
||||
%% === Step 3: Process nodes with children ===============================
|
||||
if (node.hasChildNodes) % children present
|
||||
Child = node.getChildNodes; % create array of children nodes
|
||||
nChild = Child.getLength; % number of children
|
||||
|
||||
% --- pass 1: how many children with each name -----------------------
|
||||
f = [];
|
||||
for iChild = 1:nChild % read in each child
|
||||
[cname cLeaf] = NodeName(Child.item(iChild-1), Pref.KeepNS);
|
||||
if (cLeaf<0), continue; end % unsupported leaf node types
|
||||
if (~isfield(f,cname)),
|
||||
f.(cname)=0; % initialize first time I see this name
|
||||
end
|
||||
f.(cname) = f.(cname)+1; % add to the counter
|
||||
end % end for iChild
|
||||
% text_nodes become CONTENT & for some reason current xmlread 'creates' a
|
||||
% lot of empty text fields so f.CONTENT value should not be trusted
|
||||
if (isfield(f,'CONTENT') && f.CONTENT>2), f.CONTENT=2; end
|
||||
|
||||
% --- pass 2: store all the children as struct of cell arrays ----------
|
||||
for iChild = 1:nChild % read in each child
|
||||
[c cname cLeaf] = DOMnode2struct(Child.item(iChild-1), Pref, level+1);
|
||||
if (cLeaf && isempty(c)) % if empty leaf node than skip
|
||||
continue; % usually empty text node or one of unhandled node types
|
||||
elseif (nChild==1 && cLeaf==1)
|
||||
s=c; % shortcut for a common case
|
||||
else % if normal node
|
||||
if (level>Pref.NumLevels), continue; end
|
||||
n = f.(cname); % how many of them in the array so far?
|
||||
if (~isfield(s,cname)) % encountered this name for the first time
|
||||
if (n==1) % if there will be only one of them ...
|
||||
s.(cname) = c; % than save it in format it came in
|
||||
else % if there will be many of them ...
|
||||
s.(cname) = cell(1,n);
|
||||
s.(cname){1} = c; % than save as cell array
|
||||
end
|
||||
f.(cname) = 1; % initialize the counter
|
||||
else % already have seen this name
|
||||
s.(cname){n+1} = c; % add to the array
|
||||
f.(cname) = n+1; % add to the array counter
|
||||
end
|
||||
end
|
||||
end % for iChild
|
||||
end % end if (node.hasChildNodes)
|
||||
|
||||
%% === Step 4: Post-process struct's created for nodes with children =====
|
||||
if (isstruct(s))
|
||||
fields = fieldnames(s);
|
||||
nField = length(fields);
|
||||
|
||||
% Detect structure that looks like Html table and store it in cell Matrix
|
||||
if (nField==1 && strcmpi(fields{1},Pref.TableName{1}))
|
||||
tr = s.(Pref.TableName{1});
|
||||
fields2 = fieldnames(tr{1});
|
||||
if (length(fields2)==1 && strcmpi(fields2{1},Pref.TableName{2}))
|
||||
% This seems to be a special structure such that for
|
||||
% Pref.TableName = {'tr','td'} 's' corresponds to
|
||||
% <tr> <td>M11</td> <td>M12</td> </tr>
|
||||
% <tr> <td>M12</td> <td>M22</td> </tr>
|
||||
% Recognize it as encoding for 2D struct
|
||||
nr = length(tr);
|
||||
for r = 1:nr
|
||||
row = tr{r}.(Pref.TableName{2});
|
||||
Table(r,1:length(row)) = row; %#ok<AGROW>
|
||||
end
|
||||
s = Table;
|
||||
end
|
||||
end
|
||||
|
||||
% --- Post-processing: convert 'struct of cell-arrays' to 'array of structs'
|
||||
% Example: let say s has 3 fields s.a, s.b & s.c and each field is an
|
||||
% cell-array with more than one cell-element and all 3 have the same length.
|
||||
% Then change it to array of structs, each with single cell.
|
||||
% This way element s.a{1} will be now accessed through s(1).a
|
||||
vec = zeros(size(fields));
|
||||
for i=1:nField, vec(i) = f.(fields{i}); end
|
||||
if (numel(vec)>1 && vec(1)>1 && var(vec)==0) % convert from struct of
|
||||
s = cell2struct(struct2cell(s), fields, 1); % arrays to array of struct
|
||||
end % if anyone knows better way to do above conversion please let me know.
|
||||
|
||||
end
|
||||
|
||||
%% === Step 5: Process nodes with attributes =============================
|
||||
if (node.hasAttributes && Pref.ReadAttr)
|
||||
if (~isstruct(s)), % make into struct if is not already
|
||||
ss.CONTENT=s;
|
||||
s=ss;
|
||||
end
|
||||
Attr = node.getAttributes; % list of all attributes
|
||||
for iAttr = 1:Attr.getLength % for each attribute
|
||||
name = char(Attr.item(iAttr-1).getName); % attribute name
|
||||
name = str2varName(name, Pref.KeepNS); % fix name if needed
|
||||
value = char(Attr.item(iAttr-1).getValue); % attribute value
|
||||
value = str2var(value, Pref.Str2Num, 1); % convert to number if possible
|
||||
s.ATTRIBUTE.(name) = value; % save again
|
||||
end % end iAttr loop
|
||||
end % done with attributes
|
||||
if (~isstruct(s)), return; end %The rest of the code deals with struct's
|
||||
|
||||
%% === Post-processing: fields of "s"
|
||||
% convert 'cell-array of structs' to 'arrays of structs'
|
||||
fields = fieldnames(s); % get field names
|
||||
nField = length(fields);
|
||||
for iItem=1:length(s) % for each struct in the array - usually one
|
||||
for iField=1:length(fields)
|
||||
field = fields{iField}; % get field name
|
||||
% if this is an 'item' field and user want to leave those as cells
|
||||
% than skip this one
|
||||
if (strcmpi(field, Pref.ItemName) && Pref.CellItem), continue; end
|
||||
x = s(iItem).(field);
|
||||
if (iscell(x) && all(cellfun(@isstruct,x(:))) && numel(x)>1) % it's cell-array of structs
|
||||
% numel(x)>1 check is to keep 1 cell-arrays created when Pref.CellItem=1
|
||||
try % this operation fails sometimes
|
||||
% example: change s(1).a{1}.b='jack'; s(1).a{2}.b='john'; to
|
||||
% more convinient s(1).a(1).b='jack'; s(1).a(2).b='john';
|
||||
s(iItem).(field) = [x{:}]'; %#ok<AGROW> % converted to arrays of structs
|
||||
catch %#ok<CTCH>
|
||||
% above operation will fail if s(1).a{1} and s(1).a{2} have
|
||||
% different fields. If desired, function forceCell2Struct can force
|
||||
% them to the same field structure by adding empty fields.
|
||||
if (Pref.NoCells)
|
||||
s(iItem).(field) = forceCell2Struct(x); %#ok<AGROW>
|
||||
end
|
||||
end % end catch
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%% === Step 4: Post-process struct's created for nodes with children =====
|
||||
|
||||
% --- Post-processing: remove special 'item' tags ---------------------
|
||||
% many xml writes (including xml_write) use a special keyword to mark
|
||||
% arrays of nodes (see xml_write for examples). The code below converts
|
||||
% s.item to s.CONTENT
|
||||
ItemContent = false;
|
||||
if (isfield(s,Pref.ItemName))
|
||||
s.CONTENT = s.(Pref.ItemName);
|
||||
s = rmfield(s,Pref.ItemName);
|
||||
ItemContent = Pref.CellItem; % if CellItem than keep s.CONTENT as cells
|
||||
end
|
||||
|
||||
% --- Post-processing: clean up CONTENT tags ---------------------
|
||||
% if s.CONTENT is a cell-array with empty elements at the end than trim
|
||||
% the length of this cell-array. Also if s.CONTENT is the only field than
|
||||
% remove .CONTENT part and store it as s.
|
||||
if (isfield(s,'CONTENT'))
|
||||
if (iscell(s.CONTENT) && isvector(s.CONTENT))
|
||||
x = s.CONTENT;
|
||||
for i=numel(x):-1:1, if ~isempty(x{i}), break; end; end
|
||||
if (i==1 && ~ItemContent)
|
||||
s.CONTENT = x{1}; % delete cell structure
|
||||
else
|
||||
s.CONTENT = x(1:i); % delete empty cells
|
||||
end
|
||||
end
|
||||
if (nField==1)
|
||||
if (ItemContent)
|
||||
ss = s.CONTENT; % only child: remove a level but ensure output is a cell-array
|
||||
s=[]; s{1}=ss;
|
||||
else
|
||||
s = s.CONTENT; % only child: remove a level
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
%% =======================================================================
|
||||
% === forceCell2Struct Function =========================================
|
||||
% =======================================================================
|
||||
function s = forceCell2Struct(x)
|
||||
% Convert cell-array of structs, where not all of structs have the same
|
||||
% fields, to a single array of structs
|
||||
|
||||
%% Convert 1D cell array of structs to 2D cell array, where each row
|
||||
% represents item in original array and each column corresponds to a unique
|
||||
% field name. Array "AllFields" store fieldnames for each column
|
||||
AllFields = fieldnames(x{1}); % get field names of the first struct
|
||||
CellMat = cell(length(x), length(AllFields));
|
||||
for iItem=1:length(x)
|
||||
fields = fieldnames(x{iItem}); % get field names of the next struct
|
||||
for iField=1:length(fields) % inspect all fieldnames and find those
|
||||
field = fields{iField}; % get field name
|
||||
col = find(strcmp(field,AllFields),1);
|
||||
if isempty(col) % no column for such fieldname yet
|
||||
AllFields = [AllFields; field]; %#ok<AGROW>
|
||||
col = length(AllFields); % create a new column for it
|
||||
end
|
||||
CellMat{iItem,col} = x{iItem}.(field); % store rearanged data
|
||||
end
|
||||
end
|
||||
%% Convert 2D cell array to array of structs
|
||||
s = cell2struct(CellMat, AllFields, 2);
|
||||
|
||||
%% =======================================================================
|
||||
% === str2var Function ==================================================
|
||||
% =======================================================================
|
||||
function val=str2var(str, option, attribute)
|
||||
% Can this string 'str' be converted to a number? if so than do it.
|
||||
val = str;
|
||||
len = numel(str);
|
||||
if (len==0 || option==0), return; end % Str2Num="never" of empty string -> do not do enything
|
||||
if (len>10000 && option==1), return; end % Str2Num="smart" and string is very long -> probably base64 encoded binary
|
||||
digits = '(Inf)|(NaN)|(pi)|[\t\n\d\+\-\*\.ei EI\[\]\;\,]';
|
||||
s = regexprep(str, digits, ''); % remove all the digits and other allowed characters
|
||||
if (~all(~isempty(s))) % if nothing left than this is probably a number
|
||||
if (~isempty(strfind(str, ' '))), option=2; end %if str has white-spaces assume by default that it is not a date string
|
||||
if (~isempty(strfind(str, '['))), option=2; end % same with brackets
|
||||
str(strfind(str, '\n')) = ';';% parse data tables into 2D arrays, if any
|
||||
if (option==1) % the 'smart' option
|
||||
try % try to convert to a date, like 2007-12-05
|
||||
datenum(str); % if successful than leave it as string
|
||||
catch %#ok<CTCH> % if this is not a date than ...
|
||||
option=2; % ... try converting to a number
|
||||
end
|
||||
end
|
||||
if (option==2)
|
||||
if (attribute)
|
||||
num = str2double(str); % try converting to a single number using sscanf function
|
||||
if isnan(num), return; end % So, it wasn't really a number after all
|
||||
else
|
||||
num = str2num(str); %#ok<ST2NM> % try converting to a single number or array using eval function
|
||||
end
|
||||
if(isnumeric(num) && numel(num)>0), val=num; end % if convertion to a single was succesful than save
|
||||
end
|
||||
elseif ((str(1)=='[' && str(end)==']') || (str(1)=='{' && str(end)=='}')) % this looks like a (cell) array encoded as a string
|
||||
try
|
||||
val = eval(str);
|
||||
catch %#ok<CTCH>
|
||||
val = str;
|
||||
end
|
||||
elseif (~attribute) % see if it is a boolean array with no [] brackets
|
||||
str1 = lower(str);
|
||||
str1 = strrep(str1, 'false', '0');
|
||||
str1 = strrep(str1, 'true' , '1');
|
||||
s = regexprep(str1, '[01 \;\,]', ''); % remove all 0/1, spaces, commas and semicolons
|
||||
if (~all(~isempty(s))) % if nothing left than this is probably a boolean array
|
||||
num = str2num(str1); %#ok<ST2NM>
|
||||
if(isnumeric(num) && numel(num)>0), val = (num>0); end % if convertion was succesful than save as logical
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
%% =======================================================================
|
||||
% === str2varName Function ==============================================
|
||||
% =======================================================================
|
||||
function str = str2varName(str, KeepNS)
|
||||
% convert a sting to a valid matlab variable name
|
||||
if(KeepNS)
|
||||
str = regexprep(str,':','_COLON_', 'once', 'ignorecase');
|
||||
else
|
||||
k = strfind(str,':');
|
||||
if (~isempty(k))
|
||||
str = str(k+1:end);
|
||||
end
|
||||
end
|
||||
str = regexprep(str,'-','_DASH_' ,'once', 'ignorecase');
|
||||
if (~isvarname(str)) && (~iskeyword(str))
|
||||
str = genvarname(str);
|
||||
end
|
||||
|
||||
%% =======================================================================
|
||||
% === NodeName Function =================================================
|
||||
% =======================================================================
|
||||
function [Name LeafNode] = NodeName(node, KeepNS)
|
||||
% get node name and make sure it is a valid variable name in Matlab.
|
||||
% also get node type:
|
||||
% LeafNode=0 - normal element node,
|
||||
% LeafNode=1 - text node
|
||||
% LeafNode=2 - supported non-text leaf node,
|
||||
% LeafNode=3 - supported processing instructions leaf node,
|
||||
% LeafNode=-1 - unsupported non-text leaf node
|
||||
switch (node.getNodeType)
|
||||
case node.ELEMENT_NODE
|
||||
Name = char(node.getNodeName);% capture name of the node
|
||||
Name = str2varName(Name, KeepNS); % if Name is not a good variable name - fix it
|
||||
LeafNode = 0;
|
||||
case node.TEXT_NODE
|
||||
Name = 'CONTENT';
|
||||
LeafNode = 1;
|
||||
case node.COMMENT_NODE
|
||||
Name = 'COMMENT';
|
||||
LeafNode = 2;
|
||||
case node.CDATA_SECTION_NODE
|
||||
Name = 'CDATA_SECTION';
|
||||
LeafNode = 2;
|
||||
case node.DOCUMENT_TYPE_NODE
|
||||
Name = 'DOCUMENT_TYPE';
|
||||
LeafNode = 2;
|
||||
case node.PROCESSING_INSTRUCTION_NODE
|
||||
Name = 'PROCESSING_INSTRUCTION';
|
||||
LeafNode = 3;
|
||||
otherwise
|
||||
NodeType = {'ELEMENT','ATTRIBUTE','TEXT','CDATA_SECTION', ...
|
||||
'ENTITY_REFERENCE', 'ENTITY', 'PROCESSING_INSTRUCTION', 'COMMENT',...
|
||||
'DOCUMENT', 'DOCUMENT_TYPE', 'DOCUMENT_FRAGMENT', 'NOTATION'};
|
||||
Name = char(node.getNodeName);% capture name of the node
|
||||
warning('xml_io_tools:read:unkNode', ...
|
||||
'Unknown node type encountered: %s_NODE (%s)', NodeType{node.getNodeType}, Name);
|
||||
LeafNode = -1;
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,914 @@
|
|||
%% Tutorial for xml_io_tools Package
|
||||
% *By Jarek Tuszynski*
|
||||
%
|
||||
% Package xml_io_tools can read XML files into MATLAB struct and writes
|
||||
% MATLAB data types to XML files with help of simple interface to
|
||||
% MATLAB's xmlwrite and xmlread functions.
|
||||
%
|
||||
% Two function to simplify reading and writing XML files from MATLAB:
|
||||
%
|
||||
% * Function xml_read first calls MATLAB's xmlread function and than
|
||||
% converts its output ('Document Object Model' tree of Java objects)
|
||||
% to tree of MATLAB struct's. The output is in the format of nested
|
||||
% structs and cells. In the output data structure field names are based on
|
||||
% XML tags.
|
||||
%
|
||||
% * Function xml_write first convert input tree of MATLAB structs and cells
|
||||
% and other types to tree of 'Document Object Model' nodes, and then writes
|
||||
% resulting object to XML file using MATLAB's xmlwrite function. .
|
||||
%
|
||||
%% This package can:
|
||||
% * Read most XML files, created inside and outside of MATLAB environment,
|
||||
% and convert them to MATLAB data structures.
|
||||
% * Write any MATLAB's struct tree to XML file
|
||||
% * Handle XML attributes and special XML nodes like comments, processing
|
||||
% instructions and CDATA sections
|
||||
% * Supports base64 encoding and decoding to allow handling embeded binary
|
||||
% data
|
||||
% * Be studied, modified, customized, rewritten and used in other packages
|
||||
% without any limitations. All code is included and documented. Software
|
||||
% is distributed under BSD Licence (included).
|
||||
%
|
||||
%% This package does not:
|
||||
% * Guarantee to recover the same Matlab objects that were saved. If you
|
||||
% need to be able to recover carbon copy of the structure that was saved
|
||||
% than you will have to use one of the packages that uses special set of
|
||||
% tags saved as xml attributes that help to guide the parsing of XML code.
|
||||
% This package does not use those tags.
|
||||
% * Guarantee to work with older versions of MATLAB. Functions do not work
|
||||
% with versions of MATLAB prior to 7.1 (26-Jul-2005).
|
||||
%
|
||||
%% Change History
|
||||
% * 2006-11-06 - original version
|
||||
% * 2006-11-26 - corrected xml_write to handle writing Matlab's column
|
||||
% arrays to xml files. Bug discovered and diagnosed by Kalyan Dutta.
|
||||
% * 2006-11-28 - made changes to handle special node types like:
|
||||
% COMMENTS and CDATA sections
|
||||
% * 2007-03-12 - Writing CDATA sections still did not worked. The problem
|
||||
% was diagnosed and fixed by Alberto Amaro. The fix involved rewriting
|
||||
% xmlwrite to use Apache Xerces java files directly instead of MATLAB's
|
||||
% XMLUtils java class.
|
||||
% * 2007-06-21 - Fixed problem reported by Anna Kelbert in Reviews about
|
||||
% not writing attributes of ROOT node. Also: added support for Processing
|
||||
% Instructions, added support for global text nodes: Processing
|
||||
% Instructions and comments, allowed writing tag names with special
|
||||
% characters
|
||||
% * 2007-07-20 - Added tutorial script file. Extended support for global
|
||||
% text nodes. Added more Preference fields.
|
||||
% * 2008-01-23 - Fixed problem reported by Anna Krewet of converting dates
|
||||
% in format '2007-01-01' to numbers. Improved and added warning messages.
|
||||
% Added detection of old Matlab versions incompatible with the library.
|
||||
% Expanded documentation.
|
||||
% * 2008-06-23 - Fixed problem with writing 1D array reported by Mark Neil.
|
||||
% Extended xml_read's Pref.Num2Str to 3 settings (never, smart and always)
|
||||
% for better control. Added parameter Pref.KeepNS for keeping or ignoring
|
||||
% namespace data when reading. Fixed a bug related to writing 2D cell
|
||||
% arrays brought up by Andrej's Mosat review.
|
||||
% * 2008-09-11 - Resubmitting last upload - zip file is still old
|
||||
% * 2009-02-26 - Small changes. More error handling. More robust in case of
|
||||
% large binary objects. Added support for Base64 encoding/decoding of
|
||||
% binary objects (using functions by Peter J. Acklam).
|
||||
% * 2009-06-26 - changes to xml_read: added CellItem parameter to allow
|
||||
% better control of reading files with 'item' notation (see comment by
|
||||
% Shlomi); changed try-catch statements so xml_read would work for mablab
|
||||
% versions prior to 7.5 (see Thomas Pilutti comment)
|
||||
% * 2009-12-03 - added PreserveSpace parameter for contolling empty string
|
||||
% handling as suggested by Sebastiaan. Fix suggested by Michael Murphy.
|
||||
% Fixed number recognition code as suggested by Yuan Ren.
|
||||
% * 2010-05-04 - implemented fixes suggested by Dylan Reynolds from Airbus.
|
||||
% * 2010-07-28 - implemented support for 2D arrays of cells and structs
|
||||
% suggested by Rodney Behn from MIT Lincoln Laboratory. Also attempted
|
||||
% large scale cleanup of xml_write function
|
||||
% * 2010-08-18 - minor extension to allow better handling of logical
|
||||
% scalars and arrays and function handles suggested by Andreas Richter
|
||||
% and others
|
||||
% * 2010-09-20 - allow reading and writing of sparse matrices. Improve
|
||||
% reading of 1D boolean arrays.
|
||||
% * 2010-11-05 - Fix problem with empty cells reported by Richard Cotton;
|
||||
% fixed issues with reading boolean arrays reported by Zohar Bar-Yehuda;
|
||||
% Improved speed of base64 coding and decoding by switching to java based
|
||||
% code.
|
||||
%% Licence
|
||||
% The package is distributed under BSD License
|
||||
format compact; % viewing preference
|
||||
clear variables;
|
||||
type('license.txt')
|
||||
|
||||
%% Write XML file based on a Struct using "xml_write"
|
||||
% Any MATLAB data struct can be saved to XML file.
|
||||
MyTree=[];
|
||||
MyTree.MyNumber = 13;
|
||||
MyTree.MyString = 'Hello World';
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
|
||||
%% Read XML file producing a Struct using "xml_read"
|
||||
[tree treeName] = xml_read ('test.xml');
|
||||
disp([treeName{1} ' ='])
|
||||
gen_object_display(tree)
|
||||
|
||||
%% "Pref.XmlEngine" flag in "xml_write"
|
||||
% Occasionaly some operations are performed better by Apache Xerces XML
|
||||
% engine than default xmlread function. That is why xml_write provide an
|
||||
% option for choosing the underlaying xml engine. Code below performs the
|
||||
% same operation as the previous section but using Apache Xerces XML engine.
|
||||
% Notice that in this case name of root element
|
||||
% was passed as variable and not extracted from the variable name.
|
||||
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
xml_write('test.xml', MyTree, 'TreeOfMine', Pref);
|
||||
type('test.xml')
|
||||
|
||||
%% Writing Struct with different type MATLAB arrays
|
||||
MyTree=[];
|
||||
MyTree.Empty = []; % Empty variable
|
||||
MyTree.Num_1x1 = 13; % simple scalar
|
||||
MyTree.Vec_1x3 = [1 2 3]; % horizontal vector
|
||||
MyTree.Vec_4x1 = [1; 2; 3; 4]; % vertical vector
|
||||
MyTree.Mat_2x2 = [1, 2; 3, 4]; % 2D matrix
|
||||
MyTree.Cube_3D = reshape(1:8,[2 2 2]); % 3D array
|
||||
MyTree.String1 = '[2003 10 30]'; % number string with [] brackets
|
||||
MyTree.String2 = ' 2003 10 30 '; % number string without [] brackets
|
||||
MyTree.Logical_1x1 = false; % single logical
|
||||
MyTree.Logical_2x2 = [false, true; true, false]; % 2D matrix of logicals
|
||||
MyTree.Logical_Str = 'False False True True';
|
||||
MyTree.Int_2x2 = uint8([1 2;3 4]); % 2D matrix of uint8 integers
|
||||
MyTree.Complex_1x1 = complex(1, 7); % complex scalar
|
||||
MyTree.Complex_2x2 = complex([1 2;3 4],[2 2;7 7]); % 2D matrix of complex numbers
|
||||
MyTree.Sparse_9x9 = sparse(1:9,1:9,1); % sparse 9x9 matrix
|
||||
MyTree.Function = @sum; % function handle
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
|
||||
%% Read Struct with MATLAB arrays
|
||||
% Notice that 'Cube_3D' did not preserve original dimentions
|
||||
[tree treeName] = xml_read ('test.xml');
|
||||
disp([treeName{1} ' ='])
|
||||
gen_object_display(tree)
|
||||
|
||||
%% "Pref.StructItem" flag in "xml_write" (controls 1D arrays of structs)
|
||||
% *Create a simple structure with 1D array of struct's*
|
||||
MyTree = [];
|
||||
MyTree.a(1).b = 'jack';
|
||||
MyTree.a(2).b = 'john';
|
||||
gen_object_display(MyTree)
|
||||
%%
|
||||
% *Write XML with "StructItem = true" (default). Notice single 'a'
|
||||
% section and multiple 'item' sub-sections. Those subsections are used
|
||||
% to store array elements*
|
||||
wPref.StructItem = true;
|
||||
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||
type('test.xml')
|
||||
fprintf('\nxml_read output:\n')
|
||||
gen_object_display(xml_read ('test.xml'))
|
||||
%%
|
||||
% *Write XML with "StructItem = false". Notice multiple 'a' sections*
|
||||
wPref.StructItem = false;
|
||||
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||
type('test.xml')
|
||||
fprintf('\nxml_read output:\n')
|
||||
gen_object_display(xml_read ('test.xml'))
|
||||
%%
|
||||
% *Notice that xml_read function produced the same struct when reading both files*
|
||||
%%
|
||||
% *Potential problems with "StructItem = true":*
|
||||
wPref.StructItem = true;
|
||||
MyTree1 = []; MyTree1.a.b = 'jack';
|
||||
MyTree2 = []; MyTree2.a(1).b = 'jack';
|
||||
MyTree3 = []; MyTree3.a(2).b = 'jack';
|
||||
xml_write('test.xml', MyTree1, [], wPref); type('test.xml');
|
||||
xml_write('test.xml', MyTree2, [], wPref); type('test.xml');
|
||||
xml_write('test.xml', MyTree3, [], wPref); type('test.xml');
|
||||
%%
|
||||
% *Notice that MyTree1 and MyTree2 produce identical files with no 'items',
|
||||
% while MyTree2 and MyTree3 produce very different file structures. It was
|
||||
% pointed out to me that files produced from MyTree2 and MyTree3 can not
|
||||
% belong to the same schema, which can be a problem. The solution is to use
|
||||
% cells.*
|
||||
wPref.CellItem = true;
|
||||
wPref.NoCells = true;
|
||||
MyTree2 = []; MyTree2.a{1}.b = 'jack';
|
||||
MyTree3 = []; MyTree3.a{2}.b = 'jack';
|
||||
xml_write('test.xml', MyTree2, [], wPref); type('test.xml');
|
||||
xml_write('test.xml', MyTree3, [], wPref); type('test.xml');
|
||||
|
||||
|
||||
%% "Pref.CellItem" flag in "xml_write" (controls 1D arrays of cells)
|
||||
% *Create a simple structure with cell arrays*
|
||||
MyTree = [];
|
||||
MyTree.a = {'jack', 'john'};
|
||||
disp(MyTree)
|
||||
%%
|
||||
% *Write XML with "CellItem = true" (default). Notice single 'a'
|
||||
% section and multiple 'item' sections*
|
||||
Pref=[]; Pref.CellItem = true;
|
||||
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||
type('test.xml')
|
||||
fprintf('\nxml_read output:\n');
|
||||
disp(xml_read ('test.xml'))
|
||||
%%
|
||||
% *Write XML with "CellItem = false". Notice multiple 'a' sections*
|
||||
Pref=[]; Pref.CellItem = false;
|
||||
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||
type('test.xml')
|
||||
fprintf('\nxml_read output:\n');
|
||||
disp(xml_read ('test.xml'))
|
||||
%%
|
||||
% *Notice that xml_read function produced the same struct when reading both files*
|
||||
|
||||
%% "Pref.NoCells" flag in "xml_read"
|
||||
% *Create a cell/struct mixture object*
|
||||
MyTree = [];
|
||||
MyTree.a{1}.b = 'jack';
|
||||
MyTree.a{2}.b = [];
|
||||
MyTree.a{2}.c = 'john';
|
||||
gen_object_display(MyTree);
|
||||
%%
|
||||
% *Save it to xml file*
|
||||
Pref=[]; Pref.CellItem = false;
|
||||
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Read above file with "Pref.NoCells=true" (default) - output is quite different then input*
|
||||
% By default program is trying to convert everything to struct's and arrays
|
||||
% of structs. In case arrays of structs all the structs in array need to have the
|
||||
% same fields, and if they are not than MATLAB creates empty fields.
|
||||
Pref=[]; Pref.NoCells=true;
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
%%
|
||||
% *Read above file with "Pref.NoCells=false" - now input and output are the same*
|
||||
% Cell arrays of structs allow structs in array to have different fields.
|
||||
Pref=[]; Pref.NoCells=false;
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
|
||||
%% "Pref.ItemName" flag in "xml_write" (customize 1D arrays of structs and cells)
|
||||
% *Create a cell/struct mixture object*
|
||||
MyTree = [];
|
||||
MyTree.a{1}.b = 'jack';
|
||||
MyTree.a{2}.c = 'john';
|
||||
gen_object_display(MyTree);
|
||||
%%
|
||||
% *Save it to xml file, using 'item' notation but with different name*
|
||||
Pref=[];
|
||||
Pref.CellItem = true;
|
||||
Pref.ItemName = 'MyItem';
|
||||
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||
type('test.xml')
|
||||
|
||||
%% "Pref.ItemName" flag in "xml_read"
|
||||
% *Read above file with default settings ("Pref.ItemName = 'item'")*
|
||||
% The results do not match the original structure
|
||||
Pref=[]; Pref.NoCells = false;
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
%%
|
||||
% *Read above file with "Pref.ItemName = 'MyItem'" - now saved and read
|
||||
% MATLAB structures are the same*
|
||||
Pref=[];
|
||||
Pref.ItemName = 'MyItem';
|
||||
Pref.NoCells = false;
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
|
||||
%% "Pref.CellItem" flag in "xml_read"
|
||||
% "Pref.ItemName" is used to create xml files with clearly marked arrays
|
||||
% "Pref.CellItem" flag in "xml_read" ensures that they are always read as
|
||||
% arrays by forcing output to stay in cell format. In cell format s{1} is
|
||||
% different than s, while s(1) is indistinguishable from s.
|
||||
%%
|
||||
% *Create a test file*
|
||||
MyTree = [];
|
||||
MyTree.a1{1}.b = 'jack'; % a1 - single struct
|
||||
MyTree.a2{1}.b = 'jack'; % a2 - cell array of structs with the same fields
|
||||
MyTree.a2{2}.b = 'john';
|
||||
MyTree.a3{1}.b = 'jack'; % a3 - cell array of structs with the different fields
|
||||
MyTree.a3{2}.c = 'john';
|
||||
Pref=[];
|
||||
Pref.CellItem = true;
|
||||
Pref.Debug = true;
|
||||
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Read above file with "Pref.CellItem = true" (default)*
|
||||
% All outputs are in cell format
|
||||
Pref=[];
|
||||
Pref.NoCells = false; % allow cell output
|
||||
Pref.CellItem = true; % keep 'item' arrays as cells
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
%%
|
||||
% *Read above file with "Pref.CellItem = false"*
|
||||
% Outputs format is determined by content
|
||||
Pref=[];
|
||||
Pref.NoCells = false; % allow cell output
|
||||
Pref.CellItem = false; % allow 'item' arrays to beheave like other fields
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
%%
|
||||
% *Read above file with "Pref.CellItem = false" and "Pref.NoCells = true"*
|
||||
% All outputs are in struct format
|
||||
Pref=[];
|
||||
Pref.NoCells = true; % don't allow cell output
|
||||
Pref.CellItem = false; % allow 'item' arrays to beheave like other fields
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
|
||||
%% "Pref.CellTable" flag in "xml_write" (controls 2D arrays of cells)
|
||||
% *Create a structure with 2D arrays of cells*
|
||||
MyTree = [];
|
||||
MyTree.M = {[1,2;3,4], 'M12'; struct('a','jack'), {11, 'N12'; 21, 'N22'}};
|
||||
gen_object_display(MyTree)
|
||||
%%
|
||||
% *Write XML with "CellTable = 'Html" (default). This option mimics use of
|
||||
% HTML "tr" and "td" tags to encode 2D tables. Tag names can
|
||||
% be changed using TableName parameter (see below)*
|
||||
wPref = [];
|
||||
wPref.CellTable = 'Html';
|
||||
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||
type('test.xml')
|
||||
fprintf('\nxml_read output:\n')
|
||||
rPref=[]; rPref.NoCells=false;
|
||||
gen_object_display(xml_read('test.xml', rPref))
|
||||
%%
|
||||
% *Write XML with "CellTable = 'Vector'".*
|
||||
% Converts 2D arrays to 1D array and item or regular notation. This option
|
||||
% is mostly provided for backward compatibility since this was the
|
||||
% behavior in prior verions of the code
|
||||
wPref = [];
|
||||
wPref.CellTable = 'Vector';
|
||||
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||
type('test.xml')
|
||||
fprintf('\nxml_read output:\n')
|
||||
rPref=[]; rPref.NoCells=false;
|
||||
gen_object_display(xml_read('test.xml', rPref))
|
||||
%%
|
||||
% *Create a simpler structure without struct's*
|
||||
MyTree = [];
|
||||
MyTree.M = {[1,2;3,4], 'M12'; 'M21', {11, 'N12'; 21, 'N22'}};
|
||||
gen_object_display(MyTree)
|
||||
%%
|
||||
% *Write XML with "CellTable = 'Matlab". This option encodes tables
|
||||
% consisting of numbers, strings and other cell arrays as MATLAB command
|
||||
% string. Unlike 'Html' option it does not work if one of the cells is
|
||||
% a struct*
|
||||
wPref = [];
|
||||
wPref.CellTable = 'Matlab';
|
||||
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||
type('test.xml')
|
||||
fprintf('\nxml_read output:\n')
|
||||
rPref=[]; rPref.NoCells=false;
|
||||
gen_object_display(xml_read('test.xml', rPref))
|
||||
|
||||
%% Write 2D cell array in HTML format
|
||||
MyTree = [];
|
||||
MyTree.table.ATTRIBUTE.border=1;
|
||||
MyTree.table.CONTENT = {'Apples', '44%'; 'Bannanas', '23%'; 'Oranges', '13%'; 'Other', '10%'};
|
||||
xml_write('html/test.html', MyTree);
|
||||
type('html/test.html')
|
||||
%%
|
||||
% Click on <test.html> to opened this file with a web brouwser
|
||||
|
||||
%% "Pref.StructTable" flag in "xml_write" (controls 2D arrays of structs)
|
||||
% *Create a simple structure with arrays of struct's*
|
||||
MyTree = [];
|
||||
MyTree.a(1,1).b = 'jack';
|
||||
MyTree.a(1,2).b = 'john';
|
||||
MyTree.a(2,1).b = 'jim';
|
||||
MyTree.a(2,2).b = 'jill';
|
||||
gen_object_display(MyTree)
|
||||
%%
|
||||
% *Write XML with "StructTable = 'Html" (default). This option mimics use of
|
||||
% HTML "tr" and "td" tags to encode 2D tables. Tag names can
|
||||
% be changed using TableName parameter (see below)*
|
||||
wPref = [];
|
||||
wPref.StructTable = 'Html';
|
||||
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||
type('test.xml')
|
||||
fprintf('\nxml_read output:\n')
|
||||
gen_object_display(xml_read ('test.xml'))
|
||||
%%
|
||||
% *Write XML with "CellTable = 'Vector'".*
|
||||
% Converts 2D arrays to 1D array and item or regular notation. This option
|
||||
% is mostly provided for backward compatibility since this was the
|
||||
% behavior in prior verions of the code
|
||||
wPref = [];
|
||||
wPref.StructTable = 'Vector';
|
||||
xml_write('test.xml', MyTree, 'MyTree',wPref);
|
||||
type('test.xml')
|
||||
fprintf('\nxml_read output:\n')
|
||||
gen_object_display(xml_read ('test.xml'))
|
||||
|
||||
%% "Pref.TableName" flag in "xml_write" (controls encoding tags used for 2D arrays)
|
||||
% *Create a cell object*
|
||||
MyTree = [];
|
||||
MyTree.M = {[1,2;3,4], 'M12'; 21, {11, 'N12'; 21, 'N22'}};
|
||||
gen_object_display(MyTree);
|
||||
%%
|
||||
% *Save it to xml file, using 'Html' notation but with different names for
|
||||
% rows and cells*
|
||||
Pref=[]; Pref.TableName = {'row','cell'};
|
||||
xml_write('test.xml', MyTree, 'MyTree',Pref);
|
||||
type('test.xml')
|
||||
|
||||
%% "Pref.TableName" flag in "xml_read"
|
||||
% *Read above file with default settings ("Pref.TableName = {'tr','td'}")*
|
||||
% The results do not match the original structure
|
||||
Pref=[]; Pref.NoCells = false;
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
%%
|
||||
% *Read above file with "Pref.TableName = {'row','cell'}" - now saved and read
|
||||
% MATLAB structures are the same*
|
||||
Pref=[];
|
||||
Pref.TableName = {'row','cell'};
|
||||
Pref.NoCells = false;
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
|
||||
%% "Pref.Str2Num" flag in xml_read (control conversion to numbers while reading)
|
||||
% *Create a cell/struct mixture object*
|
||||
MyTree = [];
|
||||
MyTree.str = 'sphere';
|
||||
MyTree.num1 = 123;
|
||||
MyTree.num2 = '123';
|
||||
MyTree.num3 = '[Inf,NaN]';
|
||||
MyTree.calc = '1+2+3+4';
|
||||
MyTree.func = 'sin(pi)/2';
|
||||
MyTree.String1 = '[2003 10 30]';
|
||||
MyTree.String2 = '2003 10 30'; % array resembling date
|
||||
MyTree.ISO8601 = '2003-10-30'; % date in ISO 8601 format
|
||||
MyTree.US_date = '2003/10/30'; % US style date format
|
||||
MyTree.complex = '2003i-10e-30'; % complex number resembling a date
|
||||
gen_object_display(MyTree);
|
||||
%%
|
||||
% *Save it to xml file*
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Read above file with default settings*
|
||||
% ("Pref.Str2Num = true" or "Pref.Str2Num = 'smart'"). Under this setting all
|
||||
% strings that look like numbers are converted to numbers, except for
|
||||
% strings that are recognized by MATLAB 'datenum' function as dates
|
||||
gen_object_display(xml_read('test.xml'))
|
||||
%%
|
||||
% *Note that all the fields of 'MyTree' can be converted to numbers (even
|
||||
% 'sphere') but by default the function is trying to 'judge' if a string
|
||||
% should be converted to a number or not*
|
||||
MyCell = {'sphere','1+2+3+4','sin(pi)/2','2003 10 30','2003-10-30','2003/10/30','2003i-10e-30'};
|
||||
cellfun(@str2num, MyCell, 'UniformOutput', false)
|
||||
%%
|
||||
% *Read above file with "Pref.Str2Num = false" or "Pref.Str2Num = 'never'"
|
||||
% to keep all the fields in string format*
|
||||
Pref=[]; Pref.Str2Num = false;
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
%%
|
||||
% *Read above file with "Pref.Str2Num = always"
|
||||
% to convert all strings that look like numbers to numbers* note the likelly
|
||||
% unintendet conversion of 'ISO8601'
|
||||
Pref=[]; Pref.Str2Num = 'always';
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
%%
|
||||
% *Notice that all three settings will produce the same output for "num1" and
|
||||
% "num2" and there is no way to reproduce the original "MyTree" structure.*
|
||||
|
||||
%% "Pref.PreserveSpace" flag in xml_write (control handling of strings with leading/trailing spaces)
|
||||
% *Create a struct with strings*
|
||||
MyTree=[];
|
||||
MyTree.Empty = '';
|
||||
MyTree.OneSpace = ' ';
|
||||
MyTree.TwoSpaces = ' ';
|
||||
MyTree.String1 = ' Hello World ';
|
||||
%%
|
||||
% *Write XML with "PreserveSpace = false" (default).*
|
||||
Pref=[]; Pref.PreserveSpace = false; % (default setting)
|
||||
xml_write('test.xml', MyTree, [], Pref);
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Write XML with "PreserveSpace = true".*
|
||||
Pref=[]; Pref.PreserveSpace = true;
|
||||
xml_write('test.xml', MyTree, [], Pref);
|
||||
type('test.xml')
|
||||
|
||||
%% "Pref.PreserveSpace" flag in xml_read
|
||||
% *Read file while using "PreserveSpace = false" (default).*
|
||||
Pref=[]; Pref.PreserveSpace = false; % (default setting)
|
||||
gen_object_display(xml_read('test.xml',Pref))
|
||||
%%
|
||||
% *Read file while using "PreserveSpace = true".*
|
||||
Pref=[]; Pref.PreserveSpace = true;
|
||||
gen_object_display(xml_read('test.xml',Pref))
|
||||
|
||||
|
||||
%% Write XML files with ATTRIBUTEs
|
||||
% In order to add node attributes a special ATTRIBUTE field is used.
|
||||
% ATTRIBUTEs have to be of simple types like numbers or strings (not
|
||||
% struct or cells). Attributes are easy to attach to structs nodes like
|
||||
% MyTree below.
|
||||
MyTree=[];
|
||||
MyTree.MyNumber = 13;
|
||||
MyTree.MyString = 'Hello World'; % simple case
|
||||
MyTree.ATTRIBUTE.Num = 2;
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
|
||||
%%
|
||||
% In case when one needs to attach attributes to nodes which are not
|
||||
% structs (for example strings, numbers or calls) then special CONTENT
|
||||
% field needs to be used to make the node a struct node.
|
||||
MyTree=[];
|
||||
MyTree.MyNumber = 13;
|
||||
MyTree.MyString.CONTENT = 'Hello World'; % simple case
|
||||
MyTree.MyString.ATTRIBUTE.Num = 2;
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
|
||||
%% "Pref.Str2Num" flag in file with ATTRIBUTEs
|
||||
% *Create a cell/struct mixture object*
|
||||
MyTree = [];
|
||||
MyTree.X.ATTRIBUTE.str = 'sphere';
|
||||
MyTree.X.ATTRIBUTE.num1 = 123;
|
||||
MyTree.X.ATTRIBUTE.num2 = '123';
|
||||
MyTree.X.ATTRIBUTE.num3 = '[Inf,NaN]';
|
||||
MyTree.X.ATTRIBUTE.calc = '1+2+3+4';
|
||||
MyTree.X.ATTRIBUTE.func = 'sin(pi)/2';
|
||||
MyTree.X.ATTRIBUTE.String1 = '[2003 10 30]';
|
||||
MyTree.X.ATTRIBUTE.String2 = '2003 10 30'; % array resembling date
|
||||
MyTree.X.ATTRIBUTE.ISO8601 = '2003-10-30'; % date in ISO 8601 format
|
||||
MyTree.X.ATTRIBUTE.US_date = '2003/10/30'; % US style date format
|
||||
MyTree.X.ATTRIBUTE.complex = '2003i-10e-30'; % complex number resembling a date
|
||||
gen_object_display(MyTree);
|
||||
%%
|
||||
% *Save it to xml file*
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Read above file with default settings*
|
||||
% ("Pref.Str2Num = true" or "Pref.Str2Num = 'smart'"). Under this setting all
|
||||
% strings that look like numbers are converted to numbers, except for
|
||||
% strings that are recognized by MATLAB 'datenum' function as dates
|
||||
gen_object_display(xml_read('test.xml'))
|
||||
|
||||
%%
|
||||
% *Read above file with "Pref.Str2Num = false" or "Pref.Str2Num = 'never'"
|
||||
% to keep all the fields in string format*
|
||||
Pref=[]; Pref.Str2Num = false;
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
%%
|
||||
% *Read above file with "Pref.Str2Num = always"
|
||||
% to convert all strings that look like numbers to numbers*
|
||||
Pref=[]; Pref.Str2Num = 'always';
|
||||
gen_object_display(xml_read('test.xml', Pref))
|
||||
%%
|
||||
% *Notice that all three settings will produce the same output for "num1" and
|
||||
% "num2" and there is no way to reproduce the original "MyTree" structure.*
|
||||
|
||||
|
||||
%% Write XML files with COMMENTs
|
||||
% Insertion of Comments is done with help of special COMMENT field.
|
||||
% Note that MATLAB's xmlwrite is less readable due to lack of end-of-line
|
||||
% characters around comment section.
|
||||
MyTree=[];
|
||||
MyTree.COMMENT = 'This is a comment';
|
||||
MyTree.MyNumber = 13;
|
||||
MyTree.MyString.CONTENT = 'Hello World';
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
|
||||
%%
|
||||
% *Same operation using Apache Xerces XML engine*
|
||||
% gives the same result
|
||||
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
xml_write('test.xml', MyTree, 'MyTree', Pref);
|
||||
type('test.xml')
|
||||
|
||||
%%
|
||||
% *Comments in XML top level (method #1)*
|
||||
% This method uses cell array
|
||||
MyTree=[];
|
||||
MyTree.MyNumber = 13;
|
||||
MyTree.MyString = 'Hello World';
|
||||
xml_write('test.xml', MyTree, {'MyTree', [], 'This is a global comment'});
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Same operation using Apache Xerces XML engine*
|
||||
% gives even nicer results.
|
||||
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
xml_write('test.xml', MyTree, {'MyTree', [], 'This is a global comment'}, Pref);
|
||||
type('test.xml')
|
||||
|
||||
%%
|
||||
% *Comments in XML top level (method #2)*
|
||||
% This method adds an extra top layer to the struct 'tree' and sets
|
||||
% "Pref.RootOnly = false", which informs the function about the extra
|
||||
% layer. Notice that RootName is also saved as a part of
|
||||
% the 'tree', and does not have to be passed in separately.
|
||||
MyTree=[];
|
||||
MyTree.COMMENT = 'This is a global comment';
|
||||
MyTree.MyTest.MyNumber = 13;
|
||||
MyTree.MyTest.MyString = 'Hello World';
|
||||
Pref=[]; Pref.RootOnly = false;
|
||||
xml_write('test.xml', MyTree, [], Pref);
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Same operation using Apache Xerces XML engine*
|
||||
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
Pref.RootOnly = false;
|
||||
xml_write('test.xml', MyTree, [], Pref);
|
||||
type('test.xml')
|
||||
|
||||
%% Write XML files with PROCESSING_INSTRUCTIONs
|
||||
% Insertion of Processing Instructions is done through use of special
|
||||
% PROCESSING_INSTRUCTION field, which stores the instruction string. The
|
||||
% string has to be in 'target data' format separated by space.
|
||||
MyTree=[];
|
||||
MyTree.PROCESSING_INSTRUCTION = 'xml-stylesheet type="a" href="foo"';
|
||||
MyTree.MyNumber = 13;
|
||||
MyTree.MyString = 'Hello World';
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
|
||||
%%
|
||||
% *Same operation using Apache Xerces XML engine*
|
||||
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
xml_write('test.xml', MyTree, 'MyTree', Pref);
|
||||
type('test.xml')
|
||||
|
||||
%%
|
||||
% *PROCESSING_INSTRUCTIONs in XML top level (method #1)*
|
||||
% This method uses cell array
|
||||
MyTree=[];
|
||||
MyTree.MyNumber = 13;
|
||||
MyTree.MyString = 'Hello World';
|
||||
xml_write('test.xml', MyTree, {'MyTree', 'xml-stylesheet type="a" href="foo"'});
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Same operation using Apache Xerces XML engine*
|
||||
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
xml_write('test.xml', MyTree, {'MyTree', 'xml-stylesheet type="a" href="foo"'}, Pref);
|
||||
type('test.xml')
|
||||
|
||||
%%
|
||||
% *PROCESSING_INSTRUCTIONs in XML top level (method #2)*
|
||||
% This method adds an extra top layer to the struct 'tree' and sets
|
||||
% pref.RootOnly=false, which informs the function about the extra
|
||||
% layer. Notice that RootName is also saved as a part of
|
||||
% the 'tree', and does not have to be passed in separately.
|
||||
MyTree=[];
|
||||
MyTree.PROCESSING_INSTRUCTION = 'xml-stylesheet type="a" href="foo"';
|
||||
MyTree.MyTest.MyNumber = 13;
|
||||
MyTree.MyTest.MyString = 'Hello World';
|
||||
Pref=[]; Pref.RootOnly = false;
|
||||
xml_write('test.xml', MyTree, [], Pref);
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Same operation using Apache Xerces XML engine*
|
||||
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
Pref.RootOnly = false;
|
||||
xml_write('test.xml', MyTree, 'MyTree', Pref);
|
||||
type('test.xml')
|
||||
|
||||
%% Write XML files with CDATA Sections
|
||||
% "In an XML document a CDATA (Character DATA) section is a section of
|
||||
% element content that is marked for the parser to interpret as only
|
||||
% character data, not markup." (from Wikipedia)
|
||||
% To insert CDATA Sections one use special CDATA_SECTION field,
|
||||
% which stores the instruction string. Note that MATLAB's xmlwrite created
|
||||
% wrong xml code for CDATA section
|
||||
MyTree=[];
|
||||
MyTree.CDATA_SECTION = '<A>txt</A>';
|
||||
MyTree.MyNumber = 13;
|
||||
MyTree.MyString = 'Hello World';
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Same operation using Apache Xerces XML engine produces correct results*
|
||||
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
xml_write('test.xml', MyTree, 'MyTree', Pref);
|
||||
type('test.xml')
|
||||
|
||||
%% Write XML files with special characters in TAG names
|
||||
% The input to xml_write requires that all tags one wants in XML document
|
||||
% have to be encoded as field names of MATLAB's struct's. Matlab has a lot
|
||||
% of restrictions on variable names. This section is about XML tags with
|
||||
% names not allowed as MATLAB variables, or more specifically with
|
||||
% characters allowed as xml tag names but not allowed as MATLAB variable
|
||||
% names. Characters like that can be replaced by their hexadecimal
|
||||
% representation just as it is done by genvarname function. Alternative way
|
||||
% of writing the first example is:
|
||||
MyTree=[];
|
||||
MyTree.('MyNumber') = 13; % same as MyTree.MyNumber = 13;
|
||||
MyTree.MyString.CONTENT = 'Hello World';
|
||||
MyTree.MyString.ATTRIBUTE.('Num') = 2; % same as MyTree.MyString.ATTRIBUTE.Num = 2;
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
|
||||
%%
|
||||
% *This approach fails for some characters like dash '-', colon ':', and
|
||||
% international characters.*
|
||||
MyTree=[];
|
||||
try
|
||||
MyTree.('My-Number') = 13;
|
||||
MyTree.MyString.CONTENT = 'Hello World';
|
||||
MyTree.MyString.ATTRIBUTE.('Num_ö') = 2;
|
||||
catch %#ok<CTCH>
|
||||
err = lasterror; %#ok<LERR>
|
||||
disp(err.message);
|
||||
end
|
||||
|
||||
%%
|
||||
% It can be overcome by replacing offending characters with their
|
||||
% hexadecimal representation. That can be done manually or with use of
|
||||
% genvarname function. Note that MATLAB 'type' function does not show
|
||||
% correctly 'ö' letter in xml file, but opening the file in editor shows
|
||||
% that it is correct.
|
||||
MyTree=[];
|
||||
MyTree.(genvarname('My-Number')) = 13;
|
||||
MyTree.MyString.CONTENT = 'Hello World';
|
||||
MyTree.MyString.ATTRIBUTE.Num_0xF6 = 2;
|
||||
gen_object_display(MyTree);
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
|
||||
%%
|
||||
% *Also two of the characters '-' and ':' can be encoded by a special strings:
|
||||
% '_DASH_' and '_COLON_' respectively*
|
||||
MyTree=[];
|
||||
MyTree.My_DASH_Number = 13;
|
||||
MyTree.MyString.CONTENT = 'Hello World';
|
||||
MyTree.MyString.ATTRIBUTE.Num0xF6 = 2;
|
||||
xml_write('test.xml', MyTree);
|
||||
type('test.xml')
|
||||
|
||||
%% Write XML files with Namespaces
|
||||
% No extra special fields are needed to define XML namespaces, only colon
|
||||
% character written using '0x3A' or '_COLON_'. Below is an
|
||||
% example of a namespace definition
|
||||
MyTree=[];
|
||||
MyTree.f_COLON_child.ATTRIBUTE.xmlns_COLON_f = 'http://www.foo.com';
|
||||
MyTree.f_COLON_child.f_COLON_MyNumber = 13;
|
||||
MyTree.f_COLON_child.f_COLON_MyString = 'Hello World';
|
||||
xml_write('test.xml', MyTree, 'MyTree');
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Same operation using Apache Xerces XML engine*
|
||||
Pref=[]; Pref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
xml_write('test.xml', MyTree, 'f_COLON_MyTree', Pref);
|
||||
type('test.xml')
|
||||
|
||||
%% "Pref.KeepNS" flag in "xml_read"
|
||||
% Thise option allow keeping or exclusion of namespaces in tag names.
|
||||
% By default the namespace data is kept but it produces much longer field
|
||||
% names in the output structure. Ignoring namespace will produce more
|
||||
% readible output.
|
||||
% Perform default read of file with namespace
|
||||
tree = xml_read('test.xml');
|
||||
gen_object_display(tree);
|
||||
|
||||
%%
|
||||
% Now the same operation with KeepNS = false.
|
||||
Pref=[]; Pref.KeepNS = false; % do not read attributes
|
||||
tree = xml_read('test.xml', Pref);
|
||||
gen_object_display(tree);
|
||||
|
||||
%% Read XML files with special node types
|
||||
% Display and read the file, then show the data structure. Note that
|
||||
% MATLAB 'type' function shows 'ö' letter incorrectly as 'A¶' in xml file,
|
||||
% but opening the file in editor shows that it is correct.
|
||||
fprintf('Test xml file:\n');
|
||||
type('test_file.xml')
|
||||
%%
|
||||
% Read only the Root Element (default)
|
||||
[tree GlobalTextNodes] = xml_read('test_file.xml');
|
||||
fprintf('Global Data (Root name, Global Processing Instructions and Global Comments):\n');
|
||||
disp(GlobalTextNodes')
|
||||
fprintf('\nStructure read from the file (uncludes COMMENT and CDATA sections):\n');
|
||||
gen_object_display(tree);
|
||||
%%
|
||||
% Read the whole tree including global Comments and Processing Instructions
|
||||
Pref=[]; Pref.RootOnly = false;
|
||||
[tree GlobalTextNodes] = xml_read('test_file.xml', Pref);
|
||||
fprintf('Global Data (Root name, Global Processing Instructions and Global Comments):\n');
|
||||
disp(GlobalTextNodes')
|
||||
fprintf('\nStructure read from the file (uncludes COMMENT and CDATA sections):\n');
|
||||
gen_object_display(tree);
|
||||
|
||||
%% "Pref.ReadAttr" flag in "xml_read" (control handling of nodes with attributes)
|
||||
% Those option allow exclusion of attributes
|
||||
Pref=[]; Pref.ReadAttr = false; % do not read attributes
|
||||
tree = xml_read('test_file.xml', Pref);
|
||||
gen_object_display(tree);
|
||||
|
||||
%% "Pref.ReadSpec" flag in "xml_read"
|
||||
% Those option allow exclusion of special nodes, like
|
||||
% comments, processing instructions, CData sections, etc.
|
||||
Pref=[]; Pref.ReadSpec = false; % do not read special node types
|
||||
tree = xml_read('test_file.xml', Pref);
|
||||
gen_object_display(tree);
|
||||
|
||||
%% "Pref.RootOnly" flag in "xml_read"
|
||||
% As it was shown in previous examples RootOnly parameter can be used to
|
||||
% capture global (top level) special nodes (like COMMENTs and
|
||||
% PROCESSING_INSTRUCTIONs) which are ignored by default
|
||||
Pref=[]; Pref.RootOnly = false; % do not read special node types
|
||||
tree = xml_read('test_file.xml', Pref);
|
||||
gen_object_display(tree);
|
||||
|
||||
%% "Pref.RootOnly" flag in "xml_write"
|
||||
% Writing previously read tree with default "Pref.RootOnly = true" gives
|
||||
% wrong output file
|
||||
Pref=[]; Pref.RootOnly = true; % do not read special node types
|
||||
xml_write('test.xml', tree, [], Pref);
|
||||
fprintf('Test xml file:\n');
|
||||
type('test.xml')
|
||||
%%
|
||||
% Writing the same tree with "Pref.RootOnly = false" gives correct output
|
||||
Pref=[]; Pref.RootOnly = false; % do not read special node types
|
||||
xml_write('test.xml', tree, [], Pref);
|
||||
fprintf('Test xml file:\n');
|
||||
type('test.xml')
|
||||
|
||||
%% "Pref.NumLevels" flag in "xml_read"
|
||||
% This parameter allows user to skip parts of the tree in order to save
|
||||
% time and memory. Usefull only in a rare case when a small portion of
|
||||
% large XML file is needed.
|
||||
%
|
||||
% Create test tile
|
||||
MyTree = [];
|
||||
MyTree.Level1 = 1;
|
||||
MyTree.Level1_.Level2 = 2;
|
||||
MyTree.Level1_.Level2_.Level3 = 3;
|
||||
MyTree.Level1_.Level2_.Level3_.Level4 = 4;
|
||||
xml_write('test.xml', MyTree);
|
||||
fprintf('Test xml file:\n');
|
||||
type('test.xml')
|
||||
%%
|
||||
% *Use Default ("Pref.NumLevels = infinity") setting*
|
||||
tree = xml_read('test.xml');
|
||||
gen_object_display(tree);
|
||||
%%
|
||||
% *Limit the read to only 2 levels*
|
||||
Pref=[]; Pref.NumLevels = 2;
|
||||
tree = xml_read('test.xml', Pref);
|
||||
gen_object_display(tree);
|
||||
|
||||
|
||||
|
||||
|
||||
%% Create DOM object based on a Struct using "xml_write"
|
||||
% *Create Struct tree*
|
||||
MyTree=[];
|
||||
MyTree.MyNumber = 13;
|
||||
MyTree.MyString = 'Hello World';
|
||||
%%
|
||||
% *Convert Struct to DOM object using xml_write*
|
||||
DOM = xml_write([], MyTree);
|
||||
xmlwrite('test.xml', DOM); % Save DOM object using MATLAB function
|
||||
type('test.xml')
|
||||
|
||||
%% Convert DOM object to Struct using "xml_read"
|
||||
DOM = xmlread('test.xml'); % Read DOM object using MATLAB function
|
||||
[tree treeName] = xml_read(DOM); % Convert DOM object to Struct
|
||||
disp([treeName{1} ' ='])
|
||||
gen_object_display(tree)
|
||||
|
||||
%% Write XML file based on a DOM using "xml_write_xerces"
|
||||
xmlwrite_xerces('test.xml', DOM); % Save DOM object using Xerces library
|
||||
type('test.xml')
|
||||
|
||||
%% Write XML to string instead of a file
|
||||
DOM = xml_write([], MyTree);
|
||||
str = xmlwrite(DOM);
|
||||
disp(str)
|
||||
|
||||
%% Write XML file with embedded binary data encoded as Base64 (using java version)
|
||||
fid = fopen('football.jpg', 'rb');
|
||||
raw1 = uint8(fread(fid, 'uint8')); % read image file as a raw binary
|
||||
fclose(fid);
|
||||
|
||||
MyTree=[];
|
||||
MyTree.Size = 13;
|
||||
MyTree.MyString = 'Hello World'; % simple case
|
||||
MyTree.MyImage.ATTRIBUTE.EncodingMIMEType = 'base64';
|
||||
MyTree.MyImage.CONTENT = base64encode(raw1,'java');% perform base64 encoding of the binary data
|
||||
xml_write('test.xml', MyTree); % write xml file
|
||||
|
||||
%% Read XML file with embedded binary data encoded as Base64 (using java version)
|
||||
tree = xml_read('test.xml', Pref); % read xml file
|
||||
raw = base64decode(tree.MyImage.CONTENT, '', 'java'); % convert xml image to raw binary
|
||||
fid = fopen('MyFootball.jpg', 'wb');
|
||||
fwrite(fid, raw, 'uint8'); % dumb the raw binary to the hard disk
|
||||
fclose(fid);
|
||||
I = imread('MyFootball.jpg'); % read it as an image
|
||||
imshow(I);
|
||||
|
||||
%% Write XML file with embedded binary data encoded as Base64 (simpler version using only matlab code
|
||||
% Notice that process of writing to xml stripped all end-of-lie characters
|
||||
% from base64 code.
|
||||
isChunked = true; % break into chunks 76 characters long
|
||||
url_safe = true; % 'base64url' encoding
|
||||
code = base64encode('license.txt', 'matlab', isChunked, url_safe);
|
||||
disp(code)
|
||||
MyTree=[];
|
||||
MyTree.Size = 13;
|
||||
MyTree.MyString = 'Hello World';
|
||||
MyTree.MyImage.ATTRIBUTE.EncodingMIMEType = 'base64';
|
||||
MyTree.MyImage.CONTENT = code; % perform base64 encoding of the binary data
|
||||
xml_write('test.xml', MyTree); % write xml file
|
||||
type('test.xml')
|
||||
|
||||
%% Read XML file with embedded binary data encoded as Base64 (simpler version using only matlab code
|
||||
tree = xml_read('test.xml', Pref); % read xml file
|
||||
base64decode(tree.MyImage.CONTENT, 'license2.txt', 'matlab'); % save xml image as raw binary
|
||||
type('license2.txt')
|
|
@ -0,0 +1,447 @@
|
|||
function DOMnode = xml_write(filename, tree, RootName, Pref)
|
||||
%XML_WRITE Writes Matlab data structures to XML file
|
||||
%
|
||||
% DESCRIPTION
|
||||
% xml_write( filename, tree) Converts Matlab data structure 'tree' containing
|
||||
% cells, structs, numbers and strings to Document Object Model (DOM) node
|
||||
% tree, then saves it to XML file 'filename' using Matlab's xmlwrite
|
||||
% function. Optionally one can also use alternative version of xmlwrite
|
||||
% function which directly calls JAVA functions for XML writing without
|
||||
% MATLAB middleware. This function is provided as a patch to existing
|
||||
% bugs in xmlwrite (in R2006b).
|
||||
%
|
||||
% xml_write(filename, tree, RootName, Pref) allows you to specify
|
||||
% additional preferences about file format
|
||||
%
|
||||
% DOMnode = xml_write([], tree) same as above except that DOM node is
|
||||
% not saved to the file but returned.
|
||||
%
|
||||
% INPUT
|
||||
% filename file name
|
||||
% tree Matlab structure tree to store in xml file.
|
||||
% RootName String with XML tag name used for root (top level) node
|
||||
% Optionally it can be a string cell array storing: Name of
|
||||
% root node, document "Processing Instructions" data and
|
||||
% document "comment" string
|
||||
% Pref Other preferences:
|
||||
% Pref.ItemName - default 'item' - name of a special tag used to
|
||||
% itemize cell or struct arrays
|
||||
% Pref.XmlEngine - let you choose the XML engine. Currently default is
|
||||
% 'Xerces', which is using directly the apache xerces java file.
|
||||
% Other option is 'Matlab' which uses MATLAB's xmlwrite and its
|
||||
% XMLUtils java file. Both options create identical results except in
|
||||
% case of CDATA sections where xmlwrite fails.
|
||||
% Pref.CellItem - default 'true' - allow cell arrays to use 'item'
|
||||
% notation. See below.
|
||||
% Pref.RootOnly - default true - output variable 'tree' corresponds to
|
||||
% xml file root element, otherwise it correspond to the whole file.
|
||||
% Pref.StructItem - default 'true' - allow arrays of structs to use
|
||||
% 'item' notation. For example "Pref.StructItem = true" gives:
|
||||
% <a>
|
||||
% <b>
|
||||
% <item> ... <\item>
|
||||
% <item> ... <\item>
|
||||
% <\b>
|
||||
% <\a>
|
||||
% while "Pref.StructItem = false" gives:
|
||||
% <a>
|
||||
% <b> ... <\b>
|
||||
% <b> ... <\b>
|
||||
% <\a>
|
||||
%
|
||||
%
|
||||
% Several special xml node types can be created if special tags are used
|
||||
% for field names of 'tree' nodes:
|
||||
% - node.CONTENT - stores data section of the node if other fields
|
||||
% (usually ATTRIBUTE are present. Usually data section is stored
|
||||
% directly in 'node'.
|
||||
% - node.ATTRIBUTE.name - stores node's attribute called 'name'.
|
||||
% - node.COMMENT - create comment child node from the string. For global
|
||||
% comments see "RootName" input variable.
|
||||
% - node.PROCESSING_INSTRUCTIONS - create "processing instruction" child
|
||||
% node from the string. For global "processing instructions" see
|
||||
% "RootName" input variable.
|
||||
% - node.CDATA_SECTION - stores node's CDATA section (string). Only works
|
||||
% if Pref.XmlEngine='Xerces'. For more info, see comments of F_xmlwrite.
|
||||
% - other special node types like: document fragment nodes, document type
|
||||
% nodes, entity nodes and notation nodes are not being handled by
|
||||
% 'xml_write' at the moment.
|
||||
%
|
||||
% OUTPUT
|
||||
% DOMnode Document Object Model (DOM) node tree in the format
|
||||
% required as input to xmlwrite. (optional)
|
||||
%
|
||||
% EXAMPLES:
|
||||
% MyTree=[];
|
||||
% MyTree.MyNumber = 13;
|
||||
% MyTree.MyString = 'Hello World';
|
||||
% xml_write('test.xml', MyTree);
|
||||
% type('test.xml')
|
||||
% %See also xml_tutorial.m
|
||||
%
|
||||
% See also
|
||||
% xml_read, xmlread, xmlwrite
|
||||
%
|
||||
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
|
||||
|
||||
%% Check Matlab Version
|
||||
v = ver('MATLAB');
|
||||
v = str2double(regexp(v.Version, '\d.\d','match','once'));
|
||||
if (v<7)
|
||||
error('Your MATLAB version is too old. You need version 7.0 or newer.');
|
||||
end
|
||||
|
||||
%% default preferences
|
||||
DPref.TableName = {'tr','td'}; % name of a special tags used to itemize 2D cell arrays
|
||||
DPref.ItemName = 'item'; % name of a special tag used to itemize 1D cell arrays
|
||||
DPref.StructItem = true; % allow arrays of structs to use 'item' notation
|
||||
DPref.CellItem = true; % allow cell arrays to use 'item' notation
|
||||
DPref.StructTable= 'Html';
|
||||
DPref.CellTable = 'Html';
|
||||
DPref.XmlEngine = 'Matlab'; % use matlab provided XMLUtils
|
||||
%DPref.XmlEngine = 'Xerces'; % use Xerces xml generator directly
|
||||
DPref.PreserveSpace = false; % Preserve or delete spaces at the beggining and the end of stings?
|
||||
RootOnly = true; % Input is root node only
|
||||
GlobalProcInst = [];
|
||||
GlobalComment = [];
|
||||
GlobalDocType = [];
|
||||
|
||||
%% read user preferences
|
||||
if (nargin>3)
|
||||
if (isfield(Pref, 'TableName' )), DPref.TableName = Pref.TableName; end
|
||||
if (isfield(Pref, 'ItemName' )), DPref.ItemName = Pref.ItemName; end
|
||||
if (isfield(Pref, 'StructItem')), DPref.StructItem = Pref.StructItem; end
|
||||
if (isfield(Pref, 'CellItem' )), DPref.CellItem = Pref.CellItem; end
|
||||
if (isfield(Pref, 'CellTable')), DPref.CellTable = Pref.CellTable; end
|
||||
if (isfield(Pref, 'StructTable')), DPref.StructTable= Pref.StructTable; end
|
||||
if (isfield(Pref, 'XmlEngine' )), DPref.XmlEngine = Pref.XmlEngine; end
|
||||
if (isfield(Pref, 'RootOnly' )), RootOnly = Pref.RootOnly; end
|
||||
if (isfield(Pref, 'PreserveSpace')), DPref.PreserveSpace = Pref.PreserveSpace; end
|
||||
end
|
||||
if (nargin<3 || isempty(RootName)), RootName=inputname(2); end
|
||||
if (isempty(RootName)), RootName='ROOT'; end
|
||||
if (iscell(RootName)) % RootName also stores global text node data
|
||||
rName = RootName;
|
||||
RootName = char(rName{1});
|
||||
if (length(rName)>1), GlobalProcInst = char(rName{2}); end
|
||||
if (length(rName)>2), GlobalComment = char(rName{3}); end
|
||||
if (length(rName)>3), GlobalDocType = char(rName{4}); end
|
||||
end
|
||||
if(~RootOnly && isstruct(tree)) % if struct than deal with each field separatly
|
||||
fields = fieldnames(tree);
|
||||
for i=1:length(fields)
|
||||
field = fields{i};
|
||||
x = tree(1).(field);
|
||||
if (strcmp(field, 'COMMENT'))
|
||||
GlobalComment = x;
|
||||
elseif (strcmp(field, 'PROCESSING_INSTRUCTION'))
|
||||
GlobalProcInst = x;
|
||||
elseif (strcmp(field, 'DOCUMENT_TYPE'))
|
||||
GlobalDocType = x;
|
||||
else
|
||||
RootName = field;
|
||||
t = x;
|
||||
end
|
||||
end
|
||||
tree = t;
|
||||
end
|
||||
|
||||
%% Initialize jave object that will store xml data structure
|
||||
RootName = varName2str(RootName);
|
||||
if (~isempty(GlobalDocType))
|
||||
% n = strfind(GlobalDocType, ' ');
|
||||
% if (~isempty(n))
|
||||
% dtype = com.mathworks.xml.XMLUtils.createDocumentType(GlobalDocType);
|
||||
% end
|
||||
% DOMnode = com.mathworks.xml.XMLUtils.createDocument(RootName, dtype);
|
||||
warning('xml_io_tools:write:docType', ...
|
||||
'DOCUMENT_TYPE node was encountered which is not supported yet. Ignoring.');
|
||||
end
|
||||
DOMnode = com.mathworks.xml.XMLUtils.createDocument(RootName);
|
||||
|
||||
|
||||
%% Use recursive function to convert matlab data structure to XML
|
||||
root = DOMnode.getDocumentElement;
|
||||
struct2DOMnode(DOMnode, root, tree, DPref.ItemName, DPref);
|
||||
|
||||
%% Remove the only child of the root node
|
||||
root = DOMnode.getDocumentElement;
|
||||
Child = root.getChildNodes; % create array of children nodes
|
||||
nChild = Child.getLength; % number of children
|
||||
if (nChild==1)
|
||||
node = root.removeChild(root.getFirstChild);
|
||||
while(node.hasChildNodes)
|
||||
root.appendChild(node.removeChild(node.getFirstChild));
|
||||
end
|
||||
while(node.hasAttributes) % copy all attributes
|
||||
root.setAttributeNode(node.removeAttributeNode(node.getAttributes.item(0)));
|
||||
end
|
||||
end
|
||||
|
||||
%% Save exotic Global nodes
|
||||
if (~isempty(GlobalComment))
|
||||
DOMnode.insertBefore(DOMnode.createComment(GlobalComment), DOMnode.getFirstChild());
|
||||
end
|
||||
if (~isempty(GlobalProcInst))
|
||||
n = strfind(GlobalProcInst, ' ');
|
||||
if (~isempty(n))
|
||||
proc = DOMnode.createProcessingInstruction(GlobalProcInst(1:(n(1)-1)),...
|
||||
GlobalProcInst((n(1)+1):end));
|
||||
DOMnode.insertBefore(proc, DOMnode.getFirstChild());
|
||||
end
|
||||
end
|
||||
% Not supported yet as the code below does not work
|
||||
% if (~isempty(GlobalDocType))
|
||||
% n = strfind(GlobalDocType, ' ');
|
||||
% if (~isempty(n))
|
||||
% dtype = DOMnode.createDocumentType(GlobalDocType);
|
||||
% DOMnode.insertBefore(dtype, DOMnode.getFirstChild());
|
||||
% end
|
||||
% end
|
||||
|
||||
%% save java DOM tree to XML file
|
||||
if (~isempty(filename))
|
||||
if (strcmpi(DPref.XmlEngine, 'Xerces'))
|
||||
xmlwrite_xerces(filename, DOMnode);
|
||||
else
|
||||
xmlwrite(filename, DOMnode);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
%% =======================================================================
|
||||
% === struct2DOMnode Function ===========================================
|
||||
% =======================================================================
|
||||
function [] = struct2DOMnode(xml, parent, s, TagName, Pref)
|
||||
% struct2DOMnode is a recursive function that converts matlab's structs to
|
||||
% DOM nodes.
|
||||
% INPUTS:
|
||||
% xml - jave object that will store xml data structure
|
||||
% parent - parent DOM Element
|
||||
% s - Matlab data structure to save
|
||||
% TagName - name to be used in xml tags describing 's'
|
||||
% Pref - preferenced
|
||||
% OUTPUT:
|
||||
% parent - modified 'parent'
|
||||
|
||||
% perform some conversions
|
||||
if (ischar(s) && min(size(s))>1) % if 2D array of characters
|
||||
s=cellstr(s); % than convert to cell array
|
||||
end
|
||||
% if (strcmp(TagName, 'CONTENT'))
|
||||
% while (iscell(s) && length(s)==1), s = s{1}; end % unwrap cell arrays of length 1
|
||||
% end
|
||||
TagName = varName2str(TagName);
|
||||
|
||||
%% == node is a 2D cell array ==
|
||||
% convert to some other format prior to further processing
|
||||
nDim = nnz(size(s)>1); % is it a scalar, vector, 2D array, 3D cube, etc?
|
||||
if (iscell(s) && nDim==2 && strcmpi(Pref.CellTable, 'Matlab'))
|
||||
s = var2str(s, Pref.PreserveSpace);
|
||||
end
|
||||
if (nDim==2 && (iscell (s) && strcmpi(Pref.CellTable, 'Vector')) || ...
|
||||
(isstruct(s) && strcmpi(Pref.StructTable, 'Vector')))
|
||||
s = s(:);
|
||||
end
|
||||
if (nDim>2), s = s(:); end % can not handle this case well
|
||||
nItem = numel(s);
|
||||
nDim = nnz(size(s)>1); % is it a scalar, vector, 2D array, 3D cube, etc?
|
||||
|
||||
%% == node is a cell ==
|
||||
if (iscell(s)) % if this is a cell or cell array
|
||||
if ((nDim==2 && strcmpi(Pref.CellTable,'Html')) || (nDim< 2 && Pref.CellItem))
|
||||
% if 2D array of cells than can use HTML-like notation or if 1D array
|
||||
% than can use item notation
|
||||
if (strcmp(TagName, 'CONTENT')) % CONTENT nodes already have <TagName> ... </TagName>
|
||||
array2DOMnode(xml, parent, s, Pref.ItemName, Pref ); % recursive call
|
||||
else
|
||||
node = xml.createElement(TagName); % <TagName> ... </TagName>
|
||||
array2DOMnode(xml, node, s, Pref.ItemName, Pref ); % recursive call
|
||||
parent.appendChild(node);
|
||||
end
|
||||
else % use <TagName>...<\TagName> <TagName>...<\TagName> notation
|
||||
array2DOMnode(xml, parent, s, TagName, Pref ); % recursive call
|
||||
end
|
||||
%% == node is a struct ==
|
||||
elseif (isstruct(s)) % if struct than deal with each field separatly
|
||||
if ((nDim==2 && strcmpi(Pref.StructTable,'Html')) || (nItem>1 && Pref.StructItem))
|
||||
% if 2D array of structs than can use HTML-like notation or
|
||||
% if 1D array of structs than can use 'items' notation
|
||||
node = xml.createElement(TagName);
|
||||
array2DOMnode(xml, node, s, Pref.ItemName, Pref ); % recursive call
|
||||
parent.appendChild(node);
|
||||
elseif (nItem>1) % use <TagName>...<\TagName> <TagName>...<\TagName> notation
|
||||
array2DOMnode(xml, parent, s, TagName, Pref ); % recursive call
|
||||
else % otherwise save each struct separatelly
|
||||
fields = fieldnames(s);
|
||||
node = xml.createElement(TagName);
|
||||
for i=1:length(fields) % add field by field to the node
|
||||
field = fields{i};
|
||||
x = s.(field);
|
||||
switch field
|
||||
case {'COMMENT', 'CDATA_SECTION', 'PROCESSING_INSTRUCTION'}
|
||||
if iscellstr(x) % cell array of strings -> add them one by one
|
||||
array2DOMnode(xml, node, x(:), field, Pref ); % recursive call will modify 'node'
|
||||
elseif ischar(x) % single string -> add it
|
||||
struct2DOMnode(xml, node, x, field, Pref ); % recursive call will modify 'node'
|
||||
else % not a string - Ignore
|
||||
warning('xml_io_tools:write:badSpecialNode', ...
|
||||
['Struct field named ',field,' encountered which was not a string. Ignoring.']);
|
||||
end
|
||||
case 'ATTRIBUTE' % set attributes of the node
|
||||
if (isempty(x)), continue; end
|
||||
if (isstruct(x))
|
||||
attName = fieldnames(x); % get names of all the attributes
|
||||
for k=1:length(attName) % attach them to the node
|
||||
att = xml.createAttribute(varName2str(attName(k)));
|
||||
att.setValue(var2str(x.(attName{k}),Pref.PreserveSpace));
|
||||
node.setAttributeNode(att);
|
||||
end
|
||||
else
|
||||
warning('xml_io_tools:write:badAttribute', ...
|
||||
'Struct field named ATTRIBUTE encountered which was not a struct. Ignoring.');
|
||||
end
|
||||
otherwise % set children of the node
|
||||
struct2DOMnode(xml, node, x, field, Pref ); % recursive call will modify 'node'
|
||||
end
|
||||
end % end for i=1:nFields
|
||||
parent.appendChild(node);
|
||||
end
|
||||
%% == node is a leaf node ==
|
||||
else % if not a struct and not a cell than it is a leaf node
|
||||
switch TagName % different processing depending on desired type of the node
|
||||
case 'COMMENT' % create comment node
|
||||
com = xml.createComment(s);
|
||||
parent.appendChild(com);
|
||||
case 'CDATA_SECTION' % create CDATA Section
|
||||
cdt = xml.createCDATASection(s);
|
||||
parent.appendChild(cdt);
|
||||
case 'PROCESSING_INSTRUCTION' % set attributes of the node
|
||||
OK = false;
|
||||
if (ischar(s))
|
||||
n = strfind(s, ' ');
|
||||
if (~isempty(n))
|
||||
proc = xml.createProcessingInstruction(s(1:(n(1)-1)),s((n(1)+1):end));
|
||||
parent.insertBefore(proc, parent.getFirstChild());
|
||||
OK = true;
|
||||
end
|
||||
end
|
||||
if (~OK)
|
||||
warning('xml_io_tools:write:badProcInst', ...
|
||||
['Struct field named PROCESSING_INSTRUCTION need to be',...
|
||||
' a string, for example: xml-stylesheet type="text/css" ', ...
|
||||
'href="myStyleSheet.css". Ignoring.']);
|
||||
end
|
||||
case 'CONTENT' % this is text part of already existing node
|
||||
txt = xml.createTextNode(var2str(s, Pref.PreserveSpace)); % convert to text
|
||||
parent.appendChild(txt);
|
||||
otherwise % I guess it is a regular text leaf node
|
||||
txt = xml.createTextNode(var2str(s, Pref.PreserveSpace));
|
||||
node = xml.createElement(TagName);
|
||||
node.appendChild(txt);
|
||||
parent.appendChild(node);
|
||||
end
|
||||
end % of struct2DOMnode function
|
||||
|
||||
%% =======================================================================
|
||||
% === array2DOMnode Function ============================================
|
||||
% =======================================================================
|
||||
function [] = array2DOMnode(xml, parent, s, TagName, Pref)
|
||||
% Deal with 1D and 2D arrays of cell or struct. Will modify 'parent'.
|
||||
nDim = nnz(size(s)>1); % is it a scalar, vector, 2D array, 3D cube, etc?
|
||||
switch nDim
|
||||
case 2 % 2D array
|
||||
for r=1:size(s,1)
|
||||
subnode = xml.createElement(Pref.TableName{1});
|
||||
for c=1:size(s,2)
|
||||
v = s(r,c);
|
||||
if iscell(v), v = v{1}; end
|
||||
struct2DOMnode(xml, subnode, v, Pref.TableName{2}, Pref ); % recursive call
|
||||
end
|
||||
parent.appendChild(subnode);
|
||||
end
|
||||
case 1 %1D array
|
||||
for iItem=1:numel(s)
|
||||
v = s(iItem);
|
||||
if iscell(v), v = v{1}; end
|
||||
struct2DOMnode(xml, parent, v, TagName, Pref ); % recursive call
|
||||
end
|
||||
case 0 % scalar -> this case should never be called
|
||||
if ~isempty(s)
|
||||
if iscell(s), s = s{1}; end
|
||||
struct2DOMnode(xml, parent, s, TagName, Pref );
|
||||
end
|
||||
end
|
||||
|
||||
%% =======================================================================
|
||||
% === var2str Function ==================================================
|
||||
% =======================================================================
|
||||
function str = var2str(object, PreserveSpace)
|
||||
% convert matlab variables to a string
|
||||
switch (1)
|
||||
case isempty(object)
|
||||
str = '';
|
||||
case (isnumeric(object) || islogical(object))
|
||||
if ndims(object)>2, object=object(:); end % can't handle arrays with dimention > 2
|
||||
str=mat2str(object); % convert matrix to a string
|
||||
% mark logical scalars with [] (logical arrays already have them) so the xml_read
|
||||
% recognizes them as MATLAB objects instead of strings. Same with sparse
|
||||
% matrices
|
||||
if ((islogical(object) && isscalar(object)) || issparse(object)),
|
||||
str = ['[' str ']'];
|
||||
end
|
||||
if (isinteger(object)),
|
||||
str = ['[', class(object), '(', str ')]'];
|
||||
end
|
||||
case iscell(object)
|
||||
if ndims(object)>2, object=object(:); end % can't handle cell arrays with dimention > 2
|
||||
[nr nc] = size(object);
|
||||
obj2 = object;
|
||||
for i=1:length(object(:))
|
||||
str = var2str(object{i}, PreserveSpace);
|
||||
if (ischar(object{i})), object{i} = ['''' object{i} '''']; else object{i}=str; end
|
||||
obj2{i} = [object{i} ','];
|
||||
end
|
||||
for r = 1:nr, obj2{r,nc} = [object{r,nc} ';']; end
|
||||
obj2 = obj2.';
|
||||
str = ['{' obj2{:} '}'];
|
||||
case isstruct(object)
|
||||
str='';
|
||||
warning('xml_io_tools:write:var2str', ...
|
||||
'Struct was encountered where string was expected. Ignoring.');
|
||||
case isa(object, 'function_handle')
|
||||
str = ['[@' char(object) ']'];
|
||||
case ischar(object)
|
||||
str = object;
|
||||
otherwise
|
||||
str = char(object);
|
||||
end
|
||||
|
||||
%% string clean-up
|
||||
str=str(:); str=str.'; % make sure this is a row vector of char's
|
||||
if (~isempty(str))
|
||||
str(str<32|str==127)=' '; % convert no-printable characters to spaces
|
||||
if (~PreserveSpace)
|
||||
str = strtrim(str); % remove spaces from begining and the end
|
||||
str = regexprep(str,'\s+',' '); % remove multiple spaces
|
||||
end
|
||||
end
|
||||
|
||||
%% =======================================================================
|
||||
% === var2Namestr Function ==============================================
|
||||
% =======================================================================
|
||||
function str = varName2str(str)
|
||||
% convert matlab variable names to a sting
|
||||
str = char(str);
|
||||
p = strfind(str,'0x');
|
||||
if (~isempty(p))
|
||||
for i=1:length(p)
|
||||
before = str( p(i)+(0:3) ); % string to replace
|
||||
after = char(hex2dec(before(3:4))); % string to replace with
|
||||
str = regexprep(str,before,after, 'once', 'ignorecase');
|
||||
p=p-3; % since 4 characters were replaced with one - compensate
|
||||
end
|
||||
end
|
||||
str = regexprep(str,'_COLON_',':', 'once', 'ignorecase');
|
||||
str = regexprep(str,'_DASH_' ,'-', 'once', 'ignorecase');
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
function varargout=xmlwrite_xerces(varargin)
|
||||
%XMLWRITE_XERCES Serialize an XML Document Object Model node using Xerces parser.
|
||||
% xmlwrite_xerces(FILENAME,DOMNODE) serializes the DOMNODE to file FILENAME.
|
||||
%
|
||||
% The function xmlwrite_xerces is very similar the Matlab function xmlwrite
|
||||
% but works directly with the XERCES java classes (written by Apache XML
|
||||
% Project) instead of the XMLUtils class created by Mathworks. Xerces files
|
||||
% are provided in standard MATLAB instalation and live in root\java\jarext
|
||||
% directory.
|
||||
%
|
||||
% Written by A.Amaro (02-22-2007) and generously donated to xml_io_tools.
|
||||
% This function is needed as a work-around for a bug in XMLUtils library
|
||||
% which can not write CDATA SECTION nodes correctly. Also Xerces and
|
||||
% XMLUtils libraries handle namespaces differently.
|
||||
%
|
||||
% Examples:
|
||||
% % See xmlwrite examples this function have almost identical behavior.
|
||||
%
|
||||
% Advanced use:
|
||||
% FILENAME can also be a URN, java.io.OutputStream or java.io.Writer object
|
||||
% SOURCE can also be a SAX InputSource, JAXP Source, InputStream, or
|
||||
% Reader object
|
||||
|
||||
returnString = false;
|
||||
if length(varargin)==1
|
||||
returnString = true;
|
||||
result = java.io.StringWriter;
|
||||
source = varargin{1};
|
||||
else
|
||||
result = varargin{1};
|
||||
if ischar(result)
|
||||
% Using the XERCES classes directly, is not needed to modify the
|
||||
% filename string. So I have commented this next line
|
||||
% result = F_xmlstringinput(result,false);
|
||||
end
|
||||
|
||||
source = varargin{2};
|
||||
if ischar(source)
|
||||
source = F_xmlstringinput(source,true);
|
||||
end
|
||||
end
|
||||
|
||||
% SERIALIZATION OF THE DOM DOCUMENT USING XERCES CLASSES DIRECTLY
|
||||
|
||||
% 1) create the output format according to the document definitions
|
||||
% and type
|
||||
objOutputFormat = org.apache.xml.serialize.OutputFormat(source);
|
||||
set(objOutputFormat,'Indenting','on');
|
||||
|
||||
% 2) create the output stream. In this case: an XML file
|
||||
objFile = java.io.File(result);
|
||||
objOutputStream = java.io.FileOutputStream(objFile);
|
||||
|
||||
% 3) Create the Xerces Serializer object
|
||||
objSerializer= org.apache.xml.serialize.XMLSerializer(objOutputStream,objOutputFormat);
|
||||
|
||||
% 4) Serialize to the XML files
|
||||
javaMethod('serialize',objSerializer,source);
|
||||
|
||||
% 5) IMPORTANT! Delete the objects to liberate the XML file created
|
||||
objOutputStream.close;
|
||||
|
||||
if returnString
|
||||
varargout{1}=char(result.toString);
|
||||
end
|
||||
|
||||
%% ========================================================================
|
||||
function out = F_xmlstringinput(xString,isFullSearch,varargin)
|
||||
% The function F_xmlstringinput is a copy of the private function:
|
||||
% 'xmlstringinput' that the original xmlwrite function uses.
|
||||
|
||||
if isempty(xString)
|
||||
error('Filename is empty');
|
||||
elseif ~isempty(findstr(xString,'://'))
|
||||
%xString is already a URL, most likely prefaced by file:// or http://
|
||||
out = xString;
|
||||
return;
|
||||
end
|
||||
|
||||
xPath=fileparts(xString);
|
||||
if isempty(xPath)
|
||||
if nargin<2 || isFullSearch
|
||||
out = which(xString);
|
||||
if isempty(out)
|
||||
error('xml:FileNotFound','File %s not found',xString);
|
||||
end
|
||||
else
|
||||
out = fullfile(pwd,xString);
|
||||
end
|
||||
else
|
||||
out = xString;
|
||||
if (nargin<2 || isFullSearch) && ~exist(xString,'file')
|
||||
%search to see if xString exists when isFullSearch
|
||||
error('xml:FileNotFound','File %s not found',xString);
|
||||
end
|
||||
end
|
||||
|
||||
%Return as a URN
|
||||
if strncmp(out,'\\',2)
|
||||
% SAXON UNC filepaths need to look like file:///\\\server-name\
|
||||
out = ['file:///\',out];
|
||||
elseif strncmp(out,'/',1)
|
||||
% SAXON UNIX filepaths need to look like file:///root/dir/dir
|
||||
out = ['file://',out];
|
||||
else
|
||||
% DOS filepaths need to look like file:///d:/foo/bar
|
||||
out = ['file:///',strrep(out,'\','/')];
|
||||
end
|
||||
|
|
@ -1,6 +1,17 @@
|
|||
clear
|
||||
DISFA_dir = 'D:/Datasets/DISFA/Videos_LeftCamera/';
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
|
||||
if(exist('D:/Datasets/DISFA/Videos_LeftCamera/', 'file'))
|
||||
DISFA_dir = 'D:/Datasets/DISFA/Videos_LeftCamera/';
|
||||
else
|
||||
DISFA_dir = '/multicomp/datasets/face_datasets/DISFA/Videos_LeftCamera/';
|
||||
end
|
||||
|
||||
|
||||
videos = dir([DISFA_dir, '*.avi']);
|
||||
|
||||
|
@ -22,7 +33,11 @@ parfor v = 1:numel(videos)
|
|||
output_file = [output name '_au.txt'];
|
||||
command = [executable ' -f "' vid_file '" -of "' output_file '" -q -no2Dfp -no3Dfp -noMparams -noPose -noGaze'];
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command, '-echo');
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
@ -31,8 +46,7 @@ end
|
|||
% Note that DISFA was used in training, this is not meant for experimental
|
||||
% results but rather to show how to do AU prediction and how to interpret
|
||||
% the results
|
||||
|
||||
Label_dir = 'D:/Datasets/DISFA/ActionUnit_Labels/';
|
||||
Label_dir = [DISFA_dir, '/../ActionUnit_Labels/'];
|
||||
prediction_dir = 'out_DISFA/';
|
||||
|
||||
label_folders = dir([Label_dir, 'SN*']);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
clear
|
||||
|
||||
fera_loc = 'D:\Datasets\fera\';
|
||||
addpath(genpath('helpers/'));
|
||||
find_FERA2011;
|
||||
|
||||
out_loc = './out_fera/';
|
||||
|
||||
|
@ -9,41 +10,38 @@ if(~exist(out_loc, 'dir'))
|
|||
end
|
||||
|
||||
%%
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
|
||||
fera_dirs = dir([fera_loc, 'au_train*']);
|
||||
fera_dirs = dir([FERA2011_dir, 'train*']);
|
||||
|
||||
for f1=1:numel(fera_dirs)
|
||||
parfor f1=1:numel(fera_dirs)
|
||||
|
||||
fera_dirs_level_2 = dir([fera_loc, fera_dirs(f1).name]);
|
||||
fera_dirs_level_2 = fera_dirs_level_2(3:end);
|
||||
|
||||
parfor f2=1:numel(fera_dirs_level_2)
|
||||
vid_files = dir([FERA2011_dir, fera_dirs(f1).name, '/*.avi']);
|
||||
|
||||
vid_files = dir([fera_loc, fera_dirs(f1).name, '/', fera_dirs_level_2(f2).name, '/*.avi']);
|
||||
|
||||
for v=1:numel(vid_files)
|
||||
for v=1:numel(vid_files)
|
||||
|
||||
command = [executable ' -asvid -q -no2Dfp -no3Dfp -noMparams -noPose -noGaze -au_static '];
|
||||
command = [executable ' -asvid -q -no2Dfp -no3Dfp -noMparams -noPose -noGaze -au_static '];
|
||||
|
||||
curr_vid = [fera_loc, fera_dirs(f1).name, '/', fera_dirs_level_2(f2).name, '/', vid_files(v).name];
|
||||
curr_vid = [FERA2011_dir, fera_dirs(f1).name, '/', vid_files(v).name];
|
||||
|
||||
[~,name,~] = fileparts(curr_vid);
|
||||
output_file = [out_loc name '.au.txt'];
|
||||
|
||||
command = cat(2, command, [' -f "' curr_vid '" -of "' output_file '"']);
|
||||
[~,name,~] = fileparts(curr_vid);
|
||||
output_file = [out_loc name '.au.txt'];
|
||||
|
||||
command = cat(2, command, [' -f "' curr_vid '" -of "' output_file '"']);
|
||||
|
||||
if(isunix)
|
||||
unix(command, '-echo');
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
%%
|
||||
addpath('./helpers/');
|
||||
|
||||
find_FERA2011;
|
||||
|
||||
[ labels_gt, valid_ids, filenames] = extract_FERA2011_labels(FERA2011_dir, all_recs, all_aus);
|
||||
labels_gt = cat(1, labels_gt{:});
|
||||
|
||||
|
|
|
@ -9,7 +9,11 @@ if(~exist(out_loc, 'dir'))
|
|||
mkdir(out_loc);
|
||||
end
|
||||
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
%%
|
||||
parfor f1=1:numel(devel_recs)
|
||||
|
||||
|
@ -27,8 +31,13 @@ parfor f1=1:numel(devel_recs)
|
|||
name = f1_dir;
|
||||
output_aus = [out_loc name '.au.txt'];
|
||||
|
||||
command = cat(2, command, [' -f "' curr_vid '" -of "' output_aus]);
|
||||
dos(command);
|
||||
command = cat(2, command, [' -f "' curr_vid '" -of "' output_aus, '"']);
|
||||
|
||||
if(isunix)
|
||||
unix(command, '-echo');
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
clear
|
||||
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
|
||||
output = './output_features_seq/';
|
||||
|
||||
|
@ -29,11 +35,15 @@ for i=1:numel(in_dirs)
|
|||
|
||||
command = cat(2, command, ['-asvid -fdir "' in_dirs{i} '" -of "' outputFile '" ']);
|
||||
|
||||
command = cat(2, command, [' -simalign "' outputDir_aligned '" -hogalign "' outputHOG_aligned '"']);
|
||||
command = cat(2, command, [' -simalign "' outputDir_aligned '" -simsize 200 -hogalign "' outputHOG_aligned '"']);
|
||||
|
||||
end
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command);
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
|
||||
%% Demonstrating reading the output files
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
clear
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
|
||||
output = './output_features_vid/';
|
||||
|
||||
|
@ -40,7 +45,11 @@ for i=1:numel(in_files)
|
|||
|
||||
end
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command);
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
|
||||
%% Demonstrating reading the output files
|
||||
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
exe = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
clear
|
||||
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
|
||||
output = './output_features_vid/';
|
||||
|
||||
|
@ -10,7 +16,7 @@ in_files = dir('../../videos/2015-10-15-15-14.avi');
|
|||
% some parameters
|
||||
verbose = true;
|
||||
|
||||
command = exe;
|
||||
command = executable;
|
||||
command = cat(2, command, ' -verbose -no2Dfp -no3Dfp -noMparams -noPose -noAUs ');
|
||||
|
||||
% add all videos to single argument list (so as not to load the model anew
|
||||
|
@ -31,7 +37,11 @@ for i=1:numel(in_files)
|
|||
|
||||
end
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command);
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
|
||||
%% Demonstrating reading the output files
|
||||
filename = [output name];
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
clear
|
||||
|
||||
executable = '"../../x64/Release/FaceLandmarkImg.exe"';
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FaceLandmarkImg"';
|
||||
else
|
||||
executable = '"../../x64/Release/FaceLandmarkImg.exe"';
|
||||
end
|
||||
|
||||
in_dir = '../../videos/';
|
||||
out_dir = './demo_img/';
|
||||
|
@ -38,4 +41,8 @@ command = cat(2, command, [' -mloc "', model, '"']);
|
|||
% Comment to skip this functionality
|
||||
command = cat(2, command, ' -wild ');
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command);
|
||||
else
|
||||
dos(command);
|
||||
end
|
|
@ -1,4 +1,10 @@
|
|||
executable = '"../../x64/Release/FaceLandmarkVidMulti.exe"';
|
||||
clear;
|
||||
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FaceLandmarkVidMulti"';
|
||||
else
|
||||
executable = '"../../x64/Release/FaceLandmarkVidMulti.exe"';
|
||||
end
|
||||
|
||||
output = './demo_vid/';
|
||||
|
||||
|
@ -38,4 +44,8 @@ for i=1:numel(in_files)
|
|||
|
||||
end
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command);
|
||||
else
|
||||
dos(command);
|
||||
end
|
|
@ -1,4 +1,10 @@
|
|||
executable = '"../../x64/Release/FaceLandmarkVid.exe"';
|
||||
clear
|
||||
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FaceLandmarkVid"';
|
||||
else
|
||||
executable = '"../../x64/Release/FaceLandmarkVid.exe"';
|
||||
end
|
||||
|
||||
output = './demo_vid/';
|
||||
|
||||
|
@ -39,4 +45,8 @@ for i=1:numel(in_files)
|
|||
|
||||
end
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command);
|
||||
else
|
||||
dos(command);
|
||||
end
|
|
@ -1,6 +1,4 @@
|
|||
function [ err_outline, err_no_outline ] = Run_CLM_fitting_on_images(output_loc, database_root, varargin)
|
||||
%RUN_CLM_FITTING_ON_IMAGES Summary of this function goes here
|
||||
% Detailed explanation goes here
|
||||
function [ err_outline, err_no_outline ] = Run_OF_on_images(output_loc, database_root, varargin)
|
||||
|
||||
dataset_dirs = {};
|
||||
|
||||
|
@ -27,8 +25,12 @@ else
|
|||
verbose = false;
|
||||
end
|
||||
|
||||
command = '"../../x64/Release/FaceLandmarkImg.exe" ';
|
||||
|
||||
if(isunix)
|
||||
command = '"../../build/bin/FaceLandmarkImg"';
|
||||
else
|
||||
command = '"../../x64/Release/FaceLandmarkImg.exe"';
|
||||
end
|
||||
|
||||
if(any(strcmp(varargin, 'model')))
|
||||
model = varargin{find(strcmp(varargin, 'model')) + 1};
|
||||
else
|
||||
|
@ -61,7 +63,11 @@ parfor i=1:numel(dataset_dirs)
|
|||
|
||||
command_c = cat(2, command_c, ' -wild ');
|
||||
|
||||
dos(command_c);
|
||||
if(isunix)
|
||||
unix(command_c, '-echo');
|
||||
else
|
||||
dos(command_c);
|
||||
end
|
||||
|
||||
end
|
||||
toc
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -5,8 +5,10 @@ curr_dir = cd('.');
|
|||
% Replace this with your downloaded 300-W train data
|
||||
if(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
|
||||
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
|
||||
else
|
||||
elseif(exist('D:/Dropbox/Dropbox/AAM/test data/', 'file'))
|
||||
database_root = 'D:/Dropbox/Dropbox/AAM/test data/';
|
||||
else
|
||||
database_root = '/multicomp/datasets/300-W/';
|
||||
end
|
||||
|
||||
%% Run using CLNF in the wild model
|
||||
|
@ -15,7 +17,7 @@ if(~exist(out_clnf, 'file'))
|
|||
mkdir(out_clnf);
|
||||
end
|
||||
|
||||
[err_clnf_wild, err_no_out_clnf_wild] = Run_CLM_fitting_on_images(out_clnf, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clnf_wild.txt', 'multi_view', 1);
|
||||
[err_clnf_wild, err_no_out_clnf_wild] = Run_OF_on_images(out_clnf, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clnf_wild.txt', 'multi_view', 1);
|
||||
|
||||
%% Run using SVR model
|
||||
out_svr = [curr_dir '/out_wild_svr_wild/'];
|
||||
|
@ -23,7 +25,7 @@ if(~exist(out_svr, 'file'))
|
|||
mkdir(out_svr);
|
||||
end
|
||||
|
||||
[err_svr_wild, err_no_out_svr_wild] = Run_CLM_fitting_on_images(out_svr, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clm_wild.txt', 'multi_view', 1);
|
||||
[err_svr_wild, err_no_out_svr_wild] = Run_OF_on_images(out_svr, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clm_wild.txt', 'multi_view', 1);
|
||||
|
||||
%% Run using general CLNF model
|
||||
out_clnf = [curr_dir '/out_wild_clnf/'];
|
||||
|
@ -31,7 +33,7 @@ if(~exist(out_clnf, 'file'))
|
|||
mkdir(out_clnf);
|
||||
end
|
||||
|
||||
[err_clnf, err_no_out_clnf] = Run_CLM_fitting_on_images(out_clnf, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clnf_general.txt', 'multi_view', 1);
|
||||
[err_clnf, err_no_out_clnf] = Run_OF_on_images(out_clnf, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clnf_general.txt', 'multi_view', 1);
|
||||
|
||||
%% Run using SVR model
|
||||
out_svr = [curr_dir '/out_wild_svr/'];
|
||||
|
@ -39,7 +41,7 @@ if(~exist(out_svr, 'file'))
|
|||
mkdir(out_svr);
|
||||
end
|
||||
|
||||
[err_svr, err_no_out_svr] = Run_CLM_fitting_on_images(out_svr, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clm_general.txt', 'multi_view', 1);
|
||||
[err_svr, err_no_out_svr] = Run_OF_on_images(out_svr, database_root, 'use_afw', 'use_lfpw', 'use_ibug', 'use_helen', 'verbose', 'model', 'model/main_clm_general.txt', 'multi_view', 1);
|
||||
|
||||
%%
|
||||
save('results/landmark_detections.mat');
|
|
@ -1,6 +1,10 @@
|
|||
clear
|
||||
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
|
||||
output = 'yt_features/';
|
||||
|
||||
|
@ -10,8 +14,10 @@ end
|
|||
|
||||
if(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
|
||||
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
|
||||
else
|
||||
elseif(exist('D:/Dropbox/Dropbox/AAM/test data/', 'file'))
|
||||
database_root = 'D:/Dropbox/Dropbox/AAM/test data/';
|
||||
else
|
||||
database_root = '/multicomp/datasets/';
|
||||
end
|
||||
|
||||
database_root = [database_root, '/ytceleb/'];
|
||||
|
@ -33,7 +39,11 @@ for i=1:numel(in_vids)
|
|||
command = cat(2, command, [' -f "' in_file_name '" -of "' outputFile_fp '"']);
|
||||
end
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command, '-echo')
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
|
||||
%%
|
||||
output = 'yt_features_clm/';
|
||||
|
@ -59,7 +69,11 @@ for i=1:numel(in_vids)
|
|||
command = cat(2, command, [' -f "' in_file_name '" -of "' outputFile_fp '"']);
|
||||
end
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command, '-echo')
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
%% evaluating yt datasets
|
||||
d_loc = 'yt_features/';
|
||||
d_loc_clm = 'yt_features_clm/';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
% This is sort of the unit test for the whole module (needs datasets)
|
||||
% Will take over an hour to run all
|
||||
|
||||
% Will take several hours to run all
|
||||
clear
|
||||
tic
|
||||
%% Head pose
|
||||
cd('Head Pose Experiments');
|
||||
|
@ -12,7 +12,7 @@ cd('../');
|
|||
|
||||
%% Features
|
||||
cd('Feature Point Experiments');
|
||||
run_clm_feature_point_tests_wild;
|
||||
run_OpenFace_feature_point_tests_300W;
|
||||
assert(median(err_clnf) < 0.041);
|
||||
assert(median(err_clnf_wild) < 0.041);
|
||||
run_yt_dataset;
|
||||
|
|
|
@ -7,9 +7,12 @@ if(exist([getenv('USERPROFILE') '/Dropbox/AAM/eye_clm/mpii_data/'], 'file'))
|
|||
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/eye_clm/mpii_data/'];
|
||||
elseif(exist('D:\Dropbox/Dropbox/AAM/eye_clm/mpii_data/', 'file'))
|
||||
database_root = 'D:\Dropbox/Dropbox/AAM/eye_clm/mpii_data/';
|
||||
elseif(exist('/multicomp/datasets/mpii_gaze/mpii_data/', 'file'))
|
||||
database_root = '/multicomp/datasets/mpii_gaze/mpii_data/';
|
||||
else
|
||||
fprintf('MPII gaze dataset not found\n');
|
||||
end
|
||||
|
||||
output_loc = './gaze_estimates_MPII/';
|
||||
if(~exist(output_loc, 'dir'))
|
||||
mkdir(output_loc);
|
||||
|
@ -18,7 +21,13 @@ end
|
|||
output = './mpii_out/';
|
||||
|
||||
%% Perform actual gaze predictions
|
||||
command = sprintf('"../../x64/Release/FaceLandmarkImg.exe" -fx 1028 -fy 1028 -gaze ');
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FaceLandmarkImg"';
|
||||
else
|
||||
executable = '"../../x64/Release/FaceLandmarkImg.exe"';
|
||||
end
|
||||
|
||||
command = sprintf('%s -fx 1028 -fy 1028 -gaze ', executable);
|
||||
p_dirs = dir([database_root, 'p*']);
|
||||
|
||||
parfor p=1:numel(p_dirs)
|
||||
|
@ -30,7 +39,11 @@ parfor p=1:numel(p_dirs)
|
|||
command_c = cat(2, command, input_loc, out_img_loc, out_p_loc);
|
||||
|
||||
command_c = cat(2, command_c, ' -wild');
|
||||
dos(command_c);
|
||||
if(isunix)
|
||||
unix(command_c, '-echo');
|
||||
else
|
||||
dos(command_c);
|
||||
end;
|
||||
|
||||
end
|
||||
%%
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
Dataset and model, pitch, yaw, roll, mean, median
|
||||
biwi error: 7.955, 5.583, 4.403, 5.980, 2.624
|
||||
bu error: 2.734, 3.350, 2.459, 2.848, 1.974
|
||||
ict error: 3.610, 3.959, 3.369, 3.646, 1.967
|
||||
biwi error: 7.955, 5.583, 4.402, 5.980, 2.624
|
||||
bu error: 2.762, 4.103, 2.568, 3.145, 2.118
|
||||
ict error: 3.620, 3.608, 3.626, 3.618, 2.028
|
||||
|
|
|
@ -1,30 +1,25 @@
|
|||
function [fps, resDir] = run_biwi_experiment(rootDir, biwiDir, outputDir, verbose, depth, version, varargin)
|
||||
function [output_dir] = run_biwi_experiment(rootDir, biwiDir, verbose, depth, varargin)
|
||||
% Biwi dataset experiment
|
||||
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
|
||||
output = 'Tracker_';
|
||||
output_dir = 'experiments/biwi_out';
|
||||
|
||||
dbSeqDir = dir([rootDir biwiDir]);
|
||||
|
||||
% listing the output based on the current revision
|
||||
output = [output 'r' num2str(version)];
|
||||
|
||||
if(depth)
|
||||
output = cat(2, output, '_depth');
|
||||
output_dir = cat(2, output_dir, '_depth');
|
||||
end
|
||||
|
||||
outputDir = cat(2, outputDir, ['/' output '/']);
|
||||
|
||||
if(~exist([outputDir], 'dir'))
|
||||
mkdir([outputDir]);
|
||||
end
|
||||
output_dir = cat(2, output_dir, '/');
|
||||
|
||||
offset = 0;
|
||||
|
||||
r = 1 + offset;
|
||||
|
||||
tic;
|
||||
|
||||
numTogether = 25;
|
||||
|
||||
|
@ -34,7 +29,7 @@ for i=3 + offset:numTogether:numel(dbSeqDir)
|
|||
|
||||
command = executable;
|
||||
|
||||
command = cat(2, command, [' -root ' '"' rootDir '"']);
|
||||
command = cat(2, command, [' -inroot ' '"' rootDir '"']);
|
||||
|
||||
% deal with edge cases
|
||||
if(numTogether + i > numel(dbSeqDir))
|
||||
|
@ -44,7 +39,7 @@ for i=3 + offset:numTogether:numel(dbSeqDir)
|
|||
for n=0:numTogether-1
|
||||
|
||||
inputFile = [biwiDir dbSeqDir(i+n).name '/colour.avi'];
|
||||
outputFile = [outputDir dbSeqDir(i+n).name '.txt'];
|
||||
outputFile = [output_dir dbSeqDir(i+n).name '.txt'];
|
||||
|
||||
command = cat(2, command, [' -f "' inputFile '" -of "' outputFile '"']);
|
||||
|
||||
|
@ -54,7 +49,7 @@ for i=3 + offset:numTogether:numel(dbSeqDir)
|
|||
end
|
||||
|
||||
if(verbose)
|
||||
outputVideo = [outputDir dbSeqDir(i).name '.avi'];
|
||||
outputVideo = [output_dir dbSeqDir(i).name '.avi'];
|
||||
command = cat(2, command, [' -ov "' outputVideo '"']);
|
||||
end
|
||||
end
|
||||
|
@ -65,9 +60,9 @@ for i=3 + offset:numTogether:numel(dbSeqDir)
|
|||
end
|
||||
|
||||
r = r+1;
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command, '-echo')
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
end
|
||||
|
||||
timeTaken = toc;
|
||||
fps = 15678 / timeTaken;
|
||||
resDir = outputDir;
|
|
@ -1,27 +1,21 @@
|
|||
function [fps, resDir] = run_bu_experiment(bu_dir, verbose, version, varargin)
|
||||
function [output_dir] = run_bu_experiment(bu_dir, verbose, varargin)
|
||||
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
|
||||
output = 'Tracker_';
|
||||
|
||||
% listing the output based on the current revision
|
||||
output = [output 'r' num2str(version)];
|
||||
|
||||
output = cat(2, output, '/');
|
||||
|
||||
if(~exist([bu_dir output], 'dir'))
|
||||
mkdir([bu_dir output]);
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
|
||||
output_dir = 'experiments/bu_out/';
|
||||
|
||||
buFiles = dir([bu_dir '*.avi']);
|
||||
|
||||
numTogether = 25;
|
||||
|
||||
tic;
|
||||
for i=1:numTogether:numel(buFiles)
|
||||
|
||||
command = executable;
|
||||
command = cat(2, command, [' -root ' '"' bu_dir '/"']);
|
||||
command = cat(2, command, [' -inroot ' '"' bu_dir '/"']);
|
||||
|
||||
% BU dataset orientation is in terms of camera plane, instruct the
|
||||
% tracker to output it in that format
|
||||
|
@ -37,12 +31,12 @@ function [fps, resDir] = run_bu_experiment(bu_dir, verbose, version, varargin)
|
|||
[~, name, ~] = fileparts(inputFile);
|
||||
|
||||
% where to output results
|
||||
outputFile = [output name '.txt'];
|
||||
outputFile = [output_dir name '.txt'];
|
||||
|
||||
command = cat(2, command, [' -f "' inputFile '" -of "' outputFile '"']);
|
||||
|
||||
if(verbose)
|
||||
outputVideo = ['"' output name '.avi' '"'];
|
||||
outputVideo = ['"' output_dir name '.avi' '"'];
|
||||
command = cat(2, command, [' -ov ' outputVideo]);
|
||||
end
|
||||
end
|
||||
|
@ -53,13 +47,11 @@ function [fps, resDir] = run_bu_experiment(bu_dir, verbose, version, varargin)
|
|||
command = cat(2, command, [' -mloc "', varargin{find(strcmp('model', varargin))+1}, '"']);
|
||||
end
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command, '-echo')
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
end
|
||||
|
||||
timeTaken = toc;
|
||||
fps = 9000 / timeTaken;
|
||||
|
||||
% tell the caller where the output was written
|
||||
resDir = [bu_dir output];
|
||||
|
||||
|
||||
end
|
|
@ -8,38 +8,34 @@ if exist('D:/Datasets/HeadPose', 'file')
|
|||
database_root = 'D:/Datasets/HeadPose/';
|
||||
elseif(exist([getenv('USERPROFILE') '/Dropbox/AAM/test data/'], 'file'))
|
||||
database_root = [getenv('USERPROFILE') '/Dropbox/AAM/test data/'];
|
||||
else
|
||||
elseif(exist([getenv('USERPROFILE') 'F:/Dropbox/Dropbox/AAM/test data/'], 'file'))
|
||||
database_root = 'F:/Dropbox/Dropbox/AAM/test data/';
|
||||
else
|
||||
database_root = '/multicomp/datasets/head_pose_dbs/';
|
||||
end
|
||||
|
||||
buDir = [database_root, '/bu/uniform-light/'];
|
||||
|
||||
% The fast and accurate clnf
|
||||
%%
|
||||
v = 3;
|
||||
[fps_bu_OF, resFolderBU_OF] = run_bu_experiment(buDir, false, v, 'model', 'model/main_clnf_general.txt');
|
||||
[resFolderBU_OF] = run_bu_experiment(buDir, false, 'model', 'model/main_clnf_general.txt');
|
||||
[bu_error_OF, pred_hp_bu, gt_hp_bu, all_errors_bu_OF, rels_bu] = calcBUerror(resFolderBU_OF, buDir);
|
||||
|
||||
%%
|
||||
% Run the Biwi test
|
||||
biwi_dir = '/biwi pose/';
|
||||
biwi_results_root = '/biwi pose results/';
|
||||
|
||||
% Intensity
|
||||
v = 4;
|
||||
[fps_biwi_OF, res_folder_OF] = run_biwi_experiment(database_root, biwi_dir, biwi_results_root, false, false, v, 'model', 'model/main_clnf_general.txt');
|
||||
[res_folder_biwi_OF] = run_biwi_experiment(database_root, biwi_dir, false, false, 'model', 'model/main_clnf_general.txt');
|
||||
% Calculate the resulting errors
|
||||
[biwi_error_OF, pred_hp_biwi, gt_hp_biwi, ~, all_errors_biwi_OF, rels_biwi] = calcBiwiError([database_root res_folder_OF], [database_root biwi_dir]);
|
||||
[biwi_error_OF, pred_hp_biwi, gt_hp_biwi, ~, all_errors_biwi_OF, rels_biwi] = calcBiwiError(res_folder_biwi_OF, [database_root biwi_dir]);
|
||||
|
||||
%% Run the ICT test
|
||||
ict_dir = ['ict/'];
|
||||
ict_results_root = ['ict results/'];
|
||||
ict_dir = ['/ict/'];
|
||||
|
||||
v = 4;
|
||||
% Intensity
|
||||
[fps_ict_OF, res_folder_ict_OF] = run_ict_experiment(database_root, ict_dir, ict_results_root, false, false, v, 'model', 'model/main_clnf_general.txt');
|
||||
[res_folder_ict_OF] = run_ict_experiment(database_root, ict_dir, false, false, 'model', 'model/main_clnf_general.txt');
|
||||
% Calculate the resulting errors
|
||||
[ict_error_OF, pred_hp_ict, gt_hp_ict, ~, all_errors_ict_OF, rel_ict] = calcIctError([database_root res_folder_ict_OF], [database_root ict_dir]);
|
||||
[ict_error_OF, pred_hp_ict, gt_hp_ict, ~, all_errors_ict_OF, rel_ict] = calcIctError(res_folder_ict_OF, [database_root ict_dir]);
|
||||
|
||||
%% Save the results
|
||||
filename = 'results/Pose_OF';
|
||||
|
|
|
@ -1,27 +1,22 @@
|
|||
function [fps, resDir] = run_ict_experiment(rootDir, ictDir, outputRoot, verbose, depth, version, varargin)
|
||||
function [output_dir] = run_ict_experiment(rootDir, ictDir, verbose, depth, varargin)
|
||||
%EVALUATEICTDATABASE Summary of this function goes here
|
||||
% Detailed explanation goes here
|
||||
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
if(isunix)
|
||||
executable = '"../../build/bin/FeatureExtraction"';
|
||||
else
|
||||
executable = '"../../x64/Release/FeatureExtraction.exe"';
|
||||
end
|
||||
|
||||
output = 'Tracker_';
|
||||
output_dir = 'experiments/ict_out';
|
||||
|
||||
dbSeqDir = dir([rootDir ictDir]);
|
||||
|
||||
% listing the output based on the current revision
|
||||
output = [output 'r' num2str(version)];
|
||||
|
||||
if(depth)
|
||||
output = cat(2, output, '_depth');
|
||||
output_dir = cat(2, output_dir, '_depth');
|
||||
end
|
||||
|
||||
outputDir = cat(2, outputRoot, ['/' output '/']);
|
||||
|
||||
if(~exist([rootDir outputDir], 'dir'))
|
||||
mkdir([rootDir outputDir]);
|
||||
end
|
||||
|
||||
tic;
|
||||
output_dir = cat(2, output_dir, '/');
|
||||
|
||||
numTogether = 10;
|
||||
|
||||
|
@ -29,7 +24,7 @@ for i=3:numTogether:numel(dbSeqDir)
|
|||
|
||||
command = [executable ' -fx 535 -fy 536 -cx 327 -cy 241 -no2Dfp -no3Dfp -noMparams -noAUs -noGaze '];
|
||||
|
||||
command = cat(2, command, [' -root ' '"' rootDir '/"']);
|
||||
command = cat(2, command, [' -inroot ' '"' rootDir '/"']);
|
||||
|
||||
% deal with edge cases
|
||||
if(numTogether + i > numel(dbSeqDir))
|
||||
|
@ -39,7 +34,7 @@ for i=3:numTogether:numel(dbSeqDir)
|
|||
for n=0:numTogether-1
|
||||
|
||||
inputFile = [ictDir dbSeqDir(i+n).name '/colour undist.avi'];
|
||||
outputFile = [outputDir dbSeqDir(i+n).name '.txt'];
|
||||
outputFile = [output_dir dbSeqDir(i+n).name '.txt'];
|
||||
|
||||
command = cat(2, command, [' -f "' inputFile '" -of "' outputFile '" ']);
|
||||
|
||||
|
@ -49,7 +44,7 @@ for i=3:numTogether:numel(dbSeqDir)
|
|||
end
|
||||
|
||||
if(verbose)
|
||||
outputVideo = [outputDir dbSeqDir(i+n).name '.avi'];
|
||||
outputVideo = [output_dir dbSeqDir(i+n).name '.avi'];
|
||||
command = cat(2, command, [' -ov "' outputVideo '"']);
|
||||
end
|
||||
end
|
||||
|
@ -58,12 +53,13 @@ for i=3:numTogether:numel(dbSeqDir)
|
|||
command = cat(2, command, [' -mloc "', varargin{find(strcmp('model', varargin))+1}, '"']);
|
||||
end
|
||||
|
||||
dos(command);
|
||||
if(isunix)
|
||||
unix(command, '-echo')
|
||||
else
|
||||
dos(command);
|
||||
end
|
||||
end
|
||||
|
||||
timeTaken = toc;
|
||||
fps = 10661 / timeTaken;
|
||||
resDir = outputDir;
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--------------------------------------- OpenFace Matlab runners -----------------------------------------------------------------------------
|
||||
|
||||
These are provided for recreation of some of the experiments described in the publications and to demonstrate the command line interface by calling the C++ executables from matlab. This is intended to test the Windows version of the code.
|
||||
These are provided for recreation of some of the experiments described in the publications and to demonstrate the command line interface by calling the C++ executables from Matlab.
|
||||
|
||||
======================== Demos ==================================
|
||||
|
||||
|
|
Loading…
Reference in a new issue