예제 #1
0
        // Moments vector : [m00, m01, m10, m11, m02, m20, m12, m21, m03, m30]
        Vector<double> ComputeMomentVectorForPatch(IntVector2 centerPixel, IImage image)
        {
            Vector<double> moments = new DenseVector(10);
            // M00 = total_intensity
            // Mpq = sum{x,y}( x^p*y^q*I(x,y) )
            for(int dx = -WindowRadius; dx <= WindowRadius; ++dx)
            {
                for(int dy = -_ybounds[dx + WindowRadius]; dy <= _ybounds[dx + WindowRadius]; ++dy)
                {
                    if(image.HaveValueAt(centerPixel.Y + dy, centerPixel.X + dx))
                    {
                        double val = image[centerPixel.Y + dy, centerPixel.X + dx];
                        moments[m00] += val;
                        moments[m01] += dy * val;
                        moments[m10] += dx * val;

                        moments[m11] += dx * dy * val;
                        moments[m02] += dy * dy * val;
                        moments[m20] += dx * dx * val;

                        moments[m12] += dx * dy * dy * val;
                        moments[m21] += dx * dx * dy * val;
                        moments[m03] += dy * dy * dy * val;
                        moments[m30] += dx * dx * dx * val;
                    }
                }
            }
            return moments;
        }
예제 #2
0
        public MaskedImage TransfromImageBackwards(IImage image, bool preserveSize = false)
        {
            MaskedImage undistorted;
            FindTransformedImageSize(image.RowCount, image.ColumnCount);

            Matrix<double>[] matrices = new Matrix<double>[image.ChannelsCount];
            if(preserveSize)
            {
                undistorted = new MaskedImage(image.Clone());
                for(int i = 0; i < image.ChannelsCount; ++i)
                {
                    matrices[i] = new DenseMatrix(image.RowCount, image.ColumnCount);
                    undistorted.SetMatrix(matrices[i], i);
                }
            }
            else
            {
                IImage img = image.Clone();
                for(int i = 0; i < image.ChannelsCount; ++i)
                {
                    matrices[i] = new DenseMatrix(_finalSize.Y, _finalSize.X);
                    img.SetMatrix(matrices[i], i);
                }
                undistorted = new MaskedImage(image.Clone());
            }

            int R = InterpolationRadius;
            int R21 = R * 2 + 1;
            for(int x = 0; x < matrices[0].ColumnCount; ++x)
            {
                for(int y = 0; y < matrices[0].RowCount; ++y)
                {
                    // Cast point from new image to old one
                    Vector2 oldCoords = Transformation.TransformPointBackwards(new Vector2(x: x, y: y));
                    Vector2 aa = Transformation.TransformPointForwards(oldCoords);

                    IntVector2 oldPixel = new IntVector2(oldCoords);
                    // Check if point is in old image range or points to undefined point
                    if(oldCoords.X < 0 || oldCoords.X > image.ColumnCount ||
                        oldCoords.Y < 0 || oldCoords.Y > image.RowCount ||
                        image.HaveValueAt(oldPixel.Y, oldPixel.X) == false)
                    {
                        // Point out of range, so set to black
                        for(int i = 0; i < image.ChannelsCount; ++i)
                        {
                            matrices[i].At(y, x, 0.0);
                            undistorted.SetMaskAt(y, x, false);
                        }
                    }
                    else
                    {
                        // Interpolate value from patch in old image
                        double[,] influence = new double[R21, R21];
                        double totalInf = 0;
                        // For each pixel in neighbourhood find its distance and influence of Pu on it
                        for(int dx = -R; dx <= R; ++dx)
                        {
                            for(int dy = -R; dy <= R; ++dy)
                            {
                                double distance = _computeDistance(oldCoords, oldPixel.X + dx, oldPixel.Y + dy);
                                influence[dx + R, dy + R] = 1.0 / distance;
                                totalInf += influence[dx + R, dy + R];
                            }
                        }
                        double infScale = 1.0 / totalInf; // Scale influence, so that its sum over all pixels in radius is 1
                        double[] val = new double[image.ChannelsCount];
                        for(int dx = -R; dx <= R; ++dx)
                        {
                            for(int dy = -R; dy <= R; ++dy)
                            {
                                double inf = influence[dx + R, dy + R] * infScale;
                                // Store color for new point considering influence from neighbours
                                int ix = Math.Max(0, Math.Min(image.ColumnCount - 1, oldPixel.X + dx));
                                int iy = Math.Max(0, Math.Min(image.RowCount - 1, oldPixel.Y + dy));
                                for(int i = 0; i < image.ChannelsCount; ++i)
                                {
                                    val[i] += image[iy, ix, i] * inf;
                                }
                            }
                        }
                        for(int i = 0; i < image.ChannelsCount; ++i)
                        {
                            matrices[i].At(y, x, val[i]);
                        }
                    }
                }
            }

            return undistorted;
        }