### 用于检测点的“簇”的算法

#### 16 个答案:

``````//load the image
PImage sample;
size(sample.width, sample.height);
image(sample, 0, 0);
int[][] heat = new int[width][height];

//parameters
int resolution = 5; //distance between points in the gridq
int distance = 8; //distance at wich two points are considered near
float threshold = 0.5;
int level = 240; //leven to detect the dots
int sensitivity = 1; //how much does each dot matters

//calculate the "heat" on each point of the grid
color black = color(0,0,0);
for(int a=0; a<width; a+=resolution){
for(int b=0; b<height; b+=resolution){
for(int x=0; x<width; x++){
for(int y=0; y<height; y++){
color c = sample.pixels[y*sample.width+x];
/**
* the heat should be a function of the brightness and the distance,
* but this works (tm)
*/
if(brightness(c)<level && dist(x,y,a,b)<distance){
heat[a][b] += sensitivity;
}
}
}
}
}

//render the output
for(int a=0; a<width; ++a){
for(int b=0; b<height; ++b){
pixels[b*sample.width+a] = color(heat[a][b],0,0);
}
}
updatePixels();
filter(THRESHOLD,threshold);
``````

``````//load the image
PImage sample;
size(sample.width, sample.height);
image(sample, 0, 0);
int[][] heat = new int[width][height];
int dotQ = 0;
int[][] dots = new int[width*height][2];
int X = 0;
int Y = 1;

//parameters
int resolution = 1; //distance between points in the grid
int distance = 20; //distance at wich two points are considered near
float threshold = 0.6;
int level = 240; //minimum brightness to detect the dots
int sensitivity = 1; //how much does each dot matters

//detect all dots in the sample
for(int x=0; x<width; x++){
for(int y=0; y<height; y++){
color c = pixels[y*sample.width+x];
if(brightness(c)<level) {
dots[dotQ][X] += x;
dots[dotQ++][Y] += y;
}
}
}

//calculate heat
for(int x=0; x<width; x+=resolution){
for(int y=0; y<height; y+=resolution){
for(int d=0; d<dotQ; d++){
if(dist(x,y,dots[d][X],dots[d][Y]) < distance)
heat[x][y]+=sensitivity;
}
}
}

//render the output
for(int a=0; a<width; ++a){
for(int b=0; b<height; ++b){
pixels[b*sample.width+a] = color(heat[a][b],0,0);
}
}
updatePixels();
filter(THRESHOLD,threshold);

/** This smooths the ouput with low resolutions
* for(int i=0; i<10; ++i) filter(DILATE);
* for(int i=0; i<3; ++i) filter(BLUR);
* filter(THRESHOLD);
*/
``````

## 在实践中：

OpenCV中提供了均值漂移的实现：

``````int cvMeanShift( const CvArr* prob_image, CvRect window,
CvTermCriteria criteria, CvConnectedComp* comp );
``````

O'Reilly's Learning OpenCv (google book excerpts)对其工作方式也有很好的解释。基本上只是喂你的点图像（prob_image）。

（我认为研究HDRI ToneMapping背后的技术可能是有序的，因为它们或多或少地对光密度起作用，并且有“本地”色调图和“全局”色调图，每个都会产生不同的结果）< / p>

``````1 2 3 2 1
2 4 6 4 2
3 6 9 6 3
2 4 6 4 2
1 2 3 2 1
``````

“较暗”的区域现在可以识别出多个点。

OpenCV支持形态学操作（与一系列图像处理库一样）：

1. 将概率密度函数拟合到数据中。我会使用“高斯混合物”并使用K-means算法引发的期望最大化学习来拟合它。没有EM，K-means本身有时就足够了。需要使用模型订单选择算法来启动集群本身的数量。
2. 然后，可以使用模型用p（x）对每个点进行评分。即得到该点由模型生成的后验概率。
3. 找到最大p（x）以查找群集质心。
4. 这可以使用机器学习工具箱在Matlab等工具中快速编码。在网络/标准文本中广泛讨论了MoG / EM学习/ K-Means聚类。我最喜欢的文字是Duda / Hart的“模式分类”。

<强>一个。问题陈述

<强>弘 情况1：如果点只是点（点= 2D空间中的点）。 在这种情况下，您已经拥有x＆amp; y所有点的位置。问题减少到集中点之一。 Ivan在提出解决方案方面做得很好。他还总结了其他类似风味的答案。 我的帖子除了他的帖子之外，你考虑的是你是否知道先验集群的数量。算法（可以相应地选择监督与非监督聚类）。

“具有一定高密度的区域”意味着您大致了解每单位面积中您认为高的点数。这使我走向网格方法，您将总面积分成适当大小的子区域，然后计算每个区域中的点数。一旦找到靠近阈值的网格区域，您也可以搜索网格的相邻区域。

IMO，网格方法适用于快速和脏的解决方案，但在稀疏数据上非常快速地变得非常饥饿。四棵树更好，但TIN是我个人最喜欢的任何更复杂的分析。

C＃：
public void DocumentBlobRemoval（    矩形区域，    int MinPixelCount，    int MaxPixelCount，    简短MinDensity ）

Cluster 3.0包含一个用于进行统计聚类的C方法库。它有一些不同的方法，可能会或可能不会解决您的问题，加快您的点群集采取什么形式。该库在here可用，并在Python许可下发布。