diff --git a/CMakeLists.txt b/CMakeLists.txt index e259984..ec046b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,10 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") set(CMAKE_MODULE_PATH "${BR_SHARE_DIR}/cmake" ${CMAKE_MODULE_PATH}) set(PACKAGE_YEAR 2013) +if("${CMAKE_VERSION}" VERSION_GREATER 2.8.10) + cmake_policy(SET CMP0020 OLD) +endif() + if(${CMAKE_SIZEOF_VOID_P} MATCHES 8) set(BITNESS 64) else() @@ -89,7 +93,7 @@ else() set(CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-auto-import") # Fixes a linker warning set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--enable-auto-import") elseif(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /DNOMINMAX /D_CRT_SECURE_NO_WARNINGS /wd4018 /wd4244 /wd4267 /wd4305 /wd4308 /wd4307 /wd4554 /wd4996 /nologo") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /DNOMINMAX /D_CRT_SECURE_NO_WARNINGS /wd4018 /wd4244 /wd4267 /wd4305 /wd4308 /wd4307 /wd4554 /wd4996 /nologo /MP") endif() endif() @@ -125,27 +129,7 @@ install(DIRECTORY share DESTINATION .) install(DIRECTORY ${BR_THIRDPARTY_SHARE} DESTINATION share) # Package -set(CPACK_BINARY_BUNDLE OFF) -set(CPACK_BINARY_DEB OFF) -set(CPACK_BINARY_DRAGNDROP OFF) -set(CPACK_BINARY_NSIS OFF) -set(CPACK_BINARY_OSXX11 OFF) -set(CPACK_BINARY_PACKAGEMAKER OFF) -set(CPACK_BINARY_RPM OFF) -set(CPACK_BINARY_STGZ OFF) -set(CPACK_BINARY_TBZ2 OFF) -set(CPACK_BINARY_TGZ OFF) -set(CPACK_BINARY_TZ OFF) -set(CPACK_BINARY_ZIP OFF) -set(CPACK_SOURCE_TGZ OFF) -set(CPACK_SOURCE_TZ OFF) -set(CPACK_SOURCE_ZIP OFF) - if(CMAKE_HOST_WIN32) - set(CPACK_BINARY_ZIP ON) - set(CPACK_BINARY_NSIS ON) - - # NSIS set(CPACK_NSIS_MODIFY_PATH ON) set(CPACK_NSIS_MUI_ICON ${NATIVE_ICON}) set(CPACK_NSIS_MUI_UNIICON ${NATIVE_ICON}) @@ -154,22 +138,14 @@ if(CMAKE_HOST_WIN32) set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") endif() elseif(CMAKE_HOST_APPLE) - set(CPACK_BINARY_TBZ2 ON) - set(CPACK_BINARY_BUNDLE ON) - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/README.md" "README.txt" COPYONLY) set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_BINARY_DIR}/README.txt") - set(CPACK_BUNDLE_NAME ${CPACK_PACKAGE_NAME}) set(CPACK_BUNDLE_ICON ${NATIVE_ICON}) set(CPACK_BUNDLE_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) set(CPACK_BUNDLE_STARTUP_COMMAND ${BR_SHARE_DIR}/bundle.sh) configure_file(${BR_SHARE_DIR}/Info.plist.in Info.plist) else() - set(CPACK_BINARY_TBZ2 ON) - set(CPACK_BINARY_DEB ON) - - # DEB set(CPACK_DEBIAN_PACKAGE_MAINTAINER "josh.klontz@gmail.com") endif() diff --git a/openbr/plugins/landmarks.cpp b/openbr/plugins/landmarks.cpp new file mode 100644 index 0000000..a178e33 --- /dev/null +++ b/openbr/plugins/landmarks.cpp @@ -0,0 +1,169 @@ +#include +#include "openbr_internal.h" +#include "openbr/core/qtutils.h" +#include "openbr/core/opencvutils.h" +#include "openbr/core/eigenutils.h" +#include +#include + +using namespace std; +using namespace cv; + +namespace br +{ + +/*! + * \ingroup transforms + * \brief Procrustes alignment of points + * \author Scott Klum \cite sklum + */ +class ProcrustesTransform : public Transform +{ + Q_OBJECT + + Eigen::MatrixXf meanShape; + + void train(const TemplateList &data) + { + QList< QList > normalizedPoints; + + // Normalize all sets of points + foreach (br::Template datum, data) { + QList points = datum.file.points(); + + if (points.empty()) continue; + + cv::Scalar mean = cv::mean(OpenCVUtils::toPoints(points).toVector().toStdVector()); + for (int i = 0; i < points.size(); i++) points[i] -= QPointF(mean[0],mean[1]); + + float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector()); + for (int i = 0; i < points.size(); i++) points[i] /= norm; + + normalizedPoints.append(points); + } + + // Determine mean shape + Eigen::MatrixXf shapeBuffer(normalizedPoints[0].size(), 2); + + for (int i = 0; i < normalizedPoints[0].size(); i++) { + + double x = 0; + double y = 0; + + for (int j = 0; j < normalizedPoints.size(); j++) { + x += normalizedPoints[j][i].x(); + y += normalizedPoints[j][i].y(); + } + + x /= (double)normalizedPoints.size(); + y /= (double)normalizedPoints.size(); + + shapeBuffer(i,0) = x; + shapeBuffer(i,1) = y; + } + + meanShape = shapeBuffer; + } + + void project(const Template &src, Template &dst) const + { + QList points = src.file.points(); + + cv::Scalar mean = cv::mean(OpenCVUtils::toPoints(points).toVector().toStdVector()); + for (int i = 0; i < points.size(); i++) points[i] -= QPointF(mean[0],mean[1]); + + float norm = cv::norm(OpenCVUtils::toPoints(points).toVector().toStdVector()); + Eigen::MatrixXf srcPoints(points.size(), 2); + + for (int i = 0; i < points.size(); i++) { + srcPoints(i,0) = points[i].x()/(norm/150.)+50; + srcPoints(i,1) = points[i].y()/(norm/150.)+50; + } + + Eigen::JacobiSVD svd(srcPoints.transpose()*meanShape, Eigen::ComputeThinU | Eigen::ComputeThinV); + + Eigen::MatrixXf R = svd.matrixU()*svd.matrixV().transpose(); + + Eigen::MatrixXf dstPoints = srcPoints*R; + + points.clear(); + + for (int i = 0; i < dstPoints.rows(); i++) points.append(QPointF(dstPoints(i,0),dstPoints(i,1))); + + dst.file.appendPoints(points); + } + + void store(QDataStream &stream) const + { + stream << meanShape; + } + + void load(QDataStream &stream) + { + stream >> meanShape; + } + +}; + +BR_REGISTER(Transform, ProcrustesTransform) + +/*! + * \ingroup transforms + * \brief Wraps STASM key point detector + * \author Scott Klum \cite sklum + */ +class DelauneyTransform : public UntrainableTransform +{ + Q_OBJECT + + Q_PROPERTY(bool draw READ get_draw WRITE set_draw RESET reset_draw STORED false) + BR_PROPERTY(bool, draw, false) + + void project(const Template &src, Template &dst) const + { + dst = src; + + Subdiv2D subdiv(Rect(0,0,src.m().cols,src.m().rows)); + + foreach(const cv::Point2f& point, OpenCVUtils::toPoints(src.file.points())) subdiv.insert(point); + + vector triangleList; + subdiv.getTriangleList(triangleList); + vector pt(3); + + Scalar delaunay_color(0, 0, 0); + + if (draw) { + int count = 0; + for(size_t i = 0; i < triangleList.size(); ++i) { + Vec6f t = triangleList[i]; + + pt[0] = Point(cvRound(t[0]), cvRound(t[1])); + pt[1] = Point(cvRound(t[2]), cvRound(t[3])); + pt[2] = Point(cvRound(t[4]), cvRound(t[5])); + + bool inside = true; + for (int i = 0; i < 3; i++) { + if(pt[i].x > dst.m().cols || pt[i].y > dst.m().rows || pt[i].x <= 0 || pt[i].y <= 0) { + inside = false; + } + + } + if (inside) { + count++; + //qDebug() << count << pt[0] << pt[1] << pt[2] << "Area" << contourArea(pt); + line(dst.m(), pt[0], pt[1], delaunay_color, 1); + line(dst.m(), pt[1], pt[2], delaunay_color, 1); + line(dst.m(), pt[2], pt[0], delaunay_color, 1); + } + } + } + } + +}; + +BR_REGISTER(Transform, DelauneyTransform) + +} // namespace br + +#include "landmarks.moc" diff --git a/openbr/plugins/regions.cpp b/openbr/plugins/regions.cpp index b6bba45..26d2dc0 100644 --- a/openbr/plugins/regions.cpp +++ b/openbr/plugins/regions.cpp @@ -201,9 +201,11 @@ class RectFromPointsTransform : public UntrainableTransform Q_PROPERTY(QList indices READ get_indices WRITE set_indices RESET reset_indices STORED false) Q_PROPERTY(double padding READ get_padding WRITE set_padding RESET reset_padding STORED false) Q_PROPERTY(double aspectRatio READ get_aspectRatio WRITE set_aspectRatio RESET reset_aspectRatio STORED false) + Q_PROPERTY(bool crop READ get_crop WRITE set_crop RESET reset_crop STORED false) BR_PROPERTY(QList, indices, QList()) BR_PROPERTY(double, padding, 0) BR_PROPERTY(double, aspectRatio, 1.0) + BR_PROPERTY(bool, crop, true) void project(const Template &src, Template &dst) const { @@ -218,13 +220,15 @@ class RectFromPointsTransform : public UntrainableTransform int maxX, maxY; maxX = maxY = -std::numeric_limits::max(); + QList points; + foreach(int index, indices) { if (src.file.points().size() > index) { if (src.file.points()[index].x() < minX) minX = src.file.points()[index].x(); if (src.file.points()[index].x() > maxX) maxX = src.file.points()[index].x(); if (src.file.points()[index].y() < minY) minY = src.file.points()[index].y(); if (src.file.points()[index].y() > maxY) maxY = src.file.points()[index].y(); - dst.file.appendPoint(src.file.points()[index]); + points.append(src.file.points()[index]); } } @@ -236,7 +240,10 @@ class RectFromPointsTransform : public UntrainableTransform double deltaHeight = width/aspectRatio - height; height += deltaHeight; - dst.m() = src.m()(Rect(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height))); + dst.file.setPoints(points); + + if (crop) dst.m() = src.m()(Rect(std::max(0.0, minX - deltaWidth/2.0), std::max(0.0, minY - deltaHeight/2.0), std::min((double)src.m().cols, width), std::min((double)src.m().rows, height))); + else dst.m() = src.m(); } }; diff --git a/openbr/plugins/stasm4.cpp b/openbr/plugins/stasm4.cpp index d4c5685..3191edf 100644 --- a/openbr/plugins/stasm4.cpp +++ b/openbr/plugins/stasm4.cpp @@ -1,8 +1,13 @@ #include #include -#include +#include #include "openbr_internal.h" +#include "openbr/core/qtutils.h" +#include "openbr/core/opencvutils.h" +#include +#include +using namespace std; using namespace cv; namespace br diff --git a/share/openbr/cmake/InstallDependencies.cmake b/share/openbr/cmake/InstallDependencies.cmake index 3be973a..e29b011 100644 --- a/share/openbr/cmake/InstallDependencies.cmake +++ b/share/openbr/cmake/InstallDependencies.cmake @@ -72,11 +72,11 @@ function(install_qt_misc) endif() install(FILES ${_qt5Core_install_prefix}/bin/libGLESv2${BR_INSTALL_DEPENDENCIES_SUFFIX}.dll DESTINATION bin) install(FILES ${_qt5Core_install_prefix}/bin/libEGL${BR_INSTALL_DEPENDENCIES_SUFFIX}.dll DESTINATION bin) - install(FILES ${_qt5Core_install_prefix}/bin/icuin49${BR_INSTALL_DEPENDENCIES_SUFFIX}.dll DESTINATION bin) - install(FILES ${_qt5Core_install_prefix}/bin/icuuc49${BR_INSTALL_DEPENDENCIES_SUFFIX}.dll DESTINATION bin) - install(FILES ${_qt5Core_install_prefix}/bin/icudt49.dll DESTINATION bin) - install(FILES ${_qt5Core_install_prefix}/bin/d3dcompiler_46.dll DESTINATION bin) - install(FILES ${_qt5Core_install_prefix}/plugins/platforms/qwindows${BR_INSTALL_DEPENDENCIES_SUFFIX}.dll DESTINATION bin/platforms) + file(GLOB icudlls ${_qt5Core_install_prefix}/bin/icu*.dll) + install(FILES ${icudlls} DESTINATION bin) + file(GLOB d3dcomp ${_qt5Core_install_prefix}/bin/d3dcompiler_*.dll) + install(FILES ${d3dcomp} DESTINATION bin) + install(FILES ${_qt5Core_install_prefix}/plugins/platforms/qwindows${BR_INSTALL_DEPENDENCIES_SUFFIX}.dll DESTINATION bin/platforms) endif() endfunction()