Exemplo n.º 1
0
void bayer(tkernel<T> & kernel)
{
    static const auto bayer2 = std::array<size_t, 4>({
         1,  3,
         4,  2 });

    static const auto bayer3 = std::array<size_t, 9>({
         3,  7,  4,
         6,  1,  9, 
         2,  8,  5 });

    static const auto bayer4 = std::array<size_t, 16>({
         1,  9,  3, 11,
        13,  5, 15,  7,
         4, 12,  2, 10,
        16,  8, 14,  6 });

    static const auto bayer8 = std::array<size_t, 64>({
         1, 49, 13, 61,  4, 52, 16, 64, 
        33, 17, 45, 29, 36, 20, 48, 32, 
         9, 57,  5, 53, 12, 60,  8, 56, 
        41, 25, 37, 21, 44, 28, 40, 24, 
         3, 51, 15, 63,  2, 50, 14, 62, 
        35, 19, 47, 31, 34, 18, 46, 30, 
        11, 59,  7, 55, 10, 58,  6, 54, 
        43, 27, 39, 23, 42, 26, 38, 22 });

    const auto size = kernel.size();
    if (size != 4 && size != 9 && size != 16 && size != 64)
        return;

    // a copy of the given kernel is used to read and reassign values from
    const auto read_kernel = kernel;

    switch (kernel.size())
    {
    case  4:
        for (size_t i = 0; i <  4; ++i)
            kernel[i] = read_kernel[bayer2[i] - 1];
        break;

    case  9:
        for (size_t i = 0; i < 9; ++i)
            kernel[i] = read_kernel[bayer3[i] - 1];
        break;

    case 16:
        for (size_t i = 0; i < 16; ++i)
            kernel[i] = read_kernel[bayer4[i] - 1];
        break;

    case 64:
        for (size_t i = 0; i < 64; ++i)
            kernel[i] = read_kernel[bayer8[i] - 1];
        break;
    }
}
Exemplo n.º 2
0
size_t poisson_square(tkernel<glm::tvec2<T, P>> & kernel, const unsigned int num_probes)
{
    assert(kernel.depth() == 1);

    const T min_dist = 1 / sqrt(static_cast<T>(kernel.size() * sqrt(2)));
    return poisson_square(kernel, min_dist, num_probes);
}
Exemplo n.º 3
0
        bool inplace_separable_filter(const tkernel& kernel, const range_t<tscalar>& range,
                tmatrix& src, tgetter getter, tsetter setter)
        {
                const int rows = static_cast<int>(src.rows());
                const int cols = static_cast<int>(src.cols());

                const int ksize = static_cast<int>(kernel.size());
                const int krad = ksize / 2;

                if (ksize != (2 * krad + 1))
                {
                        return false;
                }

                std::vector<tscalar> buff(std::max(rows, cols));

                // horizontal filter
                for (int r = 0; r < rows; r ++)
                {
                        for (int c = 0; c < cols; c ++)
                        {
                                buff[c] = math::cast<tscalar>(getter(src(r, c)));
                        }

                        for (int c = 0; c < cols; c ++)
                        {
                                tscalar v = 0;
                                for (int k = -krad; k <= krad; k ++)
                                {
                                        const int cc = math::clamp(k + c, 0, cols - 1);
                                        v += kernel[k + krad] * buff[cc];
                                }

                                src(r, c) = setter(src(r, c), math::cast<tvalue>(range.clamp(v)));
                        }
                }

                // vertical filter
                for (int c = 0; c < cols; c ++)
                {
                        for (int r = 0; r < rows; r ++)
                        {
                                buff[r] = math::cast<tscalar>(getter(src(r, c)));
                        }

                        for (int r = 0; r < rows; r ++)
                        {
                                tscalar v = 0;
                                for (int k = -krad; k <= krad; k ++)
                                {
                                        const int rr = math::clamp(k + r, 0, rows - 1);
                                        v += kernel[k + krad] * buff[rr];
                                }

                                src(r, c) = setter(src(r, c), math::cast<tvalue>(range.clamp(v)));
                        }
                }

                // OK
                return true;
        }
