text:
/*
 * FileUtils.cpp
 *
 *  Created on: Oct 19, 2011
 *      Author: lbossard
 */

#include "file_utils.hpp"
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>

namespace utils
{
namespace fs
{

namespace bfs = boost::filesystem;

//------------------------------------------------------------------------------
void collect_images(const std::string& input_path, std::vector<bfs::path>* image_paths)
{
  collect_files(
      input_path,
      ".*\\.(jpg|jpeg|gif|png|bmp|tiff)",
      std::back_inserter(*image_paths));
  std::sort(image_paths->begin(), image_paths->end());
}

void collect_directories( const std::string& input_path, std::vector<bfs::path>* paths) {

  bfs::directory_iterator end_iter;
  if (bfs::is_directory(input_path)) {
    for( bfs::directory_iterator dir_iter(input_path) ; dir_iter != end_iter ; ++dir_iter) {
       if (bfs::is_directory(dir_iter->status()) ) {
         paths->push_back(*dir_iter);
       }
     }

    // sort the paths
    std::sort(paths->begin(), paths->end());
  }
}

}} /* namespace utils */


text:
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2020 Richard Hodges (hodges.r@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//

#ifndef BOOST_BEAST_TEST_DETAIL_STREAM_STATE_HPP
#define BOOST_BEAST_TEST_DETAIL_STREAM_STATE_HPP

#include <boost/asio/any_io_executor.hpp>
#include <boost/beast/core/detail/service_base.hpp>
#include <boost/smart_ptr/weak_ptr.hpp>

#include <condition_variable>
#include <memory>
#include <mutex>
#include <vector>

namespace boost {
namespace beast {
namespace test {
namespace detail {

struct stream_state;

struct stream_service_impl
{
    std::mutex m_;
    std::vector<stream_state*> v_;

    BOOST_BEAST_DECL
    void
    remove(stream_state& impl);
};

//------------------------------------------------------------------------------

class stream_service
    : public beast::detail::service_base<stream_service>
{
    boost::shared_ptr<detail::stream_service_impl> sp_;

    BOOST_BEAST_DECL
    void
    shutdown() override;

public:
    BOOST_BEAST_DECL
    explicit
    stream_service(net::execution_context& ctx);

    BOOST_BEAST_DECL
    static
    auto
    make_impl(
        net::any_io_executor exec,
        test::fail_count* fc) ->
            boost::shared_ptr<detail::stream_state>;
};

//------------------------------------------------------------------------------

struct stream_read_op_base
{
    virtual ~stream_read_op_base() = default;
    virtual void operator()(error_code ec) = 0;
};

//------------------------------------------------------------------------------

enum class stream_status
{
    ok,
    eof,
};

//------------------------------------------------------------------------------

struct stream_state
{
    net::any_io_executor exec;
    boost::weak_ptr<stream_service_impl> wp;
    std::mutex m;
    flat_buffer b;
    std::condition_variable cv;
    std::unique_ptr<stream_read_op_base> op;
    stream_status code = stream_status::ok;
    fail_count* fc = nullptr;
    std::size_t nread = 0;
    std::size_t nread_bytes = 0;
    std::size_t nwrite = 0;
    std::size_t nwrite_bytes = 0;
    std::size_t read_max =
        (std::numeric_limits<std::size_t>::max)();
    std::size_t write_max =
        (std::numeric_limits<std::size_t>::max)();

    BOOST_BEAST_DECL
    stream_state(
        net::any_io_executor exec_,
        boost::weak_ptr<stream_service_impl> wp_,
        fail_count* fc_);

    BOOST_BEAST_DECL
    ~stream_state();

    BOOST_BEAST_DECL
    void
    remove() noexcept;

    BOOST_BEAST_DECL
    void
    notify_read();

    BOOST_BEAST_DECL
    void
    cancel_read();
};

} // detail
} // test
} // beast
} // boost

#ifdef BOOST_BEAST_HEADER_ONLY
#include <boost/beast/_experimental/test/detail/stream_state.ipp>
#endif

#endif // BOOST_BEAST_TEST_DETAIL_STREAM_STATE_HPP

ext: hpp


text:
// Copyright (c) 2016 Till Kolditz, Stefan de Bruijn
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>

#ifdef _MSC_VER
// disable stupid diamond-inheritance warnings (the compiler does not see that there is only a single implementation for each of the functions)
#pragma warning(disable: 4250)
#endif

#include <Util/Test.hpp>
#include <Util/AlignedBlock.hpp>
#include <Util/TestInfo.hpp>
#include <Util/ErrorInfo.hpp>
#include <Util/VFunc.hpp>
#include <Util/Euclidean.hpp>
#include <Util/Intrinsics.hpp>
#include <Util/ComputeNumRuns.hpp>
#include <Util/ExpandTest.hpp>
#include <Util/TestCase.hpp>
#include <Util/Output.hpp>

#include <Copy/CopyTest.hpp>

#include <XOR/XOR_scalar.hpp>
#include <XOR/XOR_simd.hpp>

#include <AN/AN_scalar.hpp>
#include <AN/AN_simd.hpp>

#include <Hamming/Hamming_scalar.hpp>
#include <Hamming/Hamming_simd.hpp>

#ifdef TESTCRC
#include <CRC/CRC_scalar.hpp>
#endif

using namespace coding_benchmark;

#ifdef TEST32
#include <boost/multiprecision/cpp_int.hpp>

using uint128_t = boost::multiprecision::uint128_t;
#endif

int checkArgs(
        int argc,
        char* argv[],
        size_t & AUser1) {
    if (argc == 1) {
        return 0;
    }
    if (argc != 2) {
        printUsage(argv);
        return 1;
    }
    char* endPtr = nullptr;
    AUser1 = strtoull(argv[1], &endPtr, 0);
    if (endPtr == argv[1] || AUser1 == 0 || (AUser1 & 1) == 0) {
        std::cerr << "Error: A is not a valid positive, non-zero, odd integer!\n";
        printUsage(argv);
        return 2;
    }
#if defined(TEST8)
    if (AUser1 >= (1ull << 8)) {
        std::cerr << "Error: Given A is too large! Must be at most 2^8-1\n";
        printUsage(argv);
        return 3;
    }
#elif defined(TEST16)
    if (AUser1 >= (1ull << 16)) {
        std::cerr << "Error: Given A is too large! Must be at most 2^16-1\n";
        printUsage(argv);
        return 3;
    }
#elif defined(TEST32)
    if (AUser1 >= (1ull << 32)) {
        std::cerr << "Error: Given A is too large! Must be at most 2^32-1\n";
        printUsage(argv);
        return 3;
    }
#else
#error "You must define (-D) exactly one of TEST8, TEST16, or TEST32"
#endif
    return 0;
}

int main(
        int argc,
        char* argv[]) {
    const constexpr size_t numElements = 1000001ull;
    const constexpr size_t iterations = 10000ull;
    const constexpr size_t UNROLL_LO = 1ull;
    const constexpr size_t UNROLL_HI = 1024ull;

    std::cout << "# numElements = " << numElements << '\n';
    std::cout << "# iterations = " << iterations << '\n';
    std::cout << "# UNROLL_LO = " << UNROLL_LO << '\n';
    std::cout << "# UNROLL_HI = " << UNROLL_HI << '\n';

    size_t AUser = 64311ull;
    int result = checkArgs(argc, argv, AUser);
    if (result != 0) {
        return result;
    }
    _ReadWriteBarrier();

    std::vector<std::vector<TestInfos>> vecTestInfos;

    TestConfiguration testConfig(iterations, numElements);
    // The following is for the reproducibility of the SIGMOD 2018 "AHEAD" paper, to reduce the amount of tests
    testConfig.disableAll();
    testConfig.enableCheck = true;
    testConfig.enableDecode = true;

#ifdef TEST8
    {
        uint16_t AUserInv = static_cast<uint16_t>(ext_euclidean<uint32_t>(static_cast<uint32_t>(AUser), 16));
        std::cout << "# A=" << AUser << " A^-1=" << AUserInv << std::endl;

        DataGenerationConfiguration dataGenConfig8(5, 3, 2, 0); /* TODO we do not check for overflows or underflows ANYWHERE, yet :-(*/
        AlignedBlock bufRawdata8(numElements * sizeof(uint8_t), 64);
        AlignedBlock bufEncoded8(3 * numElements * sizeof(uint8_t), 64); // Coding may generate thrice (since CRC) as much encoded output data as raw input data
        AlignedBlock bufResult8(3 * numElements * sizeof(uint8_t), 64);// Coding may generate thrice (since CRC) as much encoded result data as raw input data (or the same amount as encoded data)

        WarmUp<CopyTest8, UNROLL_LO, UNROLL_HI>("CopyTest8", "Copy", bufRawdata8, bufEncoded8, bufResult8, testConfig, dataGenConfig8);

        std::clog << "# 8-bit Baseline (memcpy / memcmp) test:" << std::endl;
        TestCase<CopyTest8, UNROLL_LO, UNROLL_HI>("CopyTest8", "Copy", bufRawdata8, bufEncoded8, bufResult8, testConfig, dataGenConfig8, vecTestInfos);
        size_t refIdx = vecTestInfos.size() - 1;

        // 8-bit data sequential tests
        std::clog << "# 8-bit scalar tests:" << std::endl;
        TestCase<XOR_scalar_8_8, UNROLL_LO, UNROLL_HI>("XOR_scalar_8_8", "XOR Scalar", bufRawdata8, bufEncoded8, bufResult8, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_scalar_8_16_u_divmod, UNROLL_LO, UNROLL_HI>("AN_scalar_8_16_u_divmod", "AN Scalar U DivMod", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_scalar_8_16_s_divmod, UNROLL_LO, UNROLL_HI>("AN_scalar_8_16_s_divmod", "AN Scalar S DivMod", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_scalar_8_16_u_inv, UNROLL_LO, UNROLL_HI>("AN_scalar_8_16_u_inv", "AN Scalar U Inv", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_scalar_8_16_s_inv, UNROLL_LO, UNROLL_HI>("AN_scalar_8_16_s_inv", "AN Scalar S Inv", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<Hamming_scalar_8, UNROLL_LO, UNROLL_HI>("Hamming_scalar_8", "Hamming Scalar", bufRawdata8, bufEncoded8, bufResult8, testConfig, dataGenConfig8, vecTestInfos, refIdx);
#ifdef TESTCRC
        TestCase<CRC16_scalar_8, UNROLL_LO, UNROLL_HI>("CRC16_scalar_8", "CRC16 Scalar", bufRawdata8, bufEncoded8, bufResult8, testConfig, dataGenConfig8, vecTestInfos, refIdx);
#endif

#ifdef __SSE4_2__
        // 8-bit data vectorized tests
        std::clog << "# 8-bit SSE4.2 tests:" << std::endl;
        TestCase<XOR_sse42_8x8_8x8, UNROLL_LO, UNROLL_HI>("XOR_sse42_16x8_16x8", "XOR SSE4.2", bufRawdata8, bufEncoded8, bufResult8, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_sse42_8_16_u_divmod, UNROLL_LO, UNROLL_HI>("AN_sse42_8_16_u_divmod", "AN SSE4.2 U DivMod", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_sse42_8_16_s_divmod, UNROLL_LO, UNROLL_HI>("AN_sse42_8_16_s_divmod", "AN SSE4.2 S DivMod", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_sse42_8_16_u_inv, UNROLL_LO, UNROLL_HI>("AN_sse42_8_16_u_inv", "AN SSE4.2 U Inv", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_sse42_8_16_s_inv, UNROLL_LO, UNROLL_HI>("AN_sse42_8_16_s_inv", "AN SSE4.2 S Inv", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<Hamming_sse42_8, UNROLL_LO, UNROLL_HI>("Hamming_sse42_8", "Hamming SSE4.2", bufRawdata8, bufEncoded8, bufResult8, testConfig, dataGenConfig8, vecTestInfos, refIdx);
#endif

#ifdef __AVX2__
        std::clog << "# 8-bit AVX2 tests:" << std::endl;
        TestCase<XOR_avx2_8x8_8x8, UNROLL_LO, UNROLL_HI>("XOR_avx2_32x8_32x8", "XOR AVX2", bufRawdata8, bufEncoded8, bufResult8, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_avx2_8_16_u_divmod, UNROLL_LO, UNROLL_HI>("AN_avx2_8_16_u_divmod", "AN AVX2 U DivMod", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_avx2_8_16_s_divmod, UNROLL_LO, UNROLL_HI>("AN_avx2_8_16_s_divmod", "AN AVX2 S DivMod", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_avx2_8_16_u_inv, UNROLL_LO, UNROLL_HI>("AN_avx2_8_16_u_inv", "AN AVX2 U Inv", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<AN_avx2_8_16_s_inv, UNROLL_LO, UNROLL_HI>("AN_avx2_8_16_s_inv", "AN AVX2 S Inv", bufRawdata8, bufEncoded8, bufResult8, AUser, AUserInv, testConfig, dataGenConfig8, vecTestInfos, refIdx);
        TestCase<Hamming_avx2_8, UNROLL_LO, UNROLL_HI>("Hamming_avx2_8", "Hamming AVX2", bufRawdata8, bufEncoded8, bufResult8, testConfig, dataGenConfig8, vecTestInfos, refIdx);
#endif
    }
#endif /* TEST8 */

#ifdef TEST16
    {
        uint32_t AUserInv = static_cast<uint32_t>(ext_euclidean<uint64_t>(AUser, 32));
        std::cout << "# A=" << AUser << " A^-1=" << AUserInv << std::endl;

        DataGenerationConfiguration dataGenConfig16(11, 5, 4, 0); /* TODO we do not check for overflows or underflows ANYWHERE, yet :-(*/
        AlignedBlock bufRawdata16(numElements * sizeof(uint16_t), 64);
        AlignedBlock bufEncoded16(3 * numElements * sizeof(uint16_t), 64); // Coding may generate thrice (since CRC) as much encoded output data as raw input data
        AlignedBlock bufResult16(3 * numElements * sizeof(uint16_t), 64);// Coding may generate thrice (since CRC) as much encoded result data as raw input data (or the same amount as encoded data)

        WarmUp<CopyTest16, UNROLL_LO, UNROLL_HI>("CopyTest16", "Copy", bufRawdata16, bufEncoded16, bufResult16, testConfig, dataGenConfig16);

        std::clog << "# 16-bit Baseline (memcpy / memcmp) test:" << std::endl;
        TestCase<CopyTest16, UNROLL_LO, UNROLL_HI>("CopyTest16", "Copy", bufRawdata16, bufEncoded16, bufResult16, testConfig, dataGenConfig16, vecTestInfos);
        size_t refIdx = vecTestInfos.size() - 1;

        // 16-bit data sequential tests
        std::clog << "# 16-bit scalar tests:" << std::endl;
        TestCase<XOR_scalar_16_16, UNROLL_LO, UNROLL_HI>("XOR_scalar_16_16", "XOR Scalar", bufRawdata16, bufEncoded16, bufResult16, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_scalar_16_32_u_divmod, UNROLL_LO, UNROLL_HI>("AN_scalar_16_32_u_divmod", "AN Scalar U DivMod", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_scalar_16_32_s_divmod, UNROLL_LO, UNROLL_HI>("AN_scalar_16_32_s_divmod", "AN Scalar S DivMod", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_scalar_16_32_u_inv, UNROLL_LO, UNROLL_HI>("AN_scalar_16_32_u_inv", "AN Scalar U Inv", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_scalar_16_32_s_inv, UNROLL_LO, UNROLL_HI>("AN_scalar_16_32_s_inv", "AN Scalar S Inv", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<Hamming_scalar_16, UNROLL_LO, UNROLL_HI>("Hamming_scalar_16", "Hamming Scalar", bufRawdata16, bufEncoded16, bufResult16, testConfig, dataGenConfig16, vecTestInfos, refIdx);
#ifdef TESTCRC
        TestCase<CRC32_scalar_16, UNROLL_LO, UNROLL_HI>("CRC32_scalar_16", "CRC32 Scalar", bufRawdata16, bufEncoded16, bufResult16, testConfig, dataGenConfig16, vecTestInfos, refIdx);
#endif

#ifdef __SSE4_2__
        // 16-bit data vectorized tests
        std::clog << "# 16-bit SSE4.2 tests:" << std::endl;
        TestCase<XOR_sse42_8x16_8x16, UNROLL_LO, UNROLL_HI>("XOR_sse42_8x16_8x16", "XOR SSE4.2", bufRawdata16, bufEncoded16, bufResult16, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_sse42_16_32_u_divmod, UNROLL_LO, UNROLL_HI>("AN_sse42_16_32_u_divmod", "AN SSE4.2 U DivMod", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_sse42_16_32_s_divmod, UNROLL_LO, UNROLL_HI>("AN_sse42_16_32_s_divmod", "AN SSE4.2 S DivMod", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_sse42_16_32_u_inv, UNROLL_LO, UNROLL_HI>("AN_sse42_16_32_u_inv", "AN SSE4.2 U Inv", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_sse42_16_32_s_inv, UNROLL_LO, UNROLL_HI>("AN_sse42_16_32_s_inv", "AN SSE4.2 S Inv", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<Hamming_sse42_16, UNROLL_LO, UNROLL_HI>("Hamming_sse42_16", "Hamming SSE4.2", bufRawdata16, bufEncoded16, bufResult16, testConfig, dataGenConfig16, vecTestInfos, refIdx);
#endif

#ifdef __AVX2__
        std::clog << "# 16-bit AVX2 tests:" << std::endl;
        TestCase<XOR_avx2_16x16_16x16, UNROLL_LO, UNROLL_HI>("XOR_avx2_16x16_16x16", "XOR AVX2", bufRawdata16, bufEncoded16, bufResult16, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_avx2_16_32_u_divmod, UNROLL_LO, UNROLL_HI>("AN_avx2_16_32_u_divmod", "AN AVX2 U DivMod", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_avx2_16_32_s_divmod, UNROLL_LO, UNROLL_HI>("AN_avx2_16_32_s_divmod", "AN AVX2 S DivMod", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_avx2_16_32_u_inv, UNROLL_LO, UNROLL_HI>("AN_avx2_16_32_u_inv", "AN AVX2 U Inv", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<AN_avx2_16_32_s_inv, UNROLL_LO, UNROLL_HI>("AN_avx2_16_32_s_inv", "AN AVX2 S Inv", bufRawdata16, bufEncoded16, bufResult16, AUser, AUserInv, testConfig, dataGenConfig16, vecTestInfos, refIdx);
        TestCase<Hamming_avx2_16, UNROLL_LO, UNROLL_HI>("Hamming_avx2_16", "Hamming AVX2", bufRawdata16, bufEncoded16, bufResult16, testConfig, dataGenConfig16, vecTestInfos, refIdx);
#endif
    }
#endif /* TEST16 */

#ifdef TEST32
    {
        uint64_t AUserInv = static_cast<uint64_t>(ext_euclidean<uint128_t>(static_cast<uint128_t>(AUser), 64));
        std::cout << "# A=" << AUser << " A^-1=" << AUserInv << std::endl;

        DataGenerationConfiguration dataGenConfig32(26, 6, 5, 0); /* TODO we do not check for overflows or underflows ANYWHERE, yet :-(*/
        AlignedBlock bufRawdata32(numElements * sizeof(uint32_t), 64);
        AlignedBlock bufEncoded32(3 * numElements * sizeof(uint32_t), 64); // Coding may generate twice as much encoded output data as raw input data
        AlignedBlock bufResult32(3 * numElements * sizeof(uint32_t), 64);// Coding may generate twice as much encoded result data as raw input data (or the same amount as encoded data)

        WarmUp<CopyTest32, UNROLL_LO, UNROLL_HI>("CopyTest32", "Copy", bufRawdata32, bufEncoded32, bufResult32, testConfig, dataGenConfig32);

        std::clog << "# 32-bit Baseline (memcpy / memcmp) test:" << std::endl;
        TestCase<CopyTest32, UNROLL_LO, UNROLL_HI>("CopyTest32", "Copy", bufRawdata32, bufEncoded32, bufResult32, testConfig, dataGenConfig32, vecTestInfos);
        size_t refIdx = vecTestInfos.size() - 1;

        std::clog << "# 32-bit Scalar tests:" << std::endl;
        // 32-bit data sequential tests
        TestCase<XOR_scalar_32_32, UNROLL_LO, UNROLL_HI>("XOR_scalar_32_32", "XOR Scalar", bufRawdata32, bufEncoded32, bufResult32, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_scalar_32_64_u_divmod, UNROLL_LO, UNROLL_HI>("AN_scalar_32_64_u_divmod", "AN Scalar U DivMod", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_scalar_32_64_s_divmod, UNROLL_LO, UNROLL_HI>("AN_scalar_32_64_s_divmod", "AN Scalar S DivMod", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_scalar_32_64_u_inv, UNROLL_LO, UNROLL_HI>("AN_scalar_32_64_u_inv", "AN Scalar U Inv", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_scalar_32_64_s_inv, UNROLL_LO, UNROLL_HI>("AN_scalar_32_64_s_inv", "AN Scalar S Inv", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<Hamming_scalar_32, UNROLL_LO, UNROLL_HI>("Hamming_scalar_32", "Hamming Scalar", bufRawdata32, bufEncoded32, bufResult32, testConfig, dataGenConfig32, vecTestInfos, refIdx);
#ifdef TESTCRC
        TestCase<CRC32_scalar_32, UNROLL_LO, UNROLL_HI>("CRC32_scalar_32", "CRC32 Scalar", bufRawdata32, bufEncoded32, bufResult32, testConfig, dataGenConfig32, vecTestInfos, refIdx);
#endif

#ifdef __SSE4_2__
        std::clog << "# 32-bit SSE4.2 tests:" << std::endl;
        // 32-bit data vectorized tests
        TestCase<XOR_sse42_4x32_4x32, UNROLL_LO, UNROLL_HI>("XOR_sse42_4x32_4x32", "XOR SSE4.2", bufRawdata32, bufEncoded32, bufResult32, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_sse42_32_64_u_divmod, UNROLL_LO, UNROLL_HI>("AN_sse42_32_64_u_divmod", "AN SSE4.2 U DivMod", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_sse42_32_64_s_divmod, UNROLL_LO, UNROLL_HI>("AN_sse42_32_64_s_divmod", "AN SSE4.2 S DivMod", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_sse42_32_64_u_inv, UNROLL_LO, UNROLL_HI>("AN_sse42_32_64_u_inv", "AN SSE4.2 U Inv", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_sse42_32_64_s_inv, UNROLL_LO, UNROLL_HI>("AN_sse42_32_64_s_inv", "AN SSE4.2 S Inv", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<Hamming_sse42_32, UNROLL_LO, UNROLL_HI>("Hamming_sse42_32", "Hamming SSE4.2", bufRawdata32, bufEncoded32, bufResult32, testConfig, dataGenConfig32, vecTestInfos, refIdx);
#endif

#ifdef __AVX2__
        std::clog << "# 32-bit AVX2 tests:" << std::endl;
        TestCase<XOR_avx2_8x32_8x32, UNROLL_LO, UNROLL_HI>("XOR_avx2_8x32_8x32", "XOR AVX2", bufRawdata32, bufEncoded32, bufResult32, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_avx2_32_64_u_divmod, UNROLL_LO, UNROLL_HI>("AN_avx2_32_64_u_divmod", "AN AVX2 U DivMod", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_avx2_32_64_s_divmod, UNROLL_LO, UNROLL_HI>("AN_avx2_32_64_s_divmod", "AN AVX2 S DivMod", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_avx2_32_64_u_inv, UNROLL_LO, UNROLL_HI>("AN_avx2_32_64_u_inv", "AN AVX2 U Inv", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<AN_avx2_32_64_s_inv, UNROLL_LO, UNROLL_HI>("AN_avx2_32_64_s_inv", "AN AVX2 S Inv", bufRawdata32, bufEncoded32, bufResult32, AUser, AUserInv, testConfig, dataGenConfig32, vecTestInfos, refIdx);
        TestCase<Hamming_avx2_32, UNROLL_LO, UNROLL_HI>("Hamming_avx2_32", "Hamming AVX2", bufRawdata32, bufEncoded32, bufResult32, testConfig, dataGenConfig32, vecTestInfos, refIdx);
#endif
    }
#endif /* TEST32 */

    printResults<false>(testConfig, vecTestInfos);
    std::cout << "\n\n";
    printResults<true>(testConfig, vecTestInfos);
}

ext: cpp


text:
#include "camerastream.h"
#include <string>
#include <QMutex>
#include <fstream>
#include <QThread>
#include <stdio.h>
#include <numeric>
#include <iostream>
#include <stdlib.h>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <list>
#include <boost/lexical_cast.hpp>
#include <opencv2/opencv.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "basicblob.hpp"

CameraStream::CameraStream(){}
CameraStream::~CameraStream(){}

using namespace cv;
using namespace std;

void CameraStream::VideoOpenning(int NumCams)
{
    // Open the videofile to check if it exists
    cap.open(InputPath);
    if (!cap.isOpened()) {
        cout << "Could not open video file " << InputPath << endl;
        exit(EXIT_FAILURE);
    }

    // Extract information from VideoCapture
    Width = cap.get(CAP_PROP_FRAME_WIDTH);
    Height = cap.get(CAP_PROP_FRAME_HEIGHT);
    FrameRate = cap.get(CAP_PROP_FPS);
    FrameNumber = cap.get(CAP_PROP_FRAME_COUNT);

    // Extract the dataset path
    vector<size_t> characterLocations;
    for(size_t i =0; i < InputPath.size(); i++){
        if(InputPath[i] == '/')
            characterLocations.push_back(i);
    }

    size_t Pos = characterLocations[characterLocations.size() - 2];
    VideoPath = InputPath.substr(0, Pos);

    if(CameraPanning){
        // Load and save CameraViews to a vector
        for(int i = 1; i <= NViews; i++){
            Mat CameraFrame = imread(VideoPath + "/Homography Images/Camera " + to_string(CameraNumber) + "/View " + to_string(i) + ".jpg");

            // Check for invalid input
            if(! CameraFrame.data ){
                cout << "Could not open Camera Views files with the following path:" << endl;
                cout << (VideoPath + "/Homography Images/Camera " + to_string(CameraNumber) + "/View " + to_string(i) + ".jpg") << endl;
                exit(EXIT_FAILURE);
            }
            CameraViewsVector.push_back(CameraFrame);
        }
    }

    // Save projected semantic into vector
    for(int i = 1; i <= NumCams; i++){
        Mat SemProjectFrame = imread(VideoPath + "/Projected Semantic Frames/Sem" + to_string(i) + "Median.png");

        // Check if image is not loaded properly
        if(!SemProjectFrame.data){
            cout << "Could not open the temporally filtered maps with the following path:" << endl;
            cout << (VideoPath + "/Projected Semantic Frames/Sem" + to_string(i) + "Median.png") << endl;
        }
        else{
            ProjectedFullSemanticVector.push_back(SemProjectFrame);
        }
    }
}

void CameraStream::getActualSemFrame(string FrameNumber)
{
    int FrameNumber2 = atoi(FrameNumber.c_str()) - 1;
    string SemImagesPath;

    if (FrameNumber2 < 10){
        // Add 000 to the path string
        SemImagesPath = VideoPath + "/Semantic Images/Camera " + to_string(CameraNumber) + "/Camera" + to_string(CameraNumber) + "000" + to_string(FrameNumber2) + ".png";
    }
    else if (FrameNumber2 < 100){
        // Add 00 to the path string
        SemImagesPath = VideoPath + "/Semantic Images/Camera " + to_string(CameraNumber) + "/Camera" + to_string(CameraNumber) + "00" + to_string(FrameNumber2) + ".png";
    }
    else if (FrameNumber2 < 1000){
        // Add 0 to the path string
        SemImagesPath = VideoPath + "/Semantic Images/Camera " + to_string(CameraNumber) + "/Camera" + to_string(CameraNumber) + "0" + to_string(FrameNumber2) + ".png";
    }
    else{
        SemImagesPath = VideoPath + "/Semantic Images/Camera " + to_string(CameraNumber) + "/Camera" + to_string(CameraNumber) + to_string(FrameNumber2) + ".png";
    }
    ActualSemFrame = imread(SemImagesPath);

    // Check for invalid input
    if(! ActualSemFrame.data ){
        cout << "Could not open the actual semantic frame with the following path:" << endl;
        cout << SemImagesPath << endl;
        exit(EXIT_FAILURE);
    }
}

void CameraStream::extractPDMask(Mat ActualSemFrame, string DatasetName)
{
    Mat SemanticImageGray;

    // Find pedestrian mask
    // - TERRACE DATASET (label 7)
    // - PETS 2012 DATASET (label 13)
    // - WILDTRACK DATASET (label 13)
    // - RLC DATASET (label 15)
    int PedestrianLabel;
    if (!DatasetName.compare("Terrace"))
        PedestrianLabel = 7;
    else if((DatasetName.find("PETS2012") != string::npos) || !DatasetName.compare("Wildtrack"))
        PedestrianLabel = 13;
    else if(!DatasetName.compare("RLC"))
        PedestrianLabel = 15;

    cvtColor(ActualSemFrame, SemanticImageGray , COLOR_BGR2GRAY);
    compare(SemanticImageGray, PedestrianLabel, PedestrianMask, CMP_EQ);
}

void CameraStream::computeHomography()
{
    if(CameraPanning){
        // Compute homogrpahy by relating points from image and world
        string MainPath = VideoPath + "/Homography Images";

        for (int CameraView = 1; CameraView <= NViews; CameraView++){
            vector<Point2f> pts_src, pts_dst;
            string XCoord, YCoord;

            // CAMERA FRAME POINTS
            string FileName = MainPath + "/Camera " + to_string(CameraNumber) + "/View " + to_string(CameraView) + "_PtsSrcFile.txt";
            ifstream input(FileName);

            if (!input) {
                // The file does not exists
                cout << "Problem with the following path:" << endl;
                cout << FileName << endl;
                cout << "The file that should contain homography points for Camera " + to_string(CameraNumber) + " Frame do not exist" << endl;
                exit(EXIT_FAILURE);
            }

            // Start decoding the file with src points
            while (input >> XCoord){
                input >> YCoord;
                Point2f pt;
                pt.x = atoi(XCoord.c_str());
                pt.y = atoi(YCoord.c_str());
                pts_src.push_back(pt);
            }

            // CENITAL FRAME POINTS
            FileName = MainPath + "/Camera " + to_string(CameraNumber) + "/View " + to_string(CameraView) + "_PtsDstFile.txt";
            ifstream input2(FileName);

            if (!input2) {
                // The file does not exists
                cout << "Problem with the following path:" << endl;
                cout << FileName << endl;
                cout << "The file that should contain homography points for Cenital Frame for camera " + to_string(CameraNumber) + " do not exist" << endl;
                exit(EXIT_FAILURE);
            }

            // Start decoding the file with dst points
            while (input2 >> XCoord){
                input2 >> YCoord;
                Point2f pt;
                pt.x = atoi(XCoord.c_str());
                pt.y = atoi(YCoord.c_str());
                pts_dst.push_back(pt);
            }

            if (pts_dst.size() != pts_src.size()){
                cout << "The number of homography points for Camera " + to_string(CameraNumber) + " is not the same in source and destiny" << endl;
                exit(EXIT_FAILURE);
            }

            // Calculate Homography and store it in the vector
            HomographyVector.push_back(findHomography(pts_src, pts_dst, LMEDS));

            // Check the homography by warping the view and drawing points //

            Mat View = imread(VideoPath + "/Homography Images/Camera " + to_string(CameraNumber) + "/View " + to_string(CameraView) + ".jpg");

            // Check for invalid input
            if(! View.data ){
                cout << "Could not open homography view files with the following path:" << endl;
                cout << (VideoPath + "/Homography Images/Camera " + to_string(CameraNumber) + "/View " + to_string(CameraView) + ".jpg") << endl;
                exit(EXIT_FAILURE);
            }

            Mat ImageWarping = Mat::zeros(986, 1606, CV_8UC1);
            Mat Homografia = HomographyVector[CameraView-1];
            warpPerspective(View, ImageWarping, Homografia, ImageWarping.size());

            // Apply Homography to vectors of Points to find the projection
            vector<Point2f> pts_src_projected;
            perspectiveTransform(pts_src, pts_src_projected, Homografia);

            for(int i = 0; i < pts_src.size(); i++){
                Point PuntoImagen = pts_src_projected[i];
                Point PuntoCenital = pts_dst[i];

                // Puntos de la imagen seleccionados proyectados
                circle(ImageWarping, PuntoImagen, 2, Scalar(255,0,0), 4);
                // Puntos de la imagen cenital seleccionados
                circle(ImageWarping, PuntoCenital, 4, Scalar(0,0,255), 4);
            }
            String ImageName = "/Users/alex/Desktop/Vistas Proyectadas/Camera " + to_string(CameraNumber) + "_Vista" + to_string(CameraView) + ".jpg";
            imwrite(ImageName, ImageWarping);
        }
    }
    else{
        // Read and decode homography matrix
        string FileName = VideoPath + "/Homography " + to_string(CameraNumber) + ".txt";
        ifstream input(FileName);

        string AuxString;
        vector<double> MatrixValues;
        Mat HomographyMatrix = Mat::zeros(3, 3, CV_64F);
        // Start decoding the file with homography matrix points
        while (input >> AuxString){
            MatrixValues.push_back(stod(AuxString.c_str()));
        }

        for(int row = 0; row < HomographyMatrix.rows; row++){
            for(int col = 0; col < HomographyMatrix.cols; col++){
                HomographyMatrix.at<double>(row,col) = MatrixValues[row*3 + col];
            }
        }
        HomographyVector.push_back(HomographyMatrix);
    }
}

void CameraStream::ViewSelection(vector<Mat> HomographyVector)
{
    // Compare Actual Frame with all the frames used to extract homographies with AKAZE
    // Extract number of correspondant view to index the homography vectors
    int NMatches;
    vector<Point2f> GoodMatchesPoints1, GoodMatchesPoints2;
    vector<Point2f> GoodMatchesPoints1Def, GoodMatchesPoints2Def;
    vector<vector<Point2f>> VectorGoodMatches1, VectorGoodMatches2;
    vector<int> VectorNMaches;

    for (int CameraView = 0; CameraView < NViews; CameraView++){
        GoodMatchesPoints1.clear();
        GoodMatchesPoints2.clear();

        Mat CameraViewImage = CameraViewsVector[CameraView];
        Mat ViewDescriptor = AKAZEDescriptorsVector[CameraView];
        vector<KeyPoint> ViewKeypoints = AKAZEKeyPointsVector[CameraView];

        Akaze(CameraViewImage, ViewKeypoints, ViewDescriptor, ActualFrame, NMatches, GoodMatchesPoints1, GoodMatchesPoints2, CameraView);

        VectorNMaches.push_back(NMatches);
        VectorGoodMatches1.push_back(GoodMatchesPoints1);
        VectorGoodMatches2.push_back(GoodMatchesPoints2);
    }

    // Sort NMatches vector
    vector<int> SortedNMatches;
    SortedNMatches = VectorNMaches;
    sort(SortedNMatches.begin(), SortedNMatches.end());

    // Extract the first maximum number of matches
    auto MaxNMatches = SortedNMatches.at(NViews-1);

    // Extract maximum positon
    SelectedView = find(VectorNMaches.begin(), VectorNMaches.end(), MaxNMatches) - VectorNMaches.begin();

    // Get the maximum view points for the homography
    GoodMatchesPoints1Def = VectorGoodMatches1[SelectedView];
    GoodMatchesPoints2Def = VectorGoodMatches2[SelectedView];

    if (GoodMatchesPoints1Def.size() > 4){
        // Number of match points between images when selecting homography is more than 4 so we can compute
        // an homography

        // Now that we know the nearest view with respect with the ActualFrame we have to
        // interpolate/trasnform the homography so it is more accurate
        // Convert the ActualFrame to the view perspective
        HomographyBetweenViews = findHomography(GoodMatchesPoints2Def, GoodMatchesPoints1Def, LMEDS);
    }
    Homography = HomographyVector[SelectedView];
}

void CameraStream::ViewSelectionFromTXT(String VideoPath, vector<Mat> HomographyVector, String FrameNumber, String DatasetName)
{
    String ViewsPath = VideoPath + "/SelectedViews" + to_string(CameraNumber) + ".txt";
    ifstream input(ViewsPath);

    if (!input) {
        // The file does not exists
        cout << "The file containing the FastRCNN blobs does not exist. Path: " << ViewsPath << endl;
        exit(EXIT_FAILURE);
    }

    // Auxiliary variables to store the information
    string AuxString;
    int Counter = 0;
    int LineCounter = 0;

    HomographyBetweenViews = Mat::zeros(3, 3, CV_64FC1);

    // Start decoding the file
    while (input >> AuxString){
        switch(Counter)
        {
        case 0:
            // Case for frame number
            if (LineCounter == atoi(FrameNumber.c_str())){
                // Convert ActualSemFrame with the computed homography to be similar to the semantic image from the view
                warpPerspective(ActualSemFrame, ActualSemFrame, HomographyBetweenViews, ActualSemFrame.size());
                return;
            }
            LineCounter++;
            Counter++;
            break;
        case 1:
            // Case for Selected View
            SelectedView = atoi(AuxString.c_str());
            Counter++;
            break;
        case 2:
            // Case for Homography(0,0)
            HomographyBetweenViews.at<double>(0,0) = atof(AuxString.c_str());
            Counter++;
            break;
        case 3:
            // Case for Homography(0,1)
            HomographyBetweenViews.at<double>(0,1) = atof(AuxString.c_str());
            Counter++;
            break;
        case 4:
            // Case for Homography(0,2)
            HomographyBetweenViews.at<double>(0,2) = atof(AuxString.c_str());
            Counter++;
            break;
        case 5:
            // Case for Homography(1,0)
            HomographyBetweenViews.at<double>(1,0) = atof(AuxString.c_str());
            Counter++;
            break;
        case 6:
            // Case for Homography(1,1)
            HomographyBetweenViews.at<double>(1,1) = atof(AuxString.c_str());
            Counter++;
            break;
        case 7:
            // Case for Homography(1,2)
            HomographyBetweenViews.at<double>(1,2) = atof(AuxString.c_str());
            Counter++;
            break;
        case 8:
            // Case for Homography(2,0)
            HomographyBetweenViews.at<double>(2,0) = atof(AuxString.c_str());
            Counter++;
            break;
        case 9:
            // Case for Homography(2,1)
            HomographyBetweenViews.at<double>(2,1) = atof(AuxString.c_str());
            Counter++;
            break;
        case 10:
            // Case for Homography(2,2)
            HomographyBetweenViews.at<double>(2,2) = atof(AuxString.c_str());
            Homography = HomographyVector[SelectedView];

            Counter++;

            // Restart the couter to read frame
            Counter = 0;
            break;
        }
    }
}

void CameraStream::saveWarpImages(Mat ActualFrame, String FrameNumber, Mat ImageWarping)
{
    // Extract image warping
    warpPerspective(ActualFrame, ImageWarping, HomographyBetweenViews, ImageWarping.size());
    warpPerspective(ImageWarping, ImageWarping, Homography, ImageWarping.size());

    String ImageName = VideoPath + "/Wrapped Images/Camera " + to_string(CameraNumber) + "/Frame" + FrameNumber + ".png";
    imwrite(ImageName, ImageWarping);
}

void CameraStream::SemanticCommonPoints(String DatasetName)
{
    // Check if Temporally Filtered Maps were loaded
    if(ProjectedFullSemanticVector.empty()){
        CommonSemanticAllCameras = Mat::zeros(5000, 5000, CV_8UC3);
    }
    else{
        // Extract common points between cameras with the offline projected semantic images
        int Rows = ProjectedFullSemanticVector[0].rows;
        int Cols = ProjectedFullSemanticVector[0].cols;
        int GrayLevel1, GrayLevel2, GrayLevel3, GrayLevel4, GrayLevel5, GrayLevel6, GrayLevel7;

        // Common semantic between the four cameras
        CommonSemanticAllCameras = Mat::zeros(Rows, Cols, ProjectedFullSemanticVector[0].type());
        for (int i = 0; i < Rows; i++){
            for (int j = 0; j < Cols; j++){
                // Extract Semantic Label for pixel. Number of labels depending on the dataset.
                GrayLevel1 = ProjectedFullSemanticVector[0].at<Vec3b>(i,j)[0];
                GrayLevel2 = ProjectedFullSemanticVector[1].at<Vec3b>(i,j)[0];
                if(!DatasetName.compare("Terrace") || !DatasetName.compare("PETS2012_S2_L1")){
                    GrayLevel3 = ProjectedFullSemanticVector[2].at<Vec3b>(i,j)[0];
                    GrayLevel4 = ProjectedFullSemanticVector[3].at<Vec3b>(i,j)[0];
                }
                else if((DatasetName.find("EPS_Hall") != string::npos) || !DatasetName.compare("RLC"))
                    GrayLevel3 = ProjectedFullSemanticVector[2].at<Vec3b>(i,j)[0];
                else if(!DatasetName.compare("Wildtrack")){
                    GrayLevel3 = ProjectedFullSemanticVector[2].at<Vec3b>(i,j)[0];
                    GrayLevel4 = ProjectedFullSemanticVector[3].at<Vec3b>(i,j)[0];
                    GrayLevel5 = ProjectedFullSemanticVector[4].at<Vec3b>(i,j)[0];
                    GrayLevel6 = ProjectedFullSemanticVector[5].at<Vec3b>(i,j)[0];
                    GrayLevel7 = ProjectedFullSemanticVector[6].at<Vec3b>(i,j)[0];
                }

                // Check if all the labels are equal. Depending on the dataset
                if (!DatasetName.compare("Terrace")){
                    if((GrayLevel1 == 3) || (GrayLevel2 == 3) || (GrayLevel3 == 3) || (GrayLevel4 == 3)){
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[0] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[1] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[2] = 3;
                    }
                }
                else if(!DatasetName.compare("PETS2012_S2_L1")){
                    if((GrayLevel1 == 10) || (GrayLevel2 == 10) || (GrayLevel3 == 10) || (GrayLevel4 == 10) ||
                            (GrayLevel1 == 7) || (GrayLevel2 == 7) || (GrayLevel3 == 7) || (GrayLevel4 == 7)){
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[0] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[1] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[2] = 3;
                    }
                }
                else if(!DatasetName.compare("PETS2012_CC")){
                    if((GrayLevel1 == 10) || (GrayLevel2 == 10) || (GrayLevel1 == 7) || (GrayLevel2 == 7) ||
                            (GrayLevel2 == 53)){
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[0] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[1] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[2] = 3;
                    }
                }
                else if((DatasetName.find("EPS_Hall") != string::npos) || !DatasetName.compare("RLC")){
                    if((GrayLevel1 == 4) || (GrayLevel2 == 4) || (GrayLevel3 == 4)){
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[0] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[1] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[2] = 3;
                    }
                }
                else if(!DatasetName.compare("Wildtrack")){
                    if((GrayLevel1 == 12) || (GrayLevel2 == 12) || (GrayLevel3 == 12) || (GrayLevel4 == 12)
                            || (GrayLevel5 == 12) || (GrayLevel6 == 12) || (GrayLevel7 == 12)){
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[0] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[1] = 3;
                        CommonSemanticAllCameras.at<Vec3b>(i,j)[2] = 3;
                    }
                }
            }
        }
    }
    // Save image Results
    String ImageName = VideoPath + "/Projected Semantic Frames/CommonSemantic.png";
    Mat Aux = CommonSemanticAllCameras*20;
    imwrite(ImageName, Aux);
}

void CameraStream::ProjectSemanticPoints(Mat CenitalPlane, String FrameNumber)
{
    // Project all semantic image
    warpPerspective(ActualSemFrame, CenitalPlane, HomographyBetweenViews, CenitalPlane.size());
    warpPerspective(CenitalPlane, CenitalPlane, Homography, CenitalPlane.size());

    String ImageName = VideoPath + "/Projected Semantic Frames/Projected Frames " + to_string(CameraNumber) + "/Frame" + FrameNumber + ".png";
    imwrite(ImageName, CenitalPlane);

    /*
    Mat FloorMask;
    Mat SemanticImageGray;
    vector<Point> FloorPoints;
    vector<Point2f> ProjectedFloor;

    // Find floor mask (label 3) and extract floor coordinates (Point format)
    cvtColor(ActualSemFrame, SemanticImageGray , CV_BGR2GRAY);
    // Floor label
    // - PETS 10,7
    // - Terrace 3
    // - EPS & RLC 4
    compare(SemanticImageGray, 4, FloorMask, CMP_EQ);
    findNonZero(FloorMask == 255, FloorPoints);

    // Convert from Point to Point2f floor coordinates. Auxiliar vector.
    vector<Point2f> FloorPoints2(FloorPoints.begin(), FloorPoints.end());

    if(FloorPoints2.empty())
        return;

    // Apply Homography to vector of Points2f to find the projection of the floor
    perspectiveTransform(FloorPoints2, ProjectedFloor, HomographyBetweenViews);
    perspectiveTransform(ProjectedFloor, ProjectedFloor, Homography);

    // Fill the global vector
    ProjectedFloorVector = ProjectedFloor;
    // Extract number of Floor Points
    NumberFloorPoints = static_cast<int>(ProjectedFloorVector.size());

    // Extract projected floor mask
    Mat ProjectedFloorMask = Mat::zeros(CenitalPlane.rows, CenitalPlane.cols, CV_8U);

    for (int i = 0 ; i < NumberFloorPoints ; i++){
        Point punto = ProjectedFloorVector[i];
        if ((punto.y > 0 && punto.y < ProjectedFloorMask.rows) && (punto.x > 0 && punto.x < ProjectedFloorMask.cols)){
            ProjectedFloorMask.at<uchar>(punto.y, punto.x) = 255;
        }
    }

    // Create the mask that will be filled
    Mat FilledFloorMask = Mat::zeros(CenitalPlane.rows, CenitalPlane.cols, CV_8U);

    // Dilatation and Erosion kernels to fill the mask
    Mat kernel_di = getStructuringElement(MORPH_ELLIPSE, Size(9, 9), Point(-1, -1));
    Mat kernel_ero = getStructuringElement(MORPH_ELLIPSE, Size(9, 9), Point(-1, -1));

    // First dilate to fill then erode to keep the original contour
    dilate(ProjectedFloorMask, FilledFloorMask, kernel_di, Point(-1, -1));
    erode(FilledFloorMask, FilledFloorMask, kernel_ero, Point(-1, -1));

    // Erase previous points
    FloorPoints.clear();
    ProjectedFloor.clear();
    ProjectedFloorVector.clear();

    // Find floor mask and extract floor coordinates (Point format)
    findNonZero(FilledFloorMask == 255, FloorPoints);

    // Convert from Point to Point2f floor coordinates. Auxiliar vector.
    vector<Point2f> FloorPoints3(FloorPoints.begin(), FloorPoints.end());

    // Fill the global vector
    ProjectedFloorVector = FloorPoints3;
    // Extract number of Floor Points
    NumberFloorPoints = static_cast<int>(ProjectedFloorVector.size());
    */
}

void CameraStream::ProjectCommonSemantic(Mat &Frame)
{
    Vec3b Color;
    vector<Point> CommonPoints;
    vector<Point2f> ReProjectedCommonPoints;
    Mat overlay;
    double alpha = 0.2;

    // Select color depending on the CameraNumber
    if (CameraNumber == 1){
        Color.val[0] = 0;
        Color.val[1] = 255;
        Color.val[2] = 0;
    }
    if (CameraNumber == 2){
        Color.val[0] = 255;
        Color.val[1] = 0;
        Color.val[2] = 0;
    }
    if (CameraNumber == 3){
        Color.val[0] = 0;
        Color.val[1] = 0;
        Color.val[2] = 255;
    }

//    // COMMON AREA BETWEEN ALL THE CAMERAS
//    Mat CommonImage1 = imread(VideoPath + "/Projected Semantic Frames/CommonSemantic.png", IMREAD_GRAYSCALE);
//    compare(CommonImage1, 60, CommonImage1, CMP_EQ);

    // Authors ROI
    Mat CommonImage1 = imread(VideoPath + "/Projected Semantic Frames/CommonSemanticAuthors.png", IMREAD_GRAYSCALE);
    compare(CommonImage1, 60, CommonImage1, CMP_EQ);

    warpPerspective(CommonImage1, overlay, Homography.inv(DECOMP_LU), Frame.size());
    warpPerspective(overlay, overlay, HomographyBetweenViews.inv(DECOMP_LU), Frame.size());

    cvtColor(overlay, overlay, cv::COLOR_GRAY2BGR);

    Mat ch1, ch2, ch3; // declare three matrices
    // "channels" is a vector of 3 Mat arrays:
    vector<Mat> channels(3);
    // split img:
    split(overlay, channels);
    // get the channels (follow BGR order in OpenCV)
    ch1 = channels[0];
    ch2 = channels[1];
    ch3 = channels[2];
    // modify channel// then merge
    ch1.setTo(0);
    ch3.setTo(0);

    merge(channels, overlay);

    // Create the convex poligon from array of Point and add transparency to the final image
    addWeighted(overlay, alpha, Frame, 1, 0, Frame);
}

void CameraStream::AkazePointsForViewImages()
{
    for (int CameraView = 0; CameraView < NViews; CameraView++){
        Mat ViewImage = CameraViewsVector[CameraView];
        vector<KeyPoint> kpts1;
        Mat desc1;

        // Compute AKAZE points for the selected view image
        akazeDescriptor = AKAZE::create();
        akazeDescriptor->detectAndCompute(ViewImage, noArray(), kpts1, desc1);

        // Save descriptors for the view image
        AKAZEDescriptorsVector.push_back(desc1);
        AKAZEKeyPointsVector.push_back(kpts1);
    }
}

void CameraStream::Akaze(Mat Image1, vector<KeyPoint> kpts1, Mat desc1, Mat Image2, int &NMatches, vector<Point2f> &GoodMatchesPoints1, vector<Point2f> &GoodMatchesPoints2, int CameraView)
{
    vector<KeyPoint> kpts2;
    Mat desc2;

    akazeDescriptor->setNOctaves(2);
    akazeDescriptor->setNOctaveLayers(1);
    akazeDescriptor->detectAndCompute(Image2, noArray(), kpts2, desc2);

    //  ------------------  //
    // BRUTE FORCE MATCHER  //
    //  ------------------  //
    BFMatcher matcher(NORM_HAMMING);
    vector<vector<DMatch>> nn_matches;
    matcher.knnMatch(desc1, desc2, nn_matches, 5);

    vector<DMatch> good_matches;
    for (size_t i = 0; i < nn_matches.size(); ++i) {
        const float ratio = 0.8; // As in Lowe's paper; can be tuned
        if (nn_matches[i][0].distance < ratio * nn_matches[i][1].distance) {
            good_matches.push_back(nn_matches[i][0]);
        }
    }

    //  ------------------  //
    //  MATCHES COORDINATES //
    //  ------------------  //
    NMatches = good_matches.size();

    // Extract point coordinates from the good matches between ActualFrame and the correspondant ViewFrame
    for (size_t j = 0; j < NMatches; ++j) {
        DMatch Match = good_matches[j];

        int Index1 = Match.queryIdx;
        int Index2 = Match.trainIdx;

        Point2f Point1 = kpts1[Index1].pt;
        Point2f Point2 = kpts2[Index2].pt;

        GoodMatchesPoints1.push_back(Point1);
        GoodMatchesPoints2.push_back(Point2);
    }

    Mat res;
    drawMatches(Image1, kpts1, Image2, kpts2, good_matches, res);
    String ImageName = "/Users/alex/Desktop/AKAZE/Camera " + to_string(CameraNumber) + "/View " + to_string(CameraView) + ".png";
    imwrite(ImageName, res);
}

void CameraStream::extractFGBlobs(Mat fgmask, string CBOption)
{
    // Required variables for connected component analysis
    Point pt;
    Rect RectangleOutput;
    Scalar NewValue = 254;
    Scalar MaxMin = 1;
    int Flag = 8;

    // Clear blob list (to fill with this function)
    vector<Rect> bloblist;
    vector<Rect> bloblist_joined;

    bloblist.clear();
    bloblist_joined.clear();

    // Connected component analysis
    // Scan the FG mask to find blob pixels
    for (int x = 0; x < fgmask.rows; x++){
        for (int y = 0; y < fgmask.cols; y++){

            // Extract connected component (blob)
            // We only analyze foreground pixels
            if ((fgmask.at<uchar>(x,y)) == 255.0) {
                pt.x = y;
                pt.y = x;

                // We use the function to obtain the blob.
                floodFill(fgmask, pt, NewValue, &RectangleOutput, MaxMin, MaxMin, Flag);

                // Increse Rectangle size if method is not Semantic
                if(CBOption.compare("PSPNet")){
                    int PixelIncrease = 25;
                    RectangleOutput.x -= PixelIncrease;
                    RectangleOutput.y -= PixelIncrease;
                    RectangleOutput.width += PixelIncrease * 4;
                    RectangleOutput.height += PixelIncrease * 4;
                }

                // Include blob in 'bloblist'
                bloblist.push_back(RectangleOutput);
            }
        }
    }

    // Iterate through nms until the number of blob do not change
    vector<Rect> resRectsAux1, resRectsAux2;
    resRectsAux1 = bloblist;

    int SizeRectsAux1 = resRectsAux1.size();
    int SizeRectsAux2 = resRectsAux2.size();

    while(SizeRectsAux1 != SizeRectsAux2){
        SizeRectsAux2 = resRectsAux2.size();
        non_max_suppresion(resRectsAux1, resRectsAux2);
        resRectsAux1 = resRectsAux2;
        SizeRectsAux1 = resRectsAux1.size();
    }

    bloblist_joined = resRectsAux2;

    vector<Rect> bloblist_joined_filtered;
    // Suppress small boxes
    for (size_t i = 0; i < bloblist_joined.size(); i++) {
        Rect rect = bloblist_joined[i];
        //if (rect.area() > 5000)
        bloblist_joined_filtered.push_back(rect);
    }
    FGBlobs = bloblist_joined_filtered;
    return;
}

void CameraStream::CheckSemanticInBlobs(vector<cvBlob> &srcBlobStructure, Mat ForegroundMask)
{
    if(srcBlobStructure.empty())
        return;

    for(size_t n = 0; n < srcBlobStructure.size(); n++){
        cvBlob SBB = srcBlobStructure[n];
        // If detection is obtained by multi-camera fusion
        if(SBB.OriginalCamera != 15){
            Mat CroppedMask = ForegroundMask(SBB.Blob);
            float Sum = sum(CroppedMask)[0];
            if(Sum <= 0){
                srcBlobStructure.erase(srcBlobStructure.begin() + n);
                n--;
            }
        }
        // If detection is obtained from only one camera
        else{
            Mat CroppedMask = ForegroundMask(SBB.Blob);
            float Sum = sum(CroppedMask)[0];
            if(Sum <= 0){
                srcBlobStructure[n].Score *= 0.75;
            }
        }
    }
    return;
}

void CameraStream::non_max_suppresion(const vector<Rect> &srcRects, vector<Rect> &resRects)
{
    resRects.clear();
    const size_t size = srcRects.size();
    if (srcRects.empty())
        return;

    float thresh = 0.2;
    int neighbors = 0;

    // Sort the bounding boxes by the bottom - right y - coordinate of the bounding box
    multimap<int, size_t> idxs;
    for (size_t i = 0; i < size; ++i) {
        idxs.insert(pair<int, size_t>(srcRects[i].br().y, i));
    }

    // keep looping while some indexes still remain in the indexes list
    while (idxs.size() > 0) {
        // grab the last rectangle
        auto lastElem = --end(idxs);
        const Rect& rect1 = srcRects[lastElem->second];

        int neigborsCount = 0;
        idxs.erase(lastElem);

        for (auto pos = begin(idxs); pos != end(idxs);){
            // grab the current rectangle
            const Rect& rect2 = srcRects[pos->second];

            float intArea = (rect1 & rect2).area();
            float unionArea = rect1.area() + rect2.area() - intArea;
            float overlap = intArea / unionArea;

            // if there is sufficient overlap, suppress the current bounding box
            if (overlap > thresh) {
                pos = idxs.erase(pos);
                ++neigborsCount;
            }
            else {
                ++pos;
            }
        }
        if (neigborsCount >= neighbors)
        {
            resRects.push_back(rect1);
        }
    }
}

void CameraStream::non_max_suppresion_scores(String CBOption, const vector<Rect> &srcRects, const vector<double> &srcScores, vector<Rect> &resRects, vector<double> &resScores)
{
    resRects.clear();
    resScores.clear();

    const size_t size = srcRects.size();
    if (!size)
        return;

    if (srcRects.size() != srcScores.size()) {
        cout << "NMS  ERROR. Sizes of detection vector and score vector are not the same." << endl;
        exit(EXIT_FAILURE);
    }

    float minScoresSum;
    if (!CBOption.compare("HOG")){
        minScoresSum = 0.5104;
    }
    else if(!CBOption.compare("FastRCNN")){
        minScoresSum = 0.3;
    }
    else if(!CBOption.compare("DPM")){
        minScoresSum = -3.6239;
    }
    else if(!CBOption.compare("ACF")){
        minScoresSum = -7.3918;
    }
    else if(!CBOption.compare("PSPNet")){
        minScoresSum = 0.5924;
    }

    float thresh = 0.2;
    int neighbors = 0;

    // Sort the bounding boxes by the detection score. Higher score first
    multimap<float, size_t> idxs;
    for (size_t i = 0; i < size; ++i){
        idxs.insert(pair<float, size_t>(srcScores[i], i));
    }

    // keep looping while some indexes still remain in the indexes list
    while (idxs.size() > 0){
        // grab the last rectangle
        auto lastElem = --end(idxs);
        const Rect& rect1 = srcRects[lastElem->second];
        const double& score1 = srcScores[lastElem->second];

        int neigborsCount = 0;
        float scoresSum = lastElem->first;

        idxs.erase(lastElem);

        for (auto pos = begin(idxs); pos != end(idxs); ){
            // grab the current rectangle
            const Rect& rect2 = srcRects[pos->second];

            float intArea = (rect1 & rect2).area();
            float unionArea = rect1.area() + rect2.area() - intArea;
            float overlap = intArea / unionArea;

            // if there is sufficient overlap, suppress the current bounding box
            if (overlap > thresh){
                scoresSum += pos->first;
                pos = idxs.erase(pos);
                ++neigborsCount;
            }
            else{
                ++pos;
            }
        }
        if (neigborsCount >= neighbors && scoresSum >= minScoresSum){
            // Save bounding box and score if conditions are fulfilled
            resRects.push_back(rect1);
            resScores.push_back(score1);
        }
    }
}

void CameraStream::selectBB(const vector<cvBlob> &srcStructure, cvBlob &resBlob, Mat ForegroundMask)
{
    double FunctionValue = -1;
    for(int BBIndex = 0; BBIndex < srcStructure.size(); BBIndex++){
        Rect AuxiliarBB = srcStructure[BBIndex].Blob;
        Mat SelectedForeground = ForegroundMask(AuxiliarBB);

        double Ratio = 0;
        for(int  row = 0; row < SelectedForeground.rows; row++){
            int col = SelectedForeground.cols/2;
            Ratio = Ratio + SelectedForeground.at<uchar>(row,col);
        }

        if(Ratio > FunctionValue){
            FunctionValue = Ratio;
            resBlob = srcStructure[BBIndex];
        }
    }
}