algoLib/sourceCode/WD_watershed.cpp

506 lines
15 KiB
C++
Raw Normal View History

2025-11-10 22:44:31 +08:00
#if 0
#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <fstream>
using namespace std;
// ͼ<><CDBC><EFBFBD>ߴ<EFBFBD>
const int WIDTH = 256;
const int HEIGHT = 256;
// 8<><38><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const int dx[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int dy[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
// <20><><EFBFBD>ؽṹ
struct Pixel {
int x, y; // <20><><EFBFBD><EFBFBD>
int value; // <20><><EFBFBD><EFBFBD>ֵ(<28>Ҷ<EFBFBD>)
Pixel(int x_, int y_, int v_) : x(x_), y(y_), value(v_) {}
// <20><><EFBFBD>ȶ<EFBFBD><C8B6><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ıȽϺ<C8BD><CFBA><EFBFBD>(С<><D0A1><EFBFBD><EFBFBD>)
bool operator<(const Pixel& other) const {
return value > other.value; // ע<><EFBFBD><E2A3BA><EFBFBD>ȶ<EFBFBD><C8B6><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD>Ǵ󶥶ѣ<F3B6A5B6><D1A3><EFBFBD><EFBFBD>ﷴת<EFB7B4>Ƚ<EFBFBD>
}
};
// <20><>ȡPGM<47><4D>ʽͼ<CABD><CDBC>
bool readPGM(const string& filename, int image[HEIGHT][WIDTH]) {
ifstream file(filename, ios::binary);
if (!file) return false;
string magic;
int w, h, max_val;
file >> magic >> w >> h >> max_val;
if (magic != "P5" || w != WIDTH || h != HEIGHT) return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD>
file.ignore(1);
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ֵ
unsigned char pixel;
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
file.read((char*)&pixel, 1);
image[i][j] = (int)pixel;
}
}
return true;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>ΪPGMͼ<4D><CDBC>
void writePGM(const string& filename, int labels[HEIGHT][WIDTH], int num_labels) {
ofstream file(filename, ios::binary);
file << "P5\n" << WIDTH << " " << HEIGHT << "\n255\n";
// <20><><EFBFBD><EFBFBD>ǩӳ<C7A9>䵽0-255<35><35>Χ
int step = 255 / (num_labels + 1);
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
unsigned char val = (labels[i][j] + 1) * step;
if (labels[i][j] == -1) val = 0; // <20><>ˮ<EFBFBD><CBAE><EFBFBD>߽<EFBFBD>
file.write((char*)&val, 1);
}
}
}
// <20><>ˮ<EFBFBD><CBAE><EFBFBD>㷨ʵ<E3B7A8><CAB5>
int watershed(int image[HEIGHT][WIDTH], int labels[HEIGHT][WIDTH]) {
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9>-1<><31>ʾδ<CABE><CEB4><EFBFBD>ǣ<EFBFBD>0<EFBFBD><30>ʾ<EFBFBD>߽<EFBFBD>
memset(labels, -1, sizeof(int) * HEIGHT * WIDTH);
// <20><><EFBFBD>ȶ<EFBFBD><C8B6><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
priority_queue<Pixel> pq;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>оֲ<D0BE><D6B2><EFBFBD>Сֵ<D0A1><D6B5>Ϊ<EFBFBD><CEAA>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
int current_label = 0;
bool is_min;
// <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>оֲ<D0BE><D6B2><EFBFBD>Сֵ<D0A1><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
is_min = true;
for (int d = 0; d < 8; ++d) {
int ni = i + dx[d];
int nj = j + dy[d];
if (ni >= 0 && ni < HEIGHT && nj >= 0 && nj < WIDTH) {
if (image[ni][nj] < image[i][j]) {
is_min = false;
break;
}
}
}
if (is_min) {
labels[i][j] = current_label++;
pq.push(Pixel(i, j, image[i][j]));
}
}
}
// <20>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD>
while (!pq.empty()) {
Pixel p = pq.top();
pq.pop();
int x = p.x;
int y = p.y;
for (int d = 0; d < 8; ++d) {
int nx = x + dx[d];
int ny = y + dy[d];
if (nx >= 0 && nx < HEIGHT && ny >= 0 && ny < WIDTH) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD>
if (labels[nx][ny] == -1) {
// <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>
labels[nx][ny] = labels[x][y];
pq.push(Pixel(nx, ny, image[nx][ny]));
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѱ<EFBFBD><D1B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>߽<EFBFBD>
else if (labels[nx][ny] != labels[x][y]) {
labels[x][y] = -1; // <20><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>߽<EFBFBD>
}
}
}
}
return current_label;
}
#if 0
<EFBFBD>˵<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD>ˮ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>α<EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD>ĻҶ<EFBFBD>ֵ<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>θ߶ȣ<EFBFBD><EFBFBD>Ҷ<EFBFBD>ֵԽ<EFBFBD>ͱ<EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD>оֲ<EFBFBD><EFBFBD><EFBFBD>Сֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Щ<EFBFBD>dz<EFBFBD>ʼ<EFBFBD><EFBFBD> "<EFBFBD><EFBFBD>ˮ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
<EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD>ʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȶ<EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>ѣ<EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>ӵ͵<EFBFBD><EFBFBD>ߵ<EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD>߽<EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ˮ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>γɷ<EFBFBD>ˮ<EFBFBD><EFBFBD><EFBFBD>߽<EFBFBD>
ʹ<EFBFBD>÷<EFBFBD><EFBFBD><EFBFBD>
׼<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD> 256x256 <EFBFBD><EFBFBD> PGM <EFBFBD><EFBFBD>ʽ<EFBFBD>Ҷ<EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊinput.pgm
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>g++ watershed.cpp - o watershed
<EFBFBD><EFBFBD><EFBFBD>г<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. / watershed
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊoutput.pgm<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD>ͬ<EFBFBD>Ҷȱ<EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD>߽<EFBFBD>Ϊ<EFBFBD><EFBFBD>ɫ
ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>м<EFBFBD><EFBFBD><EFBFBD>Ԥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶԸ<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ʵ<EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ȶ<EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٹ<EFBFBD><EFBFBD>ȷָ<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 8 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><EFBFBD>ָ<EFBFBD>Ч<EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>ɫͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>ת<EFBFBD><EFBFBD>Ϊ<EFBFBD>Ҷ<EFBFBD>ͼ<EFBFBD>ٴ<EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>񣬿<EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>WIDTH<EFBFBD><EFBFBD>HEIGHT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int main() {
int image[HEIGHT][WIDTH];
int labels[HEIGHT][WIDTH];
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC>
if (!readPGM("input.pgm", image)) {
cerr << "<EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD>ȡͼ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>" << endl;
return -1;
}
// ִ<>з<EFBFBD>ˮ<EFBFBD><CBAE><EFBFBD>
int num_labels = watershed(image, labels);
cout << "<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD> " << num_labels << " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" << endl;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
writePGM("output.pgm", labels, num_labels);
cout << "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѱ<EFBFBD><EFBFBD><EFBFBD>Ϊ output.pgm" << endl;
return 0;
}
#endif
#else
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <fstream>
#include <cmath>
#include "SG_baseDataType.h"
#include "SG_baseAlgo_Export.h"
using namespace std;
#if 0
// <20><>ȡPPM<50><4D>ʽͼ<CABD>񣨼򻯰棩
bool readPPM(const string& filename, Image& img) {
ifstream file(filename, ios::binary);
if (!file) return false;
string magic;
int maxVal;
file >> magic >> img.width >> img.height >> maxVal;
if (magic != "P6") return false; // <20><>֧<EFBFBD>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD>PPM
file.ignore(); // <20><><EFBFBD>Ի<EFBFBD><D4BB>з<EFBFBD>
vector<unsigned char> data(img.width * img.height * 3);
file.read((char*)data.data(), data.size());
// תΪ<D7AA>Ҷ<EFBFBD>ͼ<EFBFBD><CDBC>Y = 0.299*R + 0.587*G + 0.114*B<><42>
img.gray.resize(img.height, vector<int>(img.width));
img.markers.resize(img.height, vector<int>(img.width, 0)); // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼΪ0
for (int i = 0; i < img.height; ++i) {
for (int j = 0; j < img.width; ++j) {
int idx = (i * img.width + j) * 3;
int r = data[idx];
int g = data[idx + 1];
int b = data[idx + 2];
img.gray[i][j] = (int)(0.299 * r + 0.587 * g + 0.114 * b);
}
}
return true;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>ΪPPM<50><4D>ʽ
void saveResult(const string& filename, const Image& img) {
ofstream file(filename, ios::binary);
file << "P6\n" << img.width << " " << img.height << "\n255\n";
for (int i = 0; i < img.height; ++i) {
for (int j = 0; j < img.width; ++j) {
if (img.markers[i][j] == -1) { // <20><>ˮ<EFBFBD><CBAE><EFBFBD>߽磨<DFBD><E7A3A8>ɫ<EFBFBD><C9AB>
file.put(255); file.put(0); file.put(0);
}
else { // <20><><EFBFBD>򣨸<EFBFBD><F2A3A8B8>ݱ<EFBFBD><DDB1><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ɲ<EFBFBD>ͬ<EFBFBD><CDAC>ɫ<EFBFBD><C9AB>
int color = (img.markers[i][j] * 50) % 256;
file.put(color);
file.put((color + 85) % 256);
file.put((color + 170) % 256);
}
}
}
}
#endif
// 8<><38><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB>
const int dx[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int dy[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
const int dx4[] = { -1, 0, 0, 1};
const int dy4[] = { 0, -1, 1, 0};
2025-11-10 22:44:31 +08:00
// <20><><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD>Сֵ<D0A1><D6B5>Ϊ<EFBFBD><CEAA>ʼ<EFBFBD><CABC><EFBFBD>ӵ<EFBFBD>
void findMinima(SWD_waterShedImage& img, int& markerCount) {
markerCount = 1; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ID
// <20><><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><D8A3>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD>Сֵ<D0A1><D6B5>8<EFBFBD><38><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>
for (int i = 1; i < img.height - 1; ++i) {
for (int j = 1; j < img.width - 1; ++j) {
if (1 == img.markers[i][j]) //<2F><><EFBFBD><EFBFBD>
continue;
bool isMin = true;
#if 0
for (int d = 0; d < 8; ++d) {
int y = i + dy[d];
int x = j + dx[d];
if (img.gray[y][x] < img.gray[i][j]) {
isMin = false;
break;
}
}
#else
for (int dy = -7; dy < 7; dy++)
{
for (int dx = -7; dx < 7; dx++)
{
int y = i + dy;
int x = j + dx;
if ((x >= 0) && (x < img.width) && (y >= 0) && (y < img.height))
{
if (img.gray[y][x] < img.gray[i][j]) {
isMin = false;
break;
}
}
}
}
#endif
if (isMin) {
// <20><><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>Сֵ
bool hasMarker = false;
for (int d = 0; d < 8; ++d) {
int y = i + dy[d];
int x = j + dx[d];
if (img.markers[y][x] > 1) {
hasMarker = true;
img.markers[y][x] = img.markers[i][j];
break;
}
}
if (!hasMarker) {
img.markers[i][j] = ++markerCount; // <20><><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>
}
}
}
}
}
// <20><>ˮ<EFBFBD><CBAE><EFBFBD><EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void watershed(SWD_waterShedImage& img)
2025-11-10 22:44:31 +08:00
{
int markerCount;
findMinima(img, markerCount); // <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>
// <20><><EFBFBD>Ҷ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>ģ<EFBFBD><C4A3>ˮλ<CBAE><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
vector<pair<int, pair<int, int>>> pixels; // (<28>Ҷ<EFBFBD>ֵ, (x,y))
for (int i = 0; i < img.height; ++i) {
for (int j = 0; j < img.width; ++j) {
pixels.emplace_back(img.gray[i][j], make_pair(j, i));
2025-11-10 22:44:31 +08:00
}
}
sort(pixels.begin(), pixels.end());
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>ִ<EFBFBD><D6B4>עˮ<D7A2><CBAE><EFBFBD><EFBFBD>
for (const auto& p : pixels) {
int x = p.second.first;
int y = p.second.second;
if (img.markers[x][y] > 0) continue; // <20>ѱ<EFBFBD><D1B1>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD>ӵ<EFBFBD>
// <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѱ<EFBFBD><D1B1>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD>
vector<int> neighborMarkers;
for (int d = 0; d < 8; ++d) {
int nx = x + dx[d];
int ny = y + dy[d];
if (nx >= 0 && nx < img.height && ny >= 0 && ny < img.width) {
int m = img.markers[nx][ny];
if (m > 0) {
neighborMarkers.push_back(m);
}
}
}
if (neighborMarkers.empty()) {
continue; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD><EFBFBD>
}
else if (neighborMarkers.size() == 1) {
img.markers[x][y] = neighborMarkers[0]; // <20><><EFBFBD><EFBFBD>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD>
}
else {
// <20><><EFBFBD><EFBFBD><EFBFBD>򽻻㣬<F2BDBBBB><E3A3AC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ˮ<EFBFBD><CBAE>
img.markers[x][y] = -1;
}
}
}
//ģ<><C4A3>עˮ<D7A2><CBAE><EFBFBD><EFBFBD>עˮ<D7A2>ڿ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>ͬˮλע<CEBB><D7A2>
// inlet: עˮ<D7A2><CBAE>
// level: ˮλ
void waterInjection(SWD_waterShedImage& img, SVzNL2DPoint inlet, int level)
{
int py = inlet.y;
int px = inlet.x;
int marker = img.markers[py][px];
std::vector<SVzNL2DPoint> levelPts;
levelPts.push_back(inlet);
int readPtr = 0;
while (readPtr < levelPts.size())
{
SVzNL2DPoint seed = levelPts[readPtr];
readPtr++;
//4<>ڽ<EFBFBD>
for (int d = 0; d < 4; ++d)
{
int nx = seed.x + dx4[d];
int ny = seed.y + dy4[d];
if (ny >= 0 && ny < img.height && nx >= 0 && nx < img.width)
{
if ((img.gray[ny][nx] == level) && (img.markers[ny][nx] == 0))
{
img.markers[ny][nx] = marker;
SVzNL2DPoint nxt_seed = { nx, ny };
levelPts.push_back(nxt_seed);
}
}
}
2025-11-10 22:44:31 +08:00
}
}
2025-11-10 22:44:31 +08:00
bool _checkMarkerExist(std::vector<int>& MarkerLst, int marker)
{
bool exist = false;
for (int i = 0, i_max = (int)MarkerLst.size(); i < i_max; i++)
{
if (MarkerLst[i] == marker)
{
exist = true;
break;
}
}
return exist;
}
2025-11-10 22:44:31 +08:00
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD>з<EFBFBD>ˮ<EFBFBD><CBAE><EFBFBD>
// watershedSeeds:<3A><><EFBFBD>ӵ<EFBFBD>
// maxLevel:<3A><><EFBFBD><EFBFBD>ˮλֵ
void wd_seedWatershed(SWD_waterShedImage& img, std::vector<SSG_2DValueI>& watershedSeeds, int maxLevel, int startMakerID)
{
int markerCount = startMakerID;
int seedSize = (int)watershedSeeds.size();
for (int i = 0; i < seedSize; i++)
{
int px = watershedSeeds[i].x;
int py = watershedSeeds[i].y;
watershedSeeds[i].value = markerCount;
img.markers[py][px] = markerCount; // <20><><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>
int greyValue = img.gray[py][px]; //ˮλ
SVzNL2DPoint inlet = { px, py }; //עˮ<D7A2><CBAE>
waterInjection(img, inlet, greyValue);//עˮ<D7A2><CBAE><EFBFBD><EFBFBD>ͬһˮλ<CBAE><CEBB><EFBFBD>ӵIJ<D3B5><C4B2><EFBFBD>ע<EFBFBD><D7A2>
markerCount++;
}
// <20><><EFBFBD>Ҷ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>ģ<EFBFBD><C4A3>ˮλ<CBAE><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<std::vector<SVzNL2DPoint>> levelPtList;
levelPtList.resize(maxLevel + 1);
for (int y = 0; y < img.height; ++y)
{
for (int x = 0; x < img.width; ++x)
{
int level = img.gray[y][x];
if (level <= maxLevel)
{
SVzNL2DPoint a_pt = { x, y };
levelPtList[level].push_back(a_pt);
}
}
}
while (1)
{
bool allDone = true;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>ִ<EFBFBD><D6B4>עˮ<D7A2><CBAE><EFBFBD><EFBFBD>
for (int i = 0; i <= maxLevel; i++)
{
if (levelPtList[i].size() == 0)
continue;
//<2F><>ͬһˮλ<CBAE><CEBB>level)ִ<>е<EFBFBD><D0B5><EFBFBD>עˮ
bool doInjection = true;
while (doInjection)
{
int injectionNum = 0;
std::vector<SVzNL2DPoint> resiPts;
int ptSize = (int)levelPtList[i].size();
for (int pi = 0; pi < ptSize; pi++)
{
int x = levelPtList[i][pi].x;
int y = levelPtList[i][pi].y;
if (img.markers[y][x] > 0) continue; // <20>ѱ<EFBFBD><D1B1>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD>ӵ<EFBFBD>
// <20>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѱ<EFBFBD><D1B1>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD>
vector<int> neighborMarkers;
for (int d = 0; d < 8; ++d)
{
int nx = x + dx[d];
int ny = y + dy[d];
if (ny >= 0 && ny < img.height && nx >= 0 && nx < img.width)
{
int m = img.markers[ny][nx];
if (m > 0)
{
bool exist = _checkMarkerExist(neighborMarkers, m);
if (false == exist)
neighborMarkers.push_back(m);
}
}
}
if (neighborMarkers.empty())
{
resiPts.push_back(levelPtList[i][pi]);// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><C7A3>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD>
}
else if (neighborMarkers.size() == 1) {
img.markers[y][x] = neighborMarkers[0]; // <20><><EFBFBD><EFBFBD>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD>
injectionNum++;
}
else {
// <20><><EFBFBD><EFBFBD><EFBFBD>򽻻㣬<F2BDBBBB><E3A3AC><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ˮ<EFBFBD><CBAE>
img.markers[y][x] = -1;
injectionNum++;
}
}
levelPtList[i].clear();
levelPtList[i].insert(levelPtList[i].end(), resiPts.begin(), resiPts.end());
if ((injectionNum == 0) || (levelPtList[i].size() == 0))
{
doInjection = false;
if (levelPtList[i].size() > 0)
allDone = false;
}
}
}
if (true == allDone)
break;
}
2025-11-10 22:44:31 +08:00
}
#endif