什么';在C#NET中有什么好的像素化算法?

什么';在C#NET中有什么好的像素化算法?,c#,.net,image-processing,C#,.net,Image Processing,在C#NET中对图像进行像素化的好算法是什么?虽然我不知道这方面有什么好的算法,但我不得不写一些类似的东西。我使用的技术非常简单,但我认为对于大型图像来说效率不是很高。基本上,我会在5个像素块(或者你想要多大)中对图像进行颜色平均,然后使所有这些像素的颜色相同。您可以通过仅对对角线像素进行平均来加快速度,这将节省大量周期,但精度较低。一个简单但无效的解决方案是将大小调整为较小的大小,然后使用像素复制重新调整大小 更好的解决方案是(伪代码): (时间O(n),额外空间(除了可变源图像):O(1))

在C#NET中对图像进行像素化的好算法是什么?

虽然我不知道这方面有什么好的算法,但我不得不写一些类似的东西。我使用的技术非常简单,但我认为对于大型图像来说效率不是很高。基本上,我会在5个像素块(或者你想要多大)中对图像进行颜色平均,然后使所有这些像素的颜色相同。您可以通过仅对对角线像素进行平均来加快速度,这将节省大量周期,但精度较低。

一个简单但无效的解决方案是将大小调整为较小的大小,然后使用像素复制重新调整大小

更好的解决方案是(伪代码):
(时间O(n),额外空间(除了可变源图像):O(1))

//在x轴上像素化(选择一个完整的k s.t.1这个家伙有一个非常好的算法。它的工作原理是取每个“块”中所有颜色的平均值

我今天刚刚在C#/GDI+中使用了他的实现:

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Linq;
using System.Text;

/// <summary>
/// Applies a pixelation effect to an image.
/// </summary>
[SuppressMessage(
    "Microsoft.Naming",
    "CA1704",
    Justification = "'Pixelate' is a word in my book.")]
public class PixelateEffect : EffectBase
{
    /// <summary>
    /// Gets or sets the block size, in pixels.
    /// </summary>
    private int blockSize = 10;

    /// <summary>
    /// Gets or sets the block size, in pixels.
    /// </summary>
    public int BlockSize
    {
        get
        {
            return this.blockSize;
        }

        set
        {
            if (value <= 1)
            {
                throw new ArgumentOutOfRangeException("value");
            }

            this.blockSize = value;
        }
    }

    /// <summary>
    /// Applies the effect by rendering it onto the target bitmap.
    /// </summary>
    /// <param name="source">The source bitmap.</param>
    /// <param name="target">The target bitmap.</param>
    public override void DrawImage(Bitmap source, Bitmap target)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        if (target == null)
        {
            throw new ArgumentNullException("target");
        }

        if (source.Size != target.Size)
        {
            throw new ArgumentException("The source bitmap and the target bitmap must be the same size.");
        }

        using (var graphics = Graphics.FromImage(target))
        {
            graphics.PageUnit = GraphicsUnit.Pixel;

            for (int x = 0; x < source.Width; x += this.BlockSize)
            {
                for (int y = 0; y < source.Height; y += this.BlockSize)
                {
                    var sums = new Sums();

                    for (int xx = 0; xx < this.BlockSize; ++xx)
                    {
                        for (int yy = 0; yy < this.BlockSize; ++yy)
                        {
                            if (x + xx >= source.Width || y + yy >= source.Height)
                            {
                                continue;
                            }

                            var color = source.GetPixel(x + xx, y + yy);
                            sums.A += color.A;
                            sums.R += color.R;
                            sums.G += color.G;
                            sums.B += color.B;
                            sums.T++;
                        }
                    }

                    var average = Color.FromArgb(
                        sums.A / sums.T,
                        sums.R / sums.T,
                        sums.G / sums.T,
                        sums.B / sums.T);

                    using (var brush = new SolidBrush(average))
                    {
                        graphics.FillRectangle(brush, x, y, (x + this.BlockSize), (y + this.BlockSize));
                    }
                }
            }
        }
    }

    /// <summary>
    /// A structure that holds sums for color averaging.
    /// </summary>
    private struct Sums
    {
        /// <summary>
        /// Gets or sets the alpha component.
        /// </summary>
        public int A
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the red component.
        /// </summary>
        public int R
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the blue component.
        /// </summary>
        public int B
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the green component.
        /// </summary>
        public int G
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the total count.
        /// </summary>
        public int T
        {
            get;
            set;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Diagnostics.CodeAnalysis;
使用系统图;
使用System.Linq;
使用系统文本;
/// 
///将像素化效果应用于图像。
/// 
[抑制信息](
“Microsoft.Naming”,
“CA1704”,
正当性=“'Pixelate'是我书中的一个词。”)]
公共类PixelateEffect:EffectBase
{
/// 
///获取或设置块大小(以像素为单位)。
/// 
私有int blockSize=10;
/// 
///获取或设置块大小(以像素为单位)。
/// 
公共整数块大小
{
得到
{
返回此.blockSize;
}
设置
{
如果(值=震源宽度| y+yy>=震源高度)
{
继续;
}
var color=source.GetPixel(x+xx,y+yy);
总和.A+=颜色.A;
sums.R+=color.R;
sums.G+=color.G;
总和.B+=颜色.B;
sums.T++;
}
}
var average=Color.FromArgb(
sums.A/sums.T,
总和R/总和T,
总和G/总和T,
总额B/总额T);
使用(var笔刷=新的SolidBrush(平均))
{
FillRectangle(画笔,x,y,(x+this.BlockSize),(y+this.BlockSize));
}
}
}
}
}
/// 
///保存颜色平均值总和的结构。
/// 
私有结构和
{
/// 
///获取或设置alpha组件。
/// 
公共INTA
{
得到;
设置
}
/// 
///获取或设置红色组件。
/// 
公共INTR
{
得到;
设置
}
/// 
///获取或设置蓝色组件。
/// 
公共int B
{
得到;
设置
}
/// 
///获取或设置绿色组件。
/// 
公共INTG
{
得到;
设置
}
/// 
///获取或设置总计数。
/// 
公共int T
{
得到;
设置
}
}
}

