图像分割的定义是将整幅图像区域分割成各自互不交叉的小区域。图像分割的算法有很多,教科书上讲到一些经典的分割算法,包括阈值法、区域生长法、分裂与合并算法、边界跟踪与连接算法、分水岭算法,这些算法适合提取出灰度比较一致的各个区域;此外还有纹理分割算法,严格说来,与其称之为纹理分割还不如称之为纹理检测与分类,通过提取纹理特征,如:Laws特征、梯度共生矩阵特征、分形特征,得到每一个点或小邻域的特征向量,然后利用特征向量将每个点分到不同的纹理类中去。
有些扯远了,还是回到三维图像分割上来,由于三维图像的数据量是巨大的,暂不考虑复杂的纹理特征,我们仅仅希望有在GPU上实现一种并行的快速算法,能够自动标记出三维数据中所有灰度比较一致的各个连通区域。我们先看看教科书上的方法,阈值法不能提取多个灰度不一致的区域,区域生长不容易做到每个区域种子点自动选取,分裂与合并的逻辑稍显复杂且分割的区域边缘会出现锯齿,边界跟踪与连接在三维上根本没办法实现,分水岭又是串行递归的-_-!!!
假设已经是有了一幅二值图,我们就可以用连通区标记的算法,为二值图中的每一个小的区域标上不同的标号,这就是常用的二值图CCL(Connected Component Labeling)算法,可以扫描填充法、FloodFill等方式来具体实现这个算法。算法的原理是,判断当前点的邻域内有没有和当前点取值相同的点,如果有,就把他们标记为相同的标号。利用这个思想,如果在判断的时候,不是判断当前点的邻域内有没有和当前点取值相同的点,而是判断当前点的邻域内有没有和当前点取值相近的点——有点类似于梯度区域生长算法,就可以设计出适用于灰度图像的灰度连通区标记算法灰度图CCL算法,如果对每一个点进行如上判断,就可以预先生成一幅具有二值图,且对每个点的判断不依赖于其它点判断的结果,可以做到完全并行。这一段代码很简单,假设体数据已经做了去噪处理,然后用For循环遍历每一个点就能搞定(对于Cuda实现,就是把最里层的内容写到kernel里面),贴代码:
(全文…)