Пример #1
0
        static MultiDimFloatTexture makeGaussKernel(int filtersz, float sigma)
        {
            MultiDimFloatTexture kernel = new MultiDimFloatTexture(filtersz, filtersz, 1);
            float sum = 0;

            for (int j = 0; j < filtersz; j++)
            {
                for (int i = 0; i < filtersz; i++)
                {
                    float di = (float)(i - filtersz / 2);
                    float dj = (float)(j - filtersz / 2);
                    float u2 = (di * di + dj * dj) / ((float)filtersz * filtersz);
                    kernel.set((float)Math.Exp(-u2 / (2.0f * sigma * sigma)), i, j, 0);
                    sum += kernel.get(i, j, 0);
                }
            }
            // . normalize
            for (int j = 0; j < filtersz; j++)
            {
                for (int i = 0; i < filtersz; i++)
                {
                    kernel.set(kernel.get(i, j, 0) / sum, i, j, 0);
                }
            }

            return(kernel);
        }
Пример #2
0
        // constructs a neighborhood from a list of offsets
        public void construct(MultiDimFloatTexture t, accessor access, bool checkcrossing, int l, int i, int j)
        {
            //CLM this used to be static...
            s_OffsetTable = new OffsetTableInitializer(Globals.NeighborhoodSynth_NUM_NEIGHBORS);


            m_iI        = (short)i;
            m_iJ        = (short)j;
            m_bCrossing = false;

            int w = t.getWidth();
            int h = t.getHeight();
            int n = 0;

            for (int k = 0; k < T_iNumNeighbors; k++)
            {
                int offsi = s_OffsetTable.m_OffsetTable[k][0];
                int offsj = s_OffsetTable.m_OffsetTable[k][1];

                int ni = 0, nj = 0;
                access.neigh_ij(i, j, offsi, offsj, ref ni, ref nj);
                ni = ((ni % w) + w) % w; // FIXME TODO make this faster
                nj = ((nj % h) + h) % h;

                for (int c = 0; c < T_iC; c++)
                {
                    float v = t.get(ni, nj, c);
                    m_Values[n++] = v;
                }
            }

            // border detection
            // . if the neighborhood crosses the boundary of a non-toroidal texture,
            //    it will not be used as a candidate. Therefore, synthesis will not use it.
            if (checkcrossing) //l < FIRST_LEVEL_WITH_BORDER) // FIXME TODO: how to choose this automatically ?
            {
                int hl = (1 << l);
                if (i < Globals.NeighborhoodSynth_SIZE / 2 * hl || i >= w - Globals.NeighborhoodSynth_SIZE / 2 * hl)
                {
                    m_bCrossing = true;
                }
                if (j < Globals.NeighborhoodSynth_SIZE / 2 * hl || j >= h - Globals.NeighborhoodSynth_SIZE / 2 * hl)
                {
                    m_bCrossing = true;
                }
            }

            Globals.Assert(n == e_numdim);
        }
Пример #3
0
        public MultiDimFloatTexture computeNextMIPMapLevel_GaussianFilter(int filtersz)
        {
            MultiDimFloatTexture filtered = applyGaussianFilter_Separable(filtersz);
            int w = (int)Math.Max(1, m_iW / 2);
            int h = (int)Math.Max(1, m_iH / 2);
            MultiDimFloatTexture tex = new MultiDimFloatTexture(w, h, m_iNumComp);

            for (int v = 0; v < h; v++)
            {
                for (int u = 0; u < w; u++)
                {
                    for (int c = 0; c < m_iNumComp; c++)
                    {
                        tex.set(filtered.get(u * 2, v * 2, c), u, v, c);
                    }
                }
            }
            filtered = null;
            return(tex);
        }
Пример #4
0
        public Quantizer(MultiDimFloatTexture tex, int qbits, float percent)
        {
            Globals.Assert(percent > 0.0f && percent <= 100.0f);
            ScopeTimer tm = new ScopeTimer("[Quantizer]");

            m_Texture   = tex;
            m_Quantized = new MultiDimIntTexture(tex.width(), tex.height(), tex.numComp());

            m_iQBits = qbits;

            m_Mean   = new float[tex.numComp()];
            m_StdDev = new float[tex.numComp()];
            m_Center = new float[tex.numComp()];
            m_Radius = new float[tex.numComp()];

            // . compute std dev and mean of every components

            float [] sum   = new float[tex.numComp()];
            float [] sumsq = new float[tex.numComp()];

            for (int j = 0; j < tex.height(); j++)
            {
                for (int i = 0; i < tex.width(); i++)
                {
                    for (int c = 0; c < tex.numComp(); c++)
                    {
                        float f = tex.get(i, j, c);
                        sum[c]   += f;
                        sumsq[c] += f * f;
                    }
                }
            }

            float num = (float)(tex.width() * tex.height());

            for (int c = 0; c < tex.numComp(); c++)
            {
                m_Mean[c] = sum[c] / num;
                float sqstddev = (sumsq[c] - sum[c] * sum[c] / num) / (num - 1.0f);
                if (sqstddev > BMathLib.cFloatCompareEpsilon)
                {
                    m_StdDev[c] = (float)Math.Sqrt(sqstddev);
                }
                else
                {
                    m_StdDev[c] = 0.0f;
                }
            }

            // . for every component
            //      compute center and radius so that 'percent' samples are within quantization space
            for (int c = 0; c < tex.numComp(); c++)
            {
                float [] samples = new float[tex.width() * tex.height()];
                // add samples to array
                for (int j = 0; j < tex.height(); j++)
                {
                    for (int i = 0; i < tex.width(); i++)
                    {
                        samples[i + j * tex.width()] = tex.get(i, j, c);
                    }
                }

                // sort array
                Sort.RadixSort rs = new Sort.RadixSort();
                rs.Sort(samples);//sort(samples.begin(),samples.end());

                // find left and right elements so that 'percent' elements are inside
                float pout  = ((100.0f - percent) / 2) / 100.0f;
                int   left  = (int)((samples.Length - 1) * pout);
                int   right = (int)((samples.Length - 1) * (1.0f - pout));
                m_Center[c] = (samples[right] + samples[left]) / 2.0f;
                m_Radius[c] = samples[right] - samples[left];
            }

            // . quantize
            int num_outside = 0;

            for (int j = 0; j < tex.height(); j++)
            {
                for (int i = 0; i < tex.width(); i++)
                {
                    if (!quantizePixel(tex.numComp(), tex, tex.getpixIndex(i, j), m_Quantized.getpixIndex(i, j)))
                    {
                        num_outside++;
                    }
                }
            }

            float percent_out = num_outside * 100.0f / (tex.width() * tex.height());


            if (Globals.PRINT_DEBUG_MSG)
            {
                Debug.Print("-----------.>> Quantizer: num outside = " + percent_out + "%");
            }
            tm.destroy();
            tm = null;
        }
