Bonjour,
J'ai une carte des altitudes de toute l'Europe que l'on peut apparenter en une image en niveau de gris. Celle-ci fait environ 5 milliards de pixels.
Mon but est de trouver les océans et les grands lac sur cette image. Mon approche est donc de trouver des régions suffisamment grande avec exactement la même altitude.
J'ai fait quelques essais et ça marche plutôt pas mal.
J'ai développé un petit algo tout simple moi-même. Je précise que je découpe d'abord l'image en zone plus petite pour ne pas avoir de buffer trop gros...
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 //Pour chaque pixel de la zone for(int x=0; x<nSizeBuffX; x++) { for(int y=0; y<nSizeBuffY; y++) { //On calcule la position du pixel dans le buffer int nPixPos = y*nSizeBuffX+x; //On init les paramètres int nRegionSize = 0; vRegion.clear(); vPoints2Test.clear(); //Si on n'est pas déjà passé par ce pixel, on regarde la taille de sa région if(!pAlreadyTestMap[nPixPos]) { //On ajoute le premier point à la région POINT newPoint; newPoint.x = x; newPoint.y = y; vPoints2Test.push_back(newPoint); short int nCurAltitude = bufIn[nPixPos]; //Tant qu'il reste des points à tester dans cette région while( vPoints2Test.size()>0 ) { //On ajoute ce pixel à la région et on regarde si les pixels autour font partis de cette région nRegionSize += ComputeRegionSize(bufIn,nSizeBuffX,nSizeBuffY,nCurAltitude, pAlreadyTestMap,vRegion,vPoints2Test); } if( nRegionSize > fWaterMinSizePixels ) { //Si la taille de la région est suffisament grande, on dit que c'est de l'eau SetWater(bufOut,vRegion,nCurAltitude,nSizeBuffX,nSizeBuffY); } } } }
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 int ComputeRegionSize(short int* bufIn, int &nSizeBuffX, int &nSizeBuffY, short int &nCurAltitude, bool* pAlreadyTestMap, vector<POINT> &vRegion, vector<POINT> &vPoints2Test) { int x = vPoints2Test.begin()->x; int y = vPoints2Test.begin()->y; int nRegionSize = 1; int nPixPos = y*nSizeBuffX+x; //On ajoute le point courant à la region pAlreadyTestMap[nPixPos] = true; POINT newPoint; newPoint.x = x; newPoint.y = y; vRegion.push_back(newPoint); //On supprime le point courant des points à tester vPoints2Test.erase(vPoints2Test.begin()); //On teste les points voisins int nNewX = x; int nNewY = y-1; if( nNewX>=0 && nNewX<nSizeBuffX && nNewY>=0 && nNewY<nSizeBuffY ) { int nNewPixPos = nNewY*nSizeBuffX+nNewX; if( !pAlreadyTestMap[nNewPixPos] && nCurAltitude==bufIn[nNewPixPos] ) { //Si jamais testé et même altitude, on les mets dans les points à tester newPoint.x = nNewX; newPoint.y = nNewY; vPoints2Test.push_back(newPoint); pAlreadyTestMap[nNewPixPos] = true; } } nNewX = x-1; nNewY = y; if( nNewX>=0 && nNewX<nSizeBuffX && nNewY>=0 && nNewY<nSizeBuffY ) { int nNewPixPos = nNewY*nSizeBuffX+nNewX; if( !pAlreadyTestMap[nNewPixPos] && nCurAltitude==bufIn[nNewPixPos] ) { //Si jamais testé et même altitude, on les mets dans les points à tester newPoint.x = nNewX; newPoint.y = nNewY; vPoints2Test.push_back(newPoint); pAlreadyTestMap[nNewPixPos] = true; } } nNewX = x; nNewY = y+1; if( nNewX>=0 && nNewX<nSizeBuffX && nNewY>=0 && nNewY<nSizeBuffY ) { int nNewPixPos = nNewY*nSizeBuffX+nNewX; if( !pAlreadyTestMap[nNewPixPos] && nCurAltitude==bufIn[nNewPixPos] ) { //Si jamais testé et même altitude, on les mets dans les points à tester newPoint.x = nNewX; newPoint.y = nNewY; vPoints2Test.push_back(newPoint); pAlreadyTestMap[nNewPixPos] = true; } } nNewX = x+1; nNewY = y; if( nNewX>=0 && nNewX<nSizeBuffX && nNewY>=0 && nNewY<nSizeBuffY ) { int nNewPixPos = nNewY*nSizeBuffX+nNewX; if( !pAlreadyTestMap[nNewPixPos] && nCurAltitude==bufIn[nNewPixPos] ) { //Si jamais testé et même altitude, on les mets dans les points à tester newPoint.x = nNewX; newPoint.y = nNewY; vPoints2Test.push_back(newPoint); pAlreadyTestMap[nNewPixPos] = true; } } return nRegionSize; }
Maintenant, mon problème : il faut 2 jours à mon PC pour traiter tout ça !
Voyez vous quelque chose que je pourrais améliorer pour accélérer le traitement ? Le réduire à quelques heures serait pas mal...
J'aimerais rester sur mon approche, car je la trouve simple et surtout déjà implémentée :-), mais elle est surement assez limitée... donc si vous avez des idées pour tout changer et/ou utiliser des librairies comme opencv, pourquoi pas !
Merci d'avance,
Sylvain
Partager