Exemplo n.º 4
0
size_t poisson_square(tkernel<glm::tvec2<T, P>> & kernel, const T min_dist, const unsigned int num_probes)
{
    assert(kernel.depth() == 1);

    std::random_device RD;
    std::mt19937_64 generator(RD());

    std::uniform_real_distribution<> radius_dist(min_dist, min_dist * 2.0);
    std::uniform_real_distribution<> angle_dist(0.0, 2.0 * glm::pi<T>());

    std::uniform_int_distribution<> int_distribute(0, std::numeric_limits<int>::max());

    auto occupancy = poisson_square_map<T, P>{ min_dist };

    size_t k = 0; // number of valid/final points within the kernel
    kernel[k] = glm::tvec2<T, P>(0.5, 0.5);

    auto actives = std::list<size_t>();
    actives.push_back(k);

    occupancy.mask(kernel[k], k);

    while (!actives.empty() && k < kernel.size() - 1)
    {
        // randomly pick an active point
        const auto pick = int_distribute(generator);

        auto pick_it = actives.begin();
        std::advance(pick_it, pick % actives.size());

        const auto active = kernel[*pick_it];


        std::vector<std::tuple<glm::tvec2<T, P>, T>> probes{ num_probes };

        #pragma omp parallel for
        for (int i = 0; i < static_cast<int>(num_probes); ++i)
        {
            const auto r = radius_dist(generator);
            const auto a = angle_dist(generator);

            auto probe = glm::tvec2<T, P>{ active.x + r * cos(a), active.y + r * sin(a) };

            // within square? (tilable)
            if (probe.x < 0.0)
                probe.x += 1.0;
            else if (probe.x >= 1.0)
                probe.x -= 1.0;

            if (probe.y < 0.0)
                probe.y += 1.0;
            else if (probe.y >= 1.0)
                probe.y -= 1.0;

            // Note: do NOT make this optimization
            //if (!tilable && (probe.x < 0.0 || probe.x > 1.0 || probe.y < 0.0 || probe.y > 1.0))
            //    continue;

            // points within min_dist?
            const auto masked = occupancy.masked(probe, kernel);
            const auto delta = glm::abs(active - probe);

            probes[i] = std::make_tuple<glm::tvec2<T, P>, T>(std::move(probe), (masked ? static_cast<T>(-1.0) : glm::dot(delta, delta)));
        }
        
        // pick nearest probe from sample set
        glm::vec2 nearest_probe;
        auto nearest_dist = 4 * min_dist * min_dist;
        auto nearest_found = false;

        for (int i = 0; i < static_cast<int>(num_probes); ++i)
        {
            // is this nearest point yet? - optimized by using square distance -> skipping sqrt
            const auto new_dist = std::get<1>(probes[i]);
            if (new_dist < 0.0 || nearest_dist < new_dist)
                continue;

            if (!nearest_found)
                nearest_found = true;

            nearest_dist = new_dist;
            nearest_probe = std::get<0>(probes[i]);
        }

        if (!nearest_found && (actives.size() > 0 || k > 1))
        {
            actives.erase(pick_it);
            continue;
        }

        kernel[++k] = nearest_probe;
        actives.push_back(k);

        occupancy.mask(nearest_probe, k);
    }

    return k + 1;
}
Exemplo n.º 5
0
void bucket_permutate(tkernel<T> & kernel
    , const glm::uint16 subkernel_width
    , const glm::uint16 subkernel_height
    , const glm::uint16 subkernel_depth
    , const bool permutate_per_bucket)
{
    assert(subkernel_width  > 0);
    assert(subkernel_height > 0);
    assert(subkernel_depth  > 0);

    assert(subkernel_width  <= kernel.width());
    assert(subkernel_height <= kernel.height());
    assert(subkernel_depth  <= kernel.depth());

    assert(kernel.width()  % subkernel_width  == 0);
    assert(kernel.height() % subkernel_height == 0);
    assert(kernel.depth()  % subkernel_depth  == 0);

    // the number of the elements required to fill a sub-kernel is the number of required buckets
    const auto num_buckets = subkernel_width * subkernel_height * subkernel_depth;
    assert(kernel.size() % num_buckets == 0);

    if (num_buckets == 0)
        return;

    std::srand(static_cast<unsigned int>(std::time(0)));

    // the number of sub-kernels is also the number of values per bucket
    const auto num_subkernels = static_cast<int>(kernel.size() / num_buckets);

    // create buckets by sequentially adding every kernel index and shuffling every
    // bucket individually to "randomly" pop back from later on ...
    auto buckets = std::vector<std::vector<size_t>>{ };
    buckets.resize(num_buckets);

    auto index = 0;
    for (int b = 0; b < buckets.size(); ++b)
    {
        for (int i = 0; i < num_subkernels; ++i)
            buckets[b].push_back(index++);

        std::random_shuffle(buckets[b].begin(), buckets[b].end());
    }

    // use permutations to pop the last item of each bucket, while 
    // selecting the bucket based on the subkernels permutation ...

    auto subkernel_indices = std::vector<size_t>{ };
    subkernel_indices.resize(num_buckets);

    // a copy of the given kernel is used to read and reassign values from
    const auto read_kernel = kernel;

    const auto kw_over_w = kernel.width()  / subkernel_width;
    const auto kh_over_h = kernel.height() / subkernel_height;

    const auto w_step = subkernel_width;
    const auto h_step = subkernel_height * kernel.width();
    const auto d_step = subkernel_depth  * kernel.width() * kernel.height();


    // create permutations (or use single, static permutation)
    abstract_permutations * permutations{ nullptr };
    if (permutate_per_bucket)
        permutations = new unique_index_permutations{ num_buckets, num_subkernels };
    else
        permutations = new static_index_permutation{ num_buckets };


    for (int k = 0; k < num_subkernels; ++k)
    {
        const auto offset = w_step * (k % kw_over_w) 
            + h_step * ((k / kw_over_w) % kh_over_h) + d_step * (k / (kw_over_w * kh_over_h));

        // retrieve indices to map subkernel indices to the given kernel
        auto i = 0;
        for (int d = 0; d < subkernel_depth;  ++d)
        for (int h = 0; h < subkernel_height; ++h)
        for (int w = 0; w < subkernel_width; ++w)
            subkernel_indices[i++] = offset + d * kernel.width() * kernel.height() + h * kernel.width() + w;

        for (int i_permutation = 0; i_permutation < num_buckets; ++i_permutation)
        {
            const auto i_bucket = (*permutations)(k, i_permutation);
            const auto i_read   = buckets[i_bucket].back();
            const auto i_kernel = subkernel_indices[i_permutation];

            kernel[i_kernel] = read_kernel[i_read];

            buckets[i_bucket].pop_back();
        }
    }
    delete permutations;
    permutations = nullptr;
}