- gradient 대신 negate시킨 distance map을 사용한다.
- 경계영역 처리를 보완해야 한다.
- distance-map을 충분히 smooth하게 만들어야 한다: mean-filter 반복 적용.
- 참고: https://kipl.tistory.com/66의 구현보다 단순하지만 성능은 떨어진다.
#define insideROI(x, y) ((x) >= 0 && (x) < w && (y) >= 0 && (y) < h)
#define BACKGND 0xFF
int watershed(float *distMap, int w, int h, int *rgnMap) {
const int xend = w - 1, yend = h - 1;
const int nx[] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};
const int ny[] = {-1, -1, -1, 0, 0, 0, 1, 1, 1};
// processing image;
std::vector<float> wbuffer(w * h);
std::vector<float* > procImg(h);
for (int y = 0; y < h; y++)
procImg[y] = &wbuffer[y * w];
// presmooth; 10 iterations;
mean_filter(distMap, w, h, 10, procImg);
// 입력 영상에서 경계는 global maximum으로 설정;
for (int y = 0; y < h; y++ ) procImg[y][0] = procImg[y][xend] = BACKGND;
for (int x = 0; x < w; x++ ) procImg[0][x] = procImg[yend][x] = BACKGND;
// find local minima for each pixel;
int minCnt = 1;
for (int y = 0, pos = 0; y < h; y++) {
for (int x = 0; x < w; x++, pos++) {
float minVal = procImg[y][x];
if (minVal == BACKGND) {
rgnMap[pos] = 1; // background(white);
continue;
}
int minIdx = 4; //current position;
for (int k = 0; k < 9; k++) {
int xx = x + nx[k], yy = y + ny[k];
if (insideROI(xx, yy) && procImg[yy][xx] <= minVal) {
minVal = procImg[yy][xx];
minIdx = k;
}
}
if (minIdx == 4) rgnMap[pos] = ++minCnt; // center(x, y) is a new local minimum;
else rgnMap[pos] = -minIdx; // direction of local-min = "-(dir)"
}
}
// follow gradient downhill for each pixel;
// reset rgnMap to have the id's of local minimum connected with current pixel;
for (int y = 1, pos = y * w; y < yend; y++ ) {
pos++;
for (int x = 1; x < xend; x++, pos++ ) {
int minpos = pos;
while ( rgnMap[minpos] <= 0 ) { //it is not a local minimum.
switch ( rgnMap[minpos] ) {
case 0: minpos += -w - 1; break; // top-lef = downhill direction;
case -1: minpos += -w; break; // top
case -2: minpos += -w + 1; break; // top-right;
case -3: minpos--; break; // left;
case -5: minpos++; break; // right;
case -6: minpos += w - 1; break; // bot-left;
case -7: minpos += w; break; // bot;
case -8: minpos += w + 1; break; // bot-right;
}
}
// speed-up: use a stack to record downhill path.
//assign the id of a local min connected with current pixel;
rgnMap[pos] = rgnMap[minpos];
}
pos++;
}
// rgnMap는 각 픽셀과 연결되는 국소점의 id을 알려주는 lookup table이다;
return ( minCnt );
}
728x90
'Image Recognition' 카테고리의 다른 글
Anisotropic Diffusion Filter (2) (0) | 2024.02.23 |
---|---|
Edge Preserving Smoothing (0) | 2024.02.14 |
Local Ridge Orientation (0) | 2021.02.21 |
Contrast Limited Adaptive Histogram Equalization (CLAHE) (3) | 2021.02.15 |
Fixed-Point Bicubic Interpolation (1) | 2021.01.19 |