我是靠谱客的博主 平淡身影,最近开发中收集的这篇文章主要介绍图像分割之区域生长算法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

时间:2020-12-07

1. 流程简述

算法流程:

  1. 选取种子点p(x0,y0),用堆栈表示种子区域,将种子点push到种子堆栈中;
  2. 将种子堆栈中第一个种子点pop出堆栈,并以该点为中心,遍历该中心8邻域像素;
  3. 判断遍历像素点是否已经在种子区域中
    3.1 是,continue
    3.2 否,检查点p(x,y)和种子区域的均值refAvg灰度差是否满足阈值;若满足,将p(x, y) push到堆栈中;若不满足,continue
  4. 计算新的种子区域的均值refAvg,找出离上一个种子"最近"的seed,更新堆栈顺序;
  5. 重复步骤 2-3-4,直至种子堆栈为空。

3. 源码

源码v1.0,目前存在的问题是:

  • 生长过程中,以下代码只会寻找下一个种子(仅一个),取决于迭代的顺序。最终,可能导致分割效果不同。

  • 另一个问题是阈值的选择问题。

修改策略:自适应阈值?全局迭代?后续补充v2.0

int negihborRegionCheck(
unsigned char
*pSrc,
unsigned char
*pDst,
seedInfo_t
*seedPts,
unsigned int
*seedCnt,
imageSize_t
srcSize,
unsigned char
threshold
) {
if (nullptr == pSrc || nullptr == pDst || nullptr == seedPts || nullptr == seedCnt ||
srcSize.width <= 0 || srcSize.height <= 0) {
// input err.
return -1;
}
// malloc buffer for seed list.
seedInfo_t *listSeedPts = (seedInfo_t *)malloc(sizeof(seedInfo_t) * MAX_SEED_NUM);
// get seedPts[]
memcpy(listSeedPts, seedPts, sizeof(seedInfo_t) * (*seedCnt));
// get 1-st seed pts.
int numRegSeedList = *seedCnt;
int resBoundary = 0;
int nbPts[8][2] = { {-1, -1},
{ 0, -1},
{ 1, -1},
{-1,
0},
{ 1,
0},
{-1,
1},
{ 0,
1},
{ 1,
1} };
// get region mean.
float refAvg = listSeedPts[0].var;
while (numRegSeedList > 0) {
#ifdef ENABLE_OPENCV
cv::Mat ori(srcSize.height, srcSize.width, CV_8UC1, (void *)pSrc);
cv::Mat dst(srcSize.height, srcSize.width, CV_8UC1, (void *)pDst);
#endif
// pop a seed.
int x = listSeedPts[0].pts.x;
int y = listSeedPts[0].pts.y;
pDst[y * srcSize.width + x] = 255;
// mark seed.
// iter stack.
for (int k = numRegSeedList - 1; k > 0; k--) {
listSeedPts[k - 1] = listSeedPts[k];
}
listSeedPts[numRegSeedList - 1].pts.x = 0;
listSeedPts[numRegSeedList - 1].pts.y = 0;
listSeedPts[numRegSeedList - 1].var = 0;
numRegSeedList -= 1;
for (int i = 0; i < 8; i++) {
unsigned int xn = x + nbPts[i][0];
unsigned int yn = y + nbPts[i][1];
resBoundary = ((xn >= 0) && (xn <= srcSize.width - 1) &&
(yn >= 0) && (yn <= srcSize.height - 1));
if (resBoundary && pDst[yn * srcSize.width + xn] == 0) {
if (fabs(pSrc[yn * srcSize.width + xn] - refAvg) <= threshold) {
pDst[yn * srcSize.width + xn] = 255;
// add seed to list, push pts in stack.
listSeedPts[numRegSeedList].pts.x = xn;
listSeedPts[numRegSeedList].pts.y = yn;
listSeedPts[numRegSeedList].var = pSrc[yn * srcSize.width + xn];
numRegSeedList += 1;
}
}
}
// find next seed.
int idx = 0;
int minVar = 255;
float sumReg = pSrc[y * srcSize.width + x];
for (int i = 0; i < numRegSeedList; i++) {
if (minVar >= fabs(pSrc[y * srcSize.width + x] - listSeedPts[i].var)) {
minVar = fabs(pSrc[y * srcSize.width + x] - listSeedPts[i].var);
idx = i;
}
sumReg += listSeedPts[i].var;
}
if (sumReg > 0 && numRegSeedList > 0) {
refAvg = sumReg / (numRegSeedList + 1);
}
// update list (swap element).
if (idx > 0) {
int tempVar = listSeedPts[0].var;
int tempX = listSeedPts[0].pts.x;
int tempY = listSeedPts[0].pts.y;
listSeedPts[0].var = listSeedPts[idx].var;
listSeedPts[0].pts.x = listSeedPts[idx].pts.x;
listSeedPts[0].pts.y = listSeedPts[idx].pts.y;
listSeedPts[idx].var = tempVar;
listSeedPts[idx].pts.x = tempX;
listSeedPts[idx].pts.y = tempY;
}
}
if (listSeedPts) {
free(listSeedPts);
}
return 0;
}

最后

以上就是平淡身影为你收集整理的图像分割之区域生长算法的全部内容,希望文章能够帮你解决图像分割之区域生长算法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部