Пример #5
0
        // Apply a Gaussian filter of size filtersz - separable implementation
        private MultiDimFloatTexture applyGaussianFilter_Separable(int filtersz)
        {
            // . compute Gauss kernel
            MultiDimFloatTexture kernel = new MultiDimFloatTexture(filtersz, 1, 1);
            float sum = 0;

            for (int i = 0; i < filtersz; i++)
            {
                float di    = (float)(i - filtersz / 2);
                float u2    = (di * di) / ((float)filtersz * filtersz);
                float sigma = 1.0f / 3.0f; // > 3 std dev => assume 0
                kernel.set((float)Math.Exp(-u2 / (2.0f * sigma * sigma)), i, 0, 0);
                sum += kernel.get(i, 0, 0);
            }

            // . normalize
            for (int i = 0; i < filtersz; i++)
            {
                kernel.set(kernel.get(i, 0, 0) / sum, i, 0, 0);
            }

            // . alloc result and tmp buffer (initialized to 0)
            MultiDimFloatTexture tmp = new MultiDimFloatTexture(m_iW, m_iH, m_iNumComp);
            MultiDimFloatTexture res = new MultiDimFloatTexture(m_iW, m_iH, m_iNumComp);

            // . convolve - pass 1  (treat texture as toroidal)
            for (int v = 0; v < m_iH; v++)
            {
                for (int u = 0; u < m_iW; u++)
                {
                    for (int i = 0; i < filtersz; i++)
                    {
                        int x = u + i - filtersz / 2;
                        int y = v;

                        for (int c = 0; c < numComp(); c++)
                        {
                            float val = tmp.get(u, v, c);
                            tmp.set(val + ((float)getmod(x, y, c)) * kernel.get(i, 0, 0), u, v, c);
                        }
                    }
                }
            }
            // . convolve - pass 2  (treat texture as toroidal)
            for (int v = 0; v < m_iH; v++)
            {
                for (int u = 0; u < m_iW; u++)
                {
                    for (int j = 0; j < filtersz; j++)
                    {
                        int x = u;
                        int y = v + j - filtersz / 2;
                        for (int c = 0; c < m_iNumComp; c++)
                        {
                            float val = res.get(u, v, c);
                            res.set(val + ((float)tmp.getmod(x, y, c)) * kernel.get(j, 0, 0), u, v, c);
                        }
                    }
                }
            }

            kernel = null;
            tmp    = null;
            return(res);
        }
Пример #6
0
        // -----------------------------------------------------

        MultiDimFloatTexture enlargeTexture(MultiDimFloatTexture ex, int type)
        {
            ScopeTimer tm = new ScopeTimer("[Exemplar::enlargeTexture]");

            int w = ex.getWidth();
            int h = ex.getHeight();
            MultiDimFloatTexture large = new MultiDimFloatTexture(w * 2, h * 2, ex.numComp());

            for (int j = 0; j < h * 2; j++)
            {
                for (int i = 0; i < w * 2; i++)
                {
                    int ri, rj;

                    // where to read ?
                    if (type == 0)
                    {
                        // Toroidal
                        // ri
                        if (i < w / 2)
                        {
                            ri = (i + w / 2) % w;
                        }
                        else if (i < w + w / 2)
                        {
                            ri = i - w / 2;
                        }
                        else
                        {
                            ri = ((i - w / 2) % w);
                        }
                        // rj
                        if (j < h / 2)
                        {
                            rj = (j + h / 2) % h;
                        }
                        else if (j < h + h / 2)
                        {
                            rj = j - h / 2;
                        }
                        else
                        {
                            rj = ((j - h / 2) % h);
                        }
                    }
                    else
                    {
                        // Mirror
                        // ri
                        if (i < w / 2)
                        {
                            ri = (w / 2 - i);
                        }
                        else if (i < w + w / 2)
                        {
                            ri = i - w / 2;
                        }
                        else
                        {
                            ri = (w - 1 - (i - (w / 2 + w)));
                        }
                        // rj
                        if (j < h / 2)
                        {
                            rj = (h / 2 - j);
                        }
                        else if (j < h + h / 2)
                        {
                            rj = j - h / 2;
                        }
                        else
                        {
                            rj = (h - 1 - (j - (h / 2 + h)));
                        }
                    }

                    for (int c = 0; c < ex.numComp(); c++)
                    {
                        large.set(ex.get(ri, rj, c), i, j, c);
                    }
                }
            }
            tm.destroy();
            tm = null;
            return(large);
        }