好的,所以我刚开始考虑如何为Paint.NET实现一个新的图形插件,我需要知道如何在二维的整数数组中找到最常见的整数.是否有内置的C#方式来做到这一点?或者,有没有人有一个光滑的方式来做到这一点?
该数组看起来像这样:
300 300 300 300 300 300 300 0 150 300 300 300 300 300 0 0 150 300 300 300 300 0 0 0 0 300 300 300 0 0 0 0 150 300 300 0 0 0 0 0 150 300 0 0 0 0 0 0 300
我需要知道300是阵列中最常见的数字.如果没有"最常见",则只返回中心数(数组减少将始终为奇数x奇数)0.
我将使用"强力"算法实现这一点,除非你的专家可以更快地提出一些东西.
任何帮助将非常感谢.
谢谢!
编辑:更多信息......
这些值几乎总是非常多样化(比我的示例数组更加多样化).值将在0-360的范围内.根据算法的速度,阵列的大小将是5x5到大约17x17.对于大图像中的每个像素,结果将计算一次......因此更快更好.;)
你切片它至少是O(n*m) - 你将不得不至少看一次每个细胞.节约的地方是在寻找最常见之前累积每个值的计数; 如果你的整数在相对较小的范围内变化(它们是uint16,让我们说),那么你可以简单地使用平面数组而不是地图.
我猜你还可以保留当前最高和最接近的"最常见"和早期候选人的运行计数x,y,只要你小于(n*m) - (xy)的细胞留给看看,因为在那一点上,亚军不可能超过最佳候选人.
像这样的整数运算速度非常快; 即使对于百万像素图像,强力算法也应该只需要几毫秒.
我注意到你已经编辑了你的原始问题,说像素值从0..255 - 在这种情况下,绝对是一个简单的平面阵列; 它足够小,可以轻松放入l1 dcache中,并且可以快速查找平面阵列中的查找.
[编辑]:一旦你建立了直方图阵列,处理"没有最常见的数字"的情况就非常简单了:所有你要做的就是遍历它以找到"最多"和"第二大"常用数字; 如果它们同样频繁,那么根据定义,没有一个最常见的.
const int numLevels = 360; // you said each cell contains a number [0..360) int levelFrequencyCounts[numLevels]; // assume this has been populated such that levelFrequencyCounts[i] = number of cells containing "i" int mostCommon = 0, runnerUp = 0; for (int i = 1 ; i < numLevels ; ++i) { if ( levelFrequencyCounts[i] > levelFrequencyCounts[mostCommon] ) { runnnerUp = mostCommon; mostCommon = i; } } if ( levelFrequencyCounts[mostCommon] != levelFrequencyCounts[runnerUp] ) { return mostCommon; } else { return CenterOfInputData; // (something like InputData[n/2][m/2]) }