注意清空器,在我的机器上工作等等。

你希望“像素化”是什么意思?你需要多快?好的“收缩和扩展”工作很好,但速度相当慢。如果你只需要做一次,不要想入非非。
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Linq;
using System.Text;

/// <summary>
/// Applies a pixelation effect to an image.
/// </summary>
[SuppressMessage(
    "Microsoft.Naming",
    "CA1704",
    Justification = "'Pixelate' is a word in my book.")]
public class PixelateEffect : EffectBase
{
    /// <summary>
    /// Gets or sets the block size, in pixels.
    /// </summary>
    private int blockSize = 10;

    /// <summary>
    /// Gets or sets the block size, in pixels.
    /// </summary>
    public int BlockSize
    {
        get
        {
            return this.blockSize;
        }

        set
        {
            if (value <= 1)
            {
                throw new ArgumentOutOfRangeException("value");
            }

            this.blockSize = value;
        }
    }

    /// <summary>
    /// Applies the effect by rendering it onto the target bitmap.
    /// </summary>
    /// <param name="source">The source bitmap.</param>
    /// <param name="target">The target bitmap.</param>
    public override void DrawImage(Bitmap source, Bitmap target)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        if (target == null)
        {
            throw new ArgumentNullException("target");
        }

        if (source.Size != target.Size)
        {
            throw new ArgumentException("The source bitmap and the target bitmap must be the same size.");
        }

        using (var graphics = Graphics.FromImage(target))
        {
            graphics.PageUnit = GraphicsUnit.Pixel;

            for (int x = 0; x < source.Width; x += this.BlockSize)
            {
                for (int y = 0; y < source.Height; y += this.BlockSize)
                {
                    var sums = new Sums();

                    for (int xx = 0; xx < this.BlockSize; ++xx)
                    {
                        for (int yy = 0; yy < this.BlockSize; ++yy)
                        {
                            if (x + xx >= source.Width || y + yy >= source.Height)
                            {
                                continue;
                            }

                            var color = source.GetPixel(x + xx, y + yy);
                            sums.A += color.A;
                            sums.R += color.R;
                            sums.G += color.G;
                            sums.B += color.B;
                            sums.T++;
                        }
                    }

                    var average = Color.FromArgb(
                        sums.A / sums.T,
                        sums.R / sums.T,
                        sums.G / sums.T,
                        sums.B / sums.T);

                    using (var brush = new SolidBrush(average))
                    {
                        graphics.FillRectangle(brush, x, y, (x + this.BlockSize), (y + this.BlockSize));
                    }
                }
            }
        }
    }

    /// <summary>
    /// A structure that holds sums for color averaging.
    /// </summary>
    private struct Sums
    {
        /// <summary>
        /// Gets or sets the alpha component.
        /// </summary>
        public int A
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the red component.
        /// </summary>
        public int R
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the blue component.
        /// </summary>
        public int B
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the green component.
        /// </summary>
        public int G
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the total count.
        /// </summary>
        public int T
        {
            get;
            set;
        }
    }
}