diff options
author | Willy Sudiarto Raharjo <willysr@slackbuilds.org> | 2015-10-17 22:04:59 +0700 |
---|---|---|
committer | Willy Sudiarto Raharjo <willysr@slackbuilds.org> | 2015-10-17 22:07:01 +0700 |
commit | d000e6e4151a1829c3ee761b4b07f86101762b39 (patch) | |
tree | 2ee73ebe81a82244525cae116b85ab3dc3ac76be /libraries/libkface | |
parent | 8a748875c35cf2f73d5b94187f620e4973528f44 (diff) |
libraries/libkface: Added (KDE face recognition wrapper library).
Signed-off-by: Willy Sudiarto Raharjo <willysr@slackbuilds.org>
Diffstat (limited to 'libraries/libkface')
-rw-r--r-- | libraries/libkface/README | 2 | ||||
-rw-r--r-- | libraries/libkface/libkface.SlackBuild | 101 | ||||
-rw-r--r-- | libraries/libkface/libkface.info | 10 | ||||
-rw-r--r-- | libraries/libkface/libkface.patch | 418 | ||||
-rw-r--r-- | libraries/libkface/slack-desc | 19 |
5 files changed, 550 insertions, 0 deletions
diff --git a/libraries/libkface/README b/libraries/libkface/README new file mode 100644 index 0000000000000..8ccd70bdbc4ec --- /dev/null +++ b/libraries/libkface/README @@ -0,0 +1,2 @@ +A Qt/C++ wrapper around LibFace library to perform face recognition +and detection over pictures. diff --git a/libraries/libkface/libkface.SlackBuild b/libraries/libkface/libkface.SlackBuild new file mode 100644 index 0000000000000..51dad62750aa7 --- /dev/null +++ b/libraries/libkface/libkface.SlackBuild @@ -0,0 +1,101 @@ +#!/bin/sh + +# Slackware build script for libkface + +# Copyright 2015 Willy Sudiarto Raharjo <willysr@slackbuilds.org> +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 AUTHOR 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. + +PRGNAM=libkface +VERSION=${VERSION:-15.08.2} +BUILD=${BUILD:-1} +TAG=${TAG:-_SBo} + +if [ -z "$ARCH" ]; then + case "$( uname -m )" in + i?86) ARCH=i486 ;; + arm*) ARCH=arm ;; + *) ARCH=$( uname -m ) ;; + esac +fi + +CWD=$(pwd) +TMP=${TMP:-/tmp/SBo} +PKG=$TMP/package-$PRGNAM +OUTPUT=${OUTPUT:-/tmp} + +if [ "$ARCH" = "i486" ]; then + SLKCFLAGS="-O2 -march=i486 -mtune=i686" + LIBDIRSUFFIX="" +elif [ "$ARCH" = "i686" ]; then + SLKCFLAGS="-O2 -march=i686 -mtune=i686" + LIBDIRSUFFIX="" +elif [ "$ARCH" = "x86_64" ]; then + SLKCFLAGS="-O2 -fPIC" + LIBDIRSUFFIX="64" +else + SLKCFLAGS="-O2" + LIBDIRSUFFIX="" +fi + +set -e + +rm -rf $PKG +mkdir -p $TMP $PKG $OUTPUT +cd $TMP +rm -rf $PRGNAM-$VERSION +tar xvf $CWD/$PRGNAM-$VERSION.tar.xz +cd $PRGNAM-$VERSION +chown -R root:root . +find -L . \ + \( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \ + -o -perm 511 \) -exec chmod 755 {} \; -o \ + \( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \ + -o -perm 440 -o -perm 400 \) -exec chmod 644 {} \; + +# patch to support OpenCV3 +# https://quickgit.kde.org/?p=libkface.git&a=commit&h=a53bcebbfc4e6c42ee73adddc41f8c2f8f8f39c8 +patch -p1 < $CWD/libkface.patch + +mkdir -p build +cd build + cmake \ + -DCMAKE_C_FLAGS:STRING="$SLKCFLAGS" \ + -DCMAKE_CXX_FLAGS:STRING="$SLKCFLAGS" \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DLIB_SUFFIX=${LIBDIRSUFFIX} \ + -DMAN_INSTALL_DIR=/usr/man \ + -DENABLE_OPENCV3=ON \ + -DCMAKE_BUILD_TYPE=Release .. + make + make install DESTDIR=$PKG +cd .. + +find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \ + | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true + +mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION +cp -a COPYING* AUTHORS README TODO $PKG/usr/doc/$PRGNAM-$VERSION +cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild + +mkdir -p $PKG/install +cat $CWD/slack-desc > $PKG/install/slack-desc + +cd $PKG +/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.${PKGTYPE:-tgz} diff --git a/libraries/libkface/libkface.info b/libraries/libkface/libkface.info new file mode 100644 index 0000000000000..3f13e95821884 --- /dev/null +++ b/libraries/libkface/libkface.info @@ -0,0 +1,10 @@ +PRGNAM="libkface" +VERSION="15.08.2" +HOMEPAGE="https://www.digikam.org" +DOWNLOAD="http://download.kde.org/stable/applications/15.08.2/src/libkface-15.08.2.tar.xz" +MD5SUM="ab51bf06908c4580769fed3bd2e2d774" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +REQUIRES="opencv" +MAINTAINER="Willy Sudiarto Raharjo" +EMAIL="willysr@slackbuilds.org" diff --git a/libraries/libkface/libkface.patch b/libraries/libkface/libkface.patch new file mode 100644 index 0000000000000..dff5711b74e44 --- /dev/null +++ b/libraries/libkface/libkface.patch @@ -0,0 +1,418 @@ +From: Gilles Caulier <caulier.gilles@gmail.com> +Date: Sat, 05 Sep 2015 19:20:22 +0000 +Subject: apply patch #94414 to support OpenCV3 +X-Git-Url: http://quickgit.kde.org/?p=libkface.git&a=commitdiff&h=a53bcebbfc4e6c42ee73adddc41f8c2f8f8f39c8 +--- +apply patch #94414 to support OpenCV3 +CCBUGS: 349601 +--- + + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -9,6 +9,8 @@ + + message(STATUS "----------------------------------------------------------------------------------") + message(STATUS "Starting CMake configuration for: libkface") ++ ++option(ENABLE_OPENCV3 "Build libkface with OpenCV3 instead OpenCV2 (default=OFF)" OFF) + + find_package(Qt4 4.6.0 REQUIRED) + find_package(KDE4 REQUIRED) +@@ -30,7 +32,12 @@ + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) + + include(MacroOpenCV) +-DETECT_OPENCV(2.4.9 core highgui objdetect contrib legacy imgproc) ++ ++if (ENABLE_OPENCV3) ++ DETECT_OPENCV(3.0.0 core face highgui objdetect imgproc) ++else() ++ DETECT_OPENCV(2.4.9 core highgui objdetect contrib legacy imgproc) ++endif() + + include_directories(${OpenCV_INCLUDE_DIRS}) + + +--- a/README ++++ b/README +@@ -20,6 +20,11 @@ + libqt >= 4.6.x http://www.qtsoftware.com + libkde >= 4.4.x http://www.kde.org + libopencv >= 2.4.9 http://opencv.willowgarage.com/wiki (with opencv 'haarcascades' data files) ++ ++CMake compilation options to custom libkface: ++ ++Use CMake "-DENABLE_OPENCV3=on" flag to compile libkface source code using OpenCV3 instead OpenCV2 (disabled by default). ++ OpenCV3 support needs extra contrib modules package, especially 'face' and 'legacy' components. + + -- INSTALL ------------------------------------------------------------ + + +--- a/libkface/CMakeLists.txt ++++ b/libkface/CMakeLists.txt +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2010-2014, Gilles Caulier, <caulier dot gilles at gmail dot com> ++# Copyright (c) 2010-2015, Gilles Caulier, <caulier dot gilles at gmail dot com> + # + # Redistribution and use is allowed according to the terms of the BSD license. + # For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +--- a/libkface/detection/opencvfacedetector.cpp ++++ b/libkface/detection/opencvfacedetector.cpp +@@ -18,7 +18,7 @@ + * <a href="alexjironkin at gmail dot com">alexjironkin at gmail dot com</a> + * @author Copyright (C) 2010 by Aditya Bhatt + * <a href="adityabhatt at gmail dot com">adityabhatt at gmail dot com</a> +- * @author Copyright (C) 2010-2014 by Gilles Caulier ++ * @author Copyright (C) 2010-2015 by Gilles Caulier + * <a href="mailto:caulier dot gilles at gmail dot com">caulier dot gilles at gmail dot com</a> + * @author Copyright (C) 2010-2013 by Marcel Wiesweg + * <a href="mailto:marcel dot wiesweg at gmx dot de">marcel dot wiesweg at gmx dot de</a> +@@ -136,13 +136,14 @@ + + cv::Size getOriginalWindowSize() const + { ++#if OPENCV_VERSION <= OPENCV_MAKE_VERSION(2,4,11) + // This is a HACK which may break any time. Work around the fact that getOriginalWindowSize() + // always returns (0,0) and we need these values. + if (oldCascade) + { + return oldCascade->orig_window_size; + } +- ++#endif + return cv::Size(0, 0); + } + + +--- a/libkface/libopencv.h.cmake.in ++++ b/libkface/libopencv.h.cmake.in +@@ -7,7 +7,7 @@ + * @date 2010-06-16 + * @brief Wrapper for OpenCV header files + * +- * @author Copyright (C) 2012-2014 by Gilles Caulier ++ * @author Copyright (C) 2012-2015 by Gilles Caulier + * <a href="mailto:caulier dot gilles at gmail dot com">caulier dot gilles at gmail dot com</a> + * + * This program is free software; you can redistribute it +@@ -31,16 +31,16 @@ + + // Pragma directives to reduce warnings from OpenCV header files. + #if not defined(__APPLE__) && defined(__GNUC__) +-#pragma GCC diagnostic push +-#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +-#pragma GCC diagnostic ignored "-Woverloaded-virtual" ++# pragma GCC diagnostic push ++# pragma GCC diagnostic ignored "-Wnon-virtual-dtor" ++# pragma GCC diagnostic ignored "-Woverloaded-virtual" + #endif + + #if defined(__APPLE__) && defined(__clang__) +-#pragma clang diagnostic push +-#pragma clang diagnostic ignored "-Wnon-virtual-dtor" +-#pragma clang diagnostic ignored "-Woverloaded-virtual" +-#pragma clang diagnostic ignored "-Wcast-align" ++# pragma clang diagnostic push ++# pragma clang diagnostic ignored "-Wnon-virtual-dtor" ++# pragma clang diagnostic ignored "-Woverloaded-virtual" ++# pragma clang diagnostic ignored "-Wcast-align" + #endif + + // OpenCV includes +@@ -51,23 +51,30 @@ + #define OPENCV_VERSION OPENCV_MAKE_VERSION(CV_MAJOR_VERSION,CV_MINOR_VERSION,CV_SUBMINOR_VERSION) + #define OPENCV_TEST_VERSION(major,minor,patch) ( OPENCV_VERSION >= OPENCV_MAKE_VERSION(major,minor,patch) ) + +-#include <opencv2/core/core.hpp> +-#include <opencv2/core/internal.hpp> +-#include <opencv2/contrib/contrib.hpp> ++#if OPENCV_TEST_VERSION(3,0,0) ++# include <opencv2/face.hpp> ++# include <opencv2/core.hpp> ++#else ++# include <opencv2/core/core.hpp> ++# include <opencv2/core/internal.hpp> ++# include <opencv2/contrib/contrib.hpp> ++#endif + + // for old-style code ++#if OPENCV_VERSION <= OPENCV_MAKE_VERSION(2,4,11) ++# include <opencv2/legacy/compat.hpp> ++#endif + #include <opencv2/opencv.hpp> +-#include <opencv2/legacy/compat.hpp> + #include <opencv2/highgui/highgui_c.h> + #include <opencv/cvaux.h> + + // Restore warnings + #if not defined(__APPLE__) && defined(__GNUC__) +-#pragma GCC diagnostic pop ++# pragma GCC diagnostic pop + #endif + + #if defined(__APPLE__) && defined(__clang__) +-#pragma clang diagnostic pop ++# pragma clang diagnostic pop + #endif + + #endif // LIB_OPEN_CV_H + +--- a/libkface/recognition-opencv-lbph/facerec_borrowed.cpp ++++ b/libkface/recognition-opencv-lbph/facerec_borrowed.cpp +@@ -531,15 +531,17 @@ + return ptr; + } + +-CV_INIT_ALGORITHM(LBPHFaceRecognizer, "FaceRecognizer.LBPH-KFaceIface", +- obj.info()->addParam(obj, "radius", obj.m_radius); +- obj.info()->addParam(obj, "neighbors", obj.m_neighbors); +- obj.info()->addParam(obj, "grid_x", obj.m_grid_x); +- obj.info()->addParam(obj, "grid_y", obj.m_grid_y); +- obj.info()->addParam(obj, "threshold", obj.m_threshold); +- obj.info()->addParam(obj, "histograms", obj.m_histograms); // modification: Make Read/Write +- obj.info()->addParam(obj, "labels", obj.m_labels); // modification: Make Read/Write +- obj.info()->addParam(obj, "statistic", obj.m_statisticsMode)); // modification: Add parameter ++#if OPENCV_VERSION <= OPENCV_MAKE_VERSION(2,4,11) ++ CV_INIT_ALGORITHM(LBPHFaceRecognizer, "FaceRecognizer.LBPH-KFaceIface", ++ obj.info()->addParam(obj, "radius", obj.m_radius); ++ obj.info()->addParam(obj, "neighbors", obj.m_neighbors); ++ obj.info()->addParam(obj, "grid_x", obj.m_grid_x); ++ obj.info()->addParam(obj, "grid_y", obj.m_grid_y); ++ obj.info()->addParam(obj, "threshold", obj.m_threshold); ++ obj.info()->addParam(obj, "histograms", obj.m_histograms); // modification: Make Read/Write ++ obj.info()->addParam(obj, "labels", obj.m_labels); // modification: Make Read/Write ++ obj.info()->addParam(obj, "statistic", obj.m_statisticsMode)); // modification: Add parameter ++#endif + + } // namespace KFaceIface + + +--- a/libkface/recognition-opencv-lbph/facerec_borrowed.h ++++ b/libkface/recognition-opencv-lbph/facerec_borrowed.h +@@ -45,7 +45,11 @@ + namespace KFaceIface + { + ++#if OPENCV_TEST_VERSION(3,0,0) ++class LBPHFaceRecognizer : public cv::face::FaceRecognizer ++#else + class LBPHFaceRecognizer : public cv::FaceRecognizer ++#endif + { + public: + +@@ -99,8 +103,13 @@ + + ~LBPHFaceRecognizer() {} + ++#if OPENCV_TEST_VERSION(3,0,0) ++ using cv::face::FaceRecognizer::save; ++ using cv::face::FaceRecognizer::load; ++#else + using cv::FaceRecognizer::save; + using cv::FaceRecognizer::load; ++#endif + + static cv::Ptr<LBPHFaceRecognizer> create(int radius=1, int neighbors=8, int grid_x=8, int grid_y=8, double threshold = DBL_MAX, PredictionStatistics statistics = NearestNeighbor); + +@@ -139,6 +148,34 @@ + /** + * Getter functions. + */ ++#if OPENCV_TEST_VERSION(3,0,0) ++ ++ int getNeighbors() const { return m_neighbors; } ++ void setNeighbors(int _neighbors) { m_neighbors = _neighbors; } ++ ++ int getRadius() const { return m_radius; } ++ void setRadius(int radius) { m_radius = radius; } ++ ++ int getGrid_x() const { return m_grid_x; } ++ void setGrid_x(int _grid_x) { m_grid_x = _grid_x; } ++ ++ int getGrid_y() const { return m_grid_y; } ++ void setGrid_y(int _grid_y) { m_grid_y = _grid_y; } ++ ++ double getThreshold() const { return m_threshold; } ++ void setThreshold(double _threshold) { m_threshold = _threshold; } ++ ++ void setHistograms(std::vector<cv::Mat> _histograms) { m_histograms = _histograms; } ++ std::vector<cv::Mat> getHistograms() const { return m_histograms; } ++ ++ void setLabels(cv::Mat _labels) { m_labels = _labels; } ++ cv::Mat getLabels() const { return m_labels; } ++ ++ void setStatistic(int _statistic) { m_statisticsMode = _statistic; } ++ int getStatistic() const { return m_statisticsMode; } ++ ++#else ++ + int neighbors() const { return m_neighbors; } + int radius() const { return m_radius; } + int grid_x() const { return m_grid_x; } +@@ -146,6 +183,8 @@ + + // NOTE: Implementation done through CV_INIT_ALGORITHM macro from OpenCV. + cv::AlgorithmInfo* info() const; ++ ++#endif + + private: + + +--- a/libkface/recognition-opencv-lbph/lbphfacemodel.cpp ++++ b/libkface/recognition-opencv-lbph/lbphfacemodel.cpp +@@ -61,7 +61,11 @@ + : cv::Ptr<LBPHFaceRecognizer>(LBPHFaceRecognizer::create()), + databaseId(0) + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ ptr()->setThreshold(100.0); ++#else + ptr()->set("threshold", 100.0); ++#endif + } + + LBPHFaceModel::~LBPHFaceModel() +@@ -80,9 +84,13 @@ + + const LBPHFaceRecognizer* LBPHFaceModel::ptr() const + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ const LBPHFaceRecognizer* const ptr = cv::Ptr<LBPHFaceRecognizer>::operator KFaceIface::LBPHFaceRecognizer*(); ++#else + const LBPHFaceRecognizer* const ptr = cv::Ptr<LBPHFaceRecognizer>::operator const KFaceIface::LBPHFaceRecognizer*(); +- +- if (!ptr) ++#endif ++ ++ if (!ptr) + kWarning() << "LBPHFaceRecognizer pointer is null"; + + return ptr; +@@ -90,47 +98,83 @@ + + int LBPHFaceModel::radius() const + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ return ptr()->getRadius(); ++#else + return ptr()->get<int>("radius"); ++#endif + } + + void LBPHFaceModel::setRadius(int radius) + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ ptr()->setRadius(radius); ++#else + ptr()->set("radius", radius); ++#endif + } + + int LBPHFaceModel::neighbors() const + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ return ptr()->getNeighbors(); ++#else + return ptr()->get<int>("neighbors"); ++#endif + } + + void LBPHFaceModel::setNeighbors(int neighbors) + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ ptr()->setNeighbors(neighbors); ++#else + ptr()->set("neighbors", neighbors); ++#endif + } + + int LBPHFaceModel::gridX() const + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ return ptr()->getGrid_x(); ++#else + return ptr()->get<int>("grid_x"); ++#endif + } + + void LBPHFaceModel::setGridX(int grid_x) + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ ptr()->setGrid_x(grid_x); ++#else + ptr()->set("grid_x", grid_x); ++#endif + } + + int LBPHFaceModel::gridY() const + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ return ptr()->getGrid_y(); ++#else + return ptr()->get<int>("grid_y"); ++#endif + } + + void LBPHFaceModel::setGridY(int grid_y) + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ ptr()->setGrid_y(grid_y); ++#else + ptr()->set("grid_y", grid_y); ++#endif + } + + OpenCVMatData LBPHFaceModel::histogramData(int index) const + { ++#if OPENCV_TEST_VERSION(3,0,0) ++ return OpenCVMatData(ptr()->getHistograms().at(index)); ++#else + return OpenCVMatData(ptr()->get<std::vector<cv::Mat> >("histograms").at(index)); ++#endif + } + + QList<LBPHistogramMetadata> LBPHFaceModel::histogramMetadata() const +@@ -168,12 +212,24 @@ + m_histogramMetadata << metadata; + } + ++#if OPENCV_TEST_VERSION(3,0,0) ++ std::vector<cv::Mat> currentHistograms = ptr()->getHistograms(); ++ cv::Mat currentLabels = ptr()->getLabels(); ++#else + std::vector<cv::Mat> currentHistograms = ptr()->get<std::vector<cv::Mat> >("histograms"); + cv::Mat currentLabels = ptr()->get<cv::Mat>("labels"); ++#endif ++ + currentHistograms.insert(currentHistograms.end(), newHistograms.begin(), newHistograms.end()); + currentLabels.push_back(newLabels); ++ ++#if OPENCV_TEST_VERSION(3,0,0) ++ ptr()->setHistograms(currentHistograms); ++ ptr()->setLabels(currentLabels); ++#else + ptr()->set("histograms", currentHistograms); +- ptr()->set("labels", currentLabels); ++ ptr()->set("labels", currentLabels); ++#endif + + /* + //Most cumbersome and inefficient way through a file storage which we were forced to use if we used standard OpenCV +@@ -215,7 +271,11 @@ + + // Update local information + // We assume new labels are simply appended ++#if OPENCV_TEST_VERSION(3,0,0) ++ cv::Mat currentLabels = ptr()->getLabels(); ++#else + cv::Mat currentLabels = ptr()->get<cv::Mat>("labels"); ++#endif + + for (int i = m_histogramMetadata.size() ; i < currentLabels.rows ; i++) + { + diff --git a/libraries/libkface/slack-desc b/libraries/libkface/slack-desc new file mode 100644 index 0000000000000..d48907b19ba4e --- /dev/null +++ b/libraries/libkface/slack-desc @@ -0,0 +1,19 @@ +# HOW TO EDIT THIS FILE: +# The "handy ruler" below makes it easier to edit a package description. +# Line up the first '|' above the ':' following the base package name, and +# the '|' on the right side marks the last column you can put a character in. +# You must make exactly 11 lines for the formatting to be correct. It's also +# customary to leave one space after the ':' except on otherwise blank lines. + + |-----handy-ruler------------------------------------------------------| +libkface: libkface (KDE face recognition wrapper library) +libkface: +libkface: A Qt/C++ wrapper around LibFace library to perform face recognition +libkface: and detection over pictures. +libkface: This library is used by kipi-plugins, digiKam and others. +libkface: +libkface: +libkface: +libkface: +libkface: For more information, visit: https://www.digikam.org +libkface: |