Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 计算图像中唯一颜色数的算法_C#_Algorithm_Image Processing - Fatal编程技术网

C# 计算图像中唯一颜色数的算法

C# 计算图像中唯一颜色数的算法,c#,algorithm,image-processing,C#,Algorithm,Image Processing,寻找一个足够快,仍然优雅的记忆。图像是一个24bpp的System.Drawing.Bitmap。如果你需要一个精确的数字,那么你必须在所有像素上循环。由于颜色的稀疏性,在散列中存储颜色和计数可能是最好的方法 在哈希中使用Color.ToArgb()而不是Color对象可能也是一个好主意 另外,如果速度是一个主要问题,您不想使用像GetPixel(x,y)这样的函数——而是尝试一次(一次一行)处理块。如果可以的话,获取一个指向图像内存开头的指针,这样做是不安全的。在现代图形卡之前,当大多数机器以

寻找一个足够快,仍然优雅的记忆。图像是一个24bpp的System.Drawing.Bitmap。

如果你需要一个精确的数字,那么你必须在所有像素上循环。由于颜色的稀疏性,在散列中存储颜色和计数可能是最好的方法

在哈希中使用Color.ToArgb()而不是Color对象可能也是一个好主意


另外,如果速度是一个主要问题,您不想使用像GetPixel(x,y)这样的函数——而是尝试一次(一次一行)处理块。如果可以的话,获取一个指向图像内存开头的指针,这样做是不安全的。

在现代图形卡之前,当大多数机器以256色调色板模式运行时,这是一个相当有趣的领域。对处理能力和内存的限制施加了一种可能对您有用的约束,因此搜索处理调色板的算法可能会有所帮助。

这取决于您要分析的图像类型。对于24位图像,您将需要高达2MB的内存(因为在最坏的情况下,您必须处理每种颜色)。对于这一点,位图将是最好的主意(您有一个2MB位图,其中每个位对应一种颜色)。这将是一个很好的解决方案,用于具有高颜色计数的图像,可以在O(#像素)内实现。对于16位图像,使用此技术的位图只需要8KB


然而,如果你的图片没有太多的颜色,最好使用其他颜色。但是,您需要进行某种检查,以指示应该使用哪种算法…

以前从未实现过类似的功能,但在我看来,这是一种原始实现:

对于24位图像,图像可能具有的最大颜色数最小为(2^24,图像像素数)

您只需要记录某一特定颜色是否被计数,而不需要记录计数的次数。这意味着您需要1位来记录每种颜色是否计数。这是2MB的内存。迭代像素,在2MB颜色集贴图中设置相关位。最后,循环遍历颜色集映射,对设置位进行计数(如果幸运的话,您将有一条POPCNT指令来帮助实现这一点)

对于较小的图像和较低的颜色深度,最好保留一个颜色表,并对图像中的每种颜色进行计数。

var cnt=new HashSet();
var cnt = new HashSet<System.Drawing.Color>();

foreach (Color pixel in image)
    cnt.Add(pixel);

Console.WriteLine("The image has {0} distinct colours.", cnt.Count);
foreach(图像中的彩色像素) cnt.Add(像素); WriteLine(“图像有{0}种不同的颜色。”,cnt.Count);

/编辑:正如Lou所说,使用
.GetArgb()
而不是
Color
值本身可能会稍微快一点,因为
Color
实现
GetHashCode
的方式使得图像中唯一颜色的最大数量等于像素数量,因此从处理的一开始就可以预测。 使用Konrad提出的HashSet方法似乎是一个合理的解决方案,因为散列的大小不应大于像素数,而使用JeeBee建议的位图方法则需要512 MB的32位图像(如果存在Alpha通道,并且这决定了颜色的独特性)


不过,HashSet方法的性能可能比“每种颜色一位”方法差——您可能想尝试这两种方法,并使用大量不同的图像进行一些基准测试。您没有准确定义唯一的颜色。如果您实际上指的是真正唯一的代码值(而不是视觉上相同的代码值),那么唯一精确的解决方案就是使用其他答案中描述的技术之一来实际计算它们

如果您正在寻找视觉上相似的颜色,这会很快归结为调色板映射问题,即您正在寻找256种最佳的唯一颜色,以最接近地表示原始的全动态颜色范围图像。对于大多数图像,图像从24位减少到1600万种不同的颜色是多么的好如果正确选择了256种颜色,则要开始使用的LOR可以映射到只有256种唯一颜色的图像。正确选择256种颜色的最佳选择(本例中)已经被证明是NP完全的,但是有一些实用的解决方案可以非常接近。搜索一个叫万世杰的家伙的论文和基于他的工作的东西


如果您正在寻找图像中代码值颜色数量的近似值,我将使用无损耗压缩方案压缩图像。压缩比将直接与图像中唯一代码值的数量相关。您甚至不必保留压缩输出,只需沿图像累积字节数即可方法并扔掉实际输出数据。使用一组示例图像作为参考,您可以在压缩比和图像中不同代码值的数量之间建立一个查找表。同样,最后一种技术虽然非常快,但肯定是一种近似值,但它应该有相当好的相关性。

这里的大多数人都有建议的解决方案可能会很快(实际上,仅使用2MB的解决方案在内存使用方面可能是可以接受的,而且非常快;使用哈希的解决方案可能会更快,但肯定会使用2MB以上的内存)。编程总是在内存使用和CPU时间之间进行权衡。如果您愿意“浪费”更多内存,通常可以更快地获得结果,或者通过“浪费”更多计算时间,可以更慢地获得结果,但这通常会为您保障大量内存

这里有一个到目前为止还没有人提出的解决方案。它可能是一个占用内存最少的解决方案(您可以对其进行优化,因此它使用的内存几乎不会超过将图像保留在内存中所需的内存,但是,图像将被更改,尽管您可能不得不这样做)