Ejemplo n.º 1
0
    static bool so_texel_set_contains(so_texel_set_t set, so_texel_t texel)
    {
        int hash = so_texel_hash(texel, set.capacity);

        while (set.texels[hash].x != -1)         // entries with same hash
        {
            if (set.texels[hash].x == texel.x && set.texels[hash].y == texel.y)
            {
                return(true);                // texel is already in the set
            }
            hash = (hash + 1) % set.capacity;
        }
        return(false);
    }
Ejemplo n.º 2
0
    public static bool so_seam_optimize(so_seam_t seam, Color[] data, int w, int h, int c = 3, float lambda = 0.1f)
    {
        so_texel_set_t        texels          = seam.texels;
        so_stitching_points_t stitchingPoints = seam.stitchingPoints;

        int m = stitchingPoints.count;
        int n = texels.count;

        so_texel_t[] texelsFlat = new so_texel_t[n];
        for (int i = 0; i < n; i++)
        {
            texelsFlat[i] = new so_texel_t(0, 0);
        }

        float[] A = new float[(m + n) * 8];

        int[] AsparseIndices = new int[(m + n) * 8];

        float[] b = new float[m + n];

        float[] Atb = new float[n];

        float[] x = new float[n];

        for (int i = 0, j = 0; i < texels.capacity && j < n; i++)
        {
            if (texels.texels[i].x != -1)
            {
                texelsFlat[j++] = texels.texels[i];
            }
        }

        System.Array.Sort(texelsFlat, so_texel_cmp);

        int r = 0;

        for (int i = 0; i < m; i++)
        {
            int[] column0 = { 0, 0, 0, 0 };
            int[] column1 = { 0, 0, 0, 0 };
            bool  side0valid = false, side1valid = false;
            for (int k = 0; k < 4; k++)
            {
                so_texel_t t0 = stitchingPoints.points[i].sides[0].texels[k];
                so_texel_t t1 = stitchingPoints.points[i].sides[1].texels[k];
                column0[k] = System.Array.BinarySearch(texelsFlat, t0, so_texel_cmp);
                column1[k] = System.Array.BinarySearch(texelsFlat, t1, so_texel_cmp);

                if (column0[k] == -1)
                {
                    side0valid = false; break;
                }
                if (column1[k] == -1)
                {
                    side1valid = false; break;
                }

                // test for validity of stitching point
                for (int ci = 0; ci < c; ci++)
                {
                    side0valid |= data[t0.y * w + t0.x][ci] > 0.0f;
                    side1valid |= data[t1.y * w + t1.x][ci] > 0.0f;
                }
            }

            if (side0valid && side1valid)
            {
                for (int k = 0; k < 4; k++)
                {
                    A[r * 8 + k * 2 + 0] = stitchingPoints.points[i].sides[0].weights[k];
                    AsparseIndices[r * 8 + k * 2 + 0] = column0[k];
                    A[r * 8 + k * 2 + 1] = -stitchingPoints.points[i].sides[1].weights[k];
                    AsparseIndices[r * 8 + k * 2 + 1] = column1[k];
                }
                r++;
            }
        }

        m = r;

        // add error terms for deviation from original pixel value (scaled by lambda)
        for (int i = 0; i < n; i++)
        {
            A[(m + i) * 8] = lambda;
            AsparseIndices[(m + i) * 8 + 0] = i;
            AsparseIndices[(m + i) * 8 + 1] = -1;
        }

        so_sparse_entries_t AtA = so_matrix_At_times_A(A, AsparseIndices, 8, m + n, n);
        so_sparse_entries_t L   = so_matrix_cholesky_prepare(AtA, n);

        if (L.count == 0)
        {
            return(false);            // Cholesky decomposition failed
        }

        so_sparse_entries_t Lcols = new so_sparse_entries_t(L.count);

        for (int i = 0; i < L.count; i++)
        {
            so_sparse_matrix_add(Lcols, (L.entries[i].index % n) * n + (L.entries[i].index / n), L.entries[i].value);
        }
        so_sparse_matrix_sort(Lcols);

        // solve each color channel independently
        for (int ci = 0; ci < c; ci++)
        {
            for (int i = 0; i < n; i++)
            {
                b[m + i] = lambda * data[texelsFlat[i].y * w + texelsFlat[i].x][ci];
            }

            so_matrix_At_times_b(A, m + n, n, b, Atb, AsparseIndices, 8);
            so_matrix_cholesky_solve(L, Lcols, x, Atb, n);

            // write out results
            for (int i = 0; i < n; i++)
            {
                data[texelsFlat[i].y * w + texelsFlat[i].x][ci] = Mathf.Max(x[i], 0);
            }
        }

        return(true);
    }
Ejemplo n.º 3
0
    static void so_texel_set_add(so_texel_set_t set, so_texel_t[] texels, int entries, int arrayLength = 0)
    {
        if (set.count + entries > set.capacity * 3 / 4)         // leave some free space to avoid having many collisions
        {
            int newCapacity = set.capacity > 64 ? set.capacity * 2 : 64;
            while (set.count + entries > newCapacity * 3 / 4)
            {
                newCapacity *= 2;
            }

            so_texel_t[] newTexels = new so_texel_t[newCapacity];

            for (int i = 0; i < newCapacity; i++)
            {
                newTexels[i] = new so_texel_t(-1, -1);
            }

            if (set.texels != null)
            {
                for (int i = 0; i < set.capacity; i++)                 // rehash all old texels
                {
                    if (set.texels[i].x != -1)
                    {
                        int hash = so_texel_hash(set.texels[i], newCapacity);
                        while (newTexels[hash].x != -1)                         // collisions
                        {
                            hash = (hash + 1) % newCapacity;
                        }
                        newTexels[hash] = set.texels[i];
                    }
                }
            }

            set.texels   = newTexels;
            set.capacity = newCapacity;
        }

        if (arrayLength == 0)
        {
            arrayLength = entries;
        }

        for (int i = 0; i < arrayLength; i++)
        {
            if (texels[i].x != -1)
            {
                int hash = so_texel_hash(texels[i], set.capacity);
                while (set.texels[hash].x != -1)                 // collisions
                {
                    if (set.texels[hash].x == texels[i].x && set.texels[hash].y == texels[i].y)
                    {
                        break;                         // texel is already in the set
                    }
                    hash = (hash + 1) % set.capacity;
                }

                if (set.texels[hash].x == -1)
                {
                    set.texels[hash] = texels[i];
                    set.count++;
                }
            }
        }
    }