コード例 #1
0
ファイル: ImageTransformer.cs プロジェクト: KFlaga/Cam3D
        public MaskedImage TransfromImageForwards(IImage image, bool preserveSize = false)
        {
            MaskedImage undistorted;
            var influences = FindInfluenceMatrix(image.RowCount, image.ColumnCount);
            Matrix<double>[] matrices = new Matrix<double>[image.ChannelsCount];

            if(preserveSize)
            {
                // New image is in old one's coords
                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);
                }

                // Bound processing to smaller of images in each dimesions
                int minX = Math.Max(0, _finalTopLeft.X);
                int maxX = Math.Min(image.ColumnCount, _finalSize.X + _finalTopLeft.X);
                int minY = Math.Max(0, _finalTopLeft.Y);
                int maxY = Math.Min(image.RowCount, _finalSize.Y + _finalTopLeft.Y);
                for(int x = minX; x < maxX; ++x)
                {
                    for(int y = minY; y < maxY; ++y)
                    {
                        double influenceTotal = 0.0;
                        double[] val = new double[image.ChannelsCount];
                        foreach(var inf in influences[y - _finalTopLeft.Y, x - _finalTopLeft.X]) // Move Pu to influence matrix coords
                        {
                            for(int i = 0; i < image.ChannelsCount; ++i)
                                val[i] += image[inf.Yd, inf.Xd, i] * inf.Influence;
                            influenceTotal += inf.Influence;
                        }
                        if(influenceTotal > 0.25)
                        {
                            for(int i = 0; i < image.ChannelsCount; ++i)
                                matrices[i].At(y, x, val[i] / influenceTotal);
                            undistorted.SetMaskAt(y, x, true);
                        }
                        else
                        {
                            undistorted.SetMaskAt(y, x, false);
                        }
                    }
                }
            }
            else
            {
                // New image is in same coords as influence matrix
                for(int i = 0; i < image.ChannelsCount; ++i)
                    matrices[i] = new DenseMatrix(_finalSize.Y, _finalSize.X);
                IImage img = image.Clone();
                for(int i = 0; i < image.ChannelsCount; ++i)
                    img.SetMatrix(matrices[i], i);
                undistorted = new MaskedImage(image.Clone());

                for(int x = 0; x < _finalSize.X; ++x)
                {
                    for(int y = 0; y < _finalSize.Y; ++y)
                    {
                        double influenceTotal = 0.0;
                        double[] val = new double[image.ChannelsCount];
                        foreach(var inf in influences[y, x])
                        {
                            for(int i = 0; i < image.ChannelsCount; ++i)
                                val[i] += image[inf.Yd, inf.Xd, i] * inf.Influence;
                            influenceTotal += inf.Influence;
                        }
                        if(influenceTotal > 0.5)
                        {
                            for(int i = 0; i < image.ChannelsCount; ++i)
                                matrices[i].At(y, x, val[i] / influenceTotal);
                            undistorted.SetMaskAt(y, x, true);
                        }
                        else
                        {
                            undistorted.SetMaskAt(y, x, false);
                        }
                    }
                }
            }

            return undistorted;
        }
コード例 #2
0
ファイル: ImageTransformer.cs プロジェクト: KFlaga/Cam3D
        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;
        }