| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994 |
- /**********************************************************************\
- Fichier : Plaque.cpp
- Date : 18/04/98
- Version : 1.100
- Description : classe de calcul & affichage d'une épaisseur de plaque
- |**********************************************************************|
- Bugs:
- Notes:
- |**********************************************************************|
- Historique :
- 18/04/98 1.100 : Optimisation (2x plus rapide)
- Suppression de l'utilisation d'une region pour la mesure,
- la figure est trop complexe est beaucoup de points sont
- oubliés (il suffit de l'afficher dans OnDraw pour s'en rendre
- compte).
- Suppression de m_nPointsDedans, qui au vu de l'algo était le nombre
- de points à l'extérieur de la plaque!!
- Réunion de tous les types de mesure de plaque (NB, RGB, manuel) dans
- cette classe
- 07/02/98 1.000 : Première version
- \*******************************************************************/
- /*------------------------------------------------------------------\
- Includes
- \------------------------------------------------------------------*/
- #include <limits>
- #include "PlaqueBase.h"
- #include "Ressource.h"
- #include "MeanEstimate.h"
- #include "CPlaqueResult.h"
- #include "PlaqueResult.h"
- #include "../NR/ToolsMath.h"
- #include "../Container/extendedimage.h"
- #include "stdlib.h"
- #include "stdio.h"
- #include "string.h"
- #define sqr(a) ((a) * (a))
- inline int Distance2D (const Point &pt1, const Point &pt2)
- {
- return int (sqrt((double) sqr(pt1.x - pt2.x) + (double) sqr(pt1.y - pt2.y)));
- }
- CPlaqueBase::CPlaqueBase()
- {
- m_etudie = NULL;
- RAZ();
- m_iTache = 0;
- m_clrVert = 0 | (255 << 16) | (0 << 8);
- m_clrBleue = 0 | (0 << 16) | (255 << 8);
-
- m_debug1 = 1;
- m_debug2 = 2;
- m_debug3 = 3;
- m_debug4 = 4;
- m_debug5 = 5;
- }
- CPlaqueBase::~CPlaqueBase()
- {
- delete[] m_etudie;
- }
- void CPlaqueBase::RAZ()
- {
- m_Etape = etapeRien;
- m_nVecteursTrouves = 0;
- m_nPtLongeantPlaque = 0;
- m_ptInferieur.x = 0;
- m_ptInferieur.y = 0;
- m_pointLimite1.x = 0;
- m_pointLimite1.y = 0;
- m_pointLimite2.x = 0;
- m_pointLimite2.y = 0;
- m_iMax = 0;
- m_IntervallesIntensite[0] = 0;
- m_IntervallesIntensite[1] = 0;
- m_IntervallesIntensite[2] = 0;
- // m_ptList.clear();
- }
- /*----------------------------------------------------------\
- | Mesurer |
- |-----------------------------------------------------------|
- | DESCRIPTION : |
- | On a saisi les segments. Mesurer l'épaisseur de droites |
- | perpendiculaires, jusqu'au 1° pt vert |
- | précédemment coloré par Threshold (). |
- |-----------------------------------------------------------|
- | PARAMETRES : |
- \----------------------------------------------------------*/
- const short NORTHOMAX = 1000;
- const short NMAXERREURS = 3; // Erreurs avant de déclarer le segment fini
- int CPlaqueBase::Mesurer_3 (int iMax)
- {
- short iVector;
- int retour;
-
- m_nSommeLongueurs = 0;
- m_nMesures = 0;
- m_nLongueurMax = 0;
- m_nVecteursTrouves = 0;
- m_nMesuresTotal = 0;
- // m_ptList.clear();
-
- // Seuillage par propagation
- retour = Threshold(iMax);
- // Mesurer les limites de la plaque
- for (iVector = 0; iVector < (m_nPtLongeantPlaque-1); iVector++)
- {
- retour = Mesurer_3_1Segment(m_tPtLongeantPlaque [iVector], m_tPtLongeantPlaque [iVector+1]);
- }
-
- // Et sa surface, son intensité
- retour = CalculerSurfaceEtIntensitePlaque (false);
- return retour;
- }
-
- //***** Mesurer 1 des segments définis / utilisateur
- int CPlaqueBase::Mesurer_3_1Segment (const Point &pt1, const Point &pt2)
- {
- CVector vectSegment(pt1.x, pt1.y, pt2.x, pt2.y);
- CVector vectOrtho;
- Point ptAVerifier;
- long iSegment, iLong;
- bool fFound; // Du segment à mesurer
- int nLongueurSegment;
- int retour;
- retour = 0;
- GraphMeanInit();
- Point pt( pt1.x, pt1.y );
- // Parcourir le segment et, tous les NINTERVALLE, calculer l'épaisseur
- vectOrtho = vectSegment.Orthogonal (pt, m_nSensTrigo); // 0 = sens inverse trigo
- // la vérification de l'appartenance du point à la région de traitement ralentit certainement
- // mais je ne trace apparemment pas les droites de la même manière que Windows et certains
- // points des droites des extrémités n'appartiennent pas à la région
- for (iSegment = 0; iSegment < vectSegment.Norm (); iSegment++)
- {
- vectOrtho.MoveTo(vectSegment [iSegment]);
- m_nMesuresTotal ++;
- // on effectue une mesure seulement lorsque la plaque touche la paroi
- // autrement dit, le premier point du vecteur orthogonal ne doit pas être vert
- ptAVerifier.x = vectOrtho[1].x;
- ptAVerifier.y = vectOrtho[1].y;
- // seules les extrémités des segments devraient poser des problèmes d'appartenance
- if ( m_rgnATraiter.PtInRegion(&ptAVerifier)
- && PointInBufferResult(ptAVerifier)
- && (GetPixelResult(ptAVerifier.x, ptAVerifier.y) != m_clrVert) // [LAU - 13/1/2006]
- )
- {
- fFound = false;
- // on cherche la fin de la plaque (<=> premier point vert rencontré)
- // on s'arrête dès que le point ne fait plus partie de la région de traitement
- for (iLong = 2;(!fFound )&& (iLong < NORTHOMAX) && m_rgnATraiter.PtInRegion (&ptAVerifier); iLong++)
- {
- ptAVerifier.x = vectOrtho [iLong].x;
- ptAVerifier.y = vectOrtho [iLong].y;
-
- if ( PointInBufferResult(ptAVerifier)
- && (GetPixelResult(ptAVerifier.x, ptAVerifier.y) == m_clrVert)
- )
- {
- fFound = true;
- // On a une longueur
- nLongueurSegment = iLong - 1;
- m_nSommeLongueurs += nLongueurSegment;
- m_nMesures ++;
- if ((unsigned int) nLongueurSegment > (unsigned int) m_nLongueurMax)
- m_nLongueurMax = nLongueurSegment;
- if (nLongueurSegment)
- GraphMeanAddMeasure(true, nLongueurSegment);
- m_tbPtsTrouvesFin [m_nVecteursTrouves] = vectOrtho [iLong];
- // Ajouter le segment à ceux à afficher
- /* Point pt;
- pt.x = vectOrtho[iLong].x;
- pt.y = vectOrtho[iLong].y;
- m_ptList.push_back( pt );
- */
- if ((m_nVecteursTrouves + 1) < NBVECTEURSMAX)
- {
- m_nVecteursTrouves++;
- }
- }
- }
- }
- }
- return retour;
- }
- /*----------------------------------------------------------\
- | CalculerSensVecteurs |
- |-----------------------------------------------------------|
- | DESCRIPTION : |
- | Calcule de quel côté est le pt minimum par rapport aux |
- | segments définis par l'utilisateur -> m_nSensTrigo |
- |-----------------------------------------------------------|
- | PARAMETRES : |
- \----------------------------------------------------------*/
- void CPlaqueBase::CalculerSensVecteurs()
- {
- CVector vecteur1erSegment (m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y,
- m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x, m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y);
- if (vecteur1erSegment.m_fHorizontal == true)
- {
- // Vecteur horizontal : au dessus ou en dessous ?
- if (m_tPtLongeantPlaque [0].y < m_ptInferieur.y)
- {
- // En dessous
- if (m_tPtLongeantPlaque [0].x > m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x)
- {
- m_nSensTrigo = 1;
- }
- else
- {
- m_nSensTrigo = 0;
- }
- }
- else
- {
- // Au dessus
- if (m_tPtLongeantPlaque [0].x > m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x)
- {
- m_nSensTrigo = 0;
- }
- else
- {
- m_nSensTrigo = 1;
- }
- }
- }
- else
- {
- // Vecteur vertical : à gauche ou à droite ?
- if (m_tPtLongeantPlaque [0].x < m_ptInferieur.x)
- {
- // à droite
- if (m_tPtLongeantPlaque [0].y > m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y)
- {
- m_nSensTrigo = 0;
- }
- else
- {
- m_nSensTrigo = 1;
- }
- }
- else
- {
- // à gauche
- if (m_tPtLongeantPlaque[0].y > m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].y)
- {
- m_nSensTrigo = 1;
- }
- else
- {
- m_nSensTrigo = 0;
- }
- }
- }
- }
- /*----------------------------------------------------------\
- | SetRegion |
- |-----------------------------------------------------------|
- | DESCRIPTION : |
- | Crée une région polygonale, composée des segments |
- | indiqués par l'utilisateur, de 2 segments sur les côtés, |
- | orthogonaux aux 1° et dernier segments utilisateur, |
- | et de taille suffisante pour que le m_ptInferieur |
- | soit dedans. |
- |-----------------------------------------------------------|
- | PARAMETRES : |
- \----------------------------------------------------------*/
- bool CPlaqueBase::SetRegion
- ( const CVector &vFirst,
- const CVector &vLast,
- int iLength )
- {
- CVector vOrtho;
- Point pt( m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].x, m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].y );
- vOrtho = vLast.Orthogonal (pt, m_nSensTrigo); // 0 = sens inverse trigo
- m_pointLimite1.x = vOrtho[iLength].x;
- m_pointLimite1.x = vOrtho[iLength].x;
- m_pointLimite1.y = vOrtho[iLength].y;
- m_tPtLongeantPlaque[m_nPtLongeantPlaque] = m_pointLimite1;
- pt = Point( m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y );
- vOrtho = vFirst.Orthogonal (pt, m_nSensTrigo); // 0 = sens inverse trigo
- m_pointLimite2.x = vOrtho[iLength].x;
- m_pointLimite2.y = vOrtho[iLength].y;
- m_tPtLongeantPlaque[m_nPtLongeantPlaque+1] = m_pointLimite2;
-
- // Créer le polygone
- m_rgnATraiter.DeleteObject ();
- /*
- m_debug1 = m_nPtLongeantPlaque;
- m_debug2 = m_pointLimite1.x;
- m_debug3 = m_pointLimite1.y;
- m_debug4 = m_pointLimite2.x;
- m_debug5 = m_pointLimite2.y;
- */
- return (m_rgnATraiter.CreatePolygonRgn (m_tPtLongeantPlaque, m_nPtLongeantPlaque + 2));
- } // fin de SetRegion
- int CPlaqueBase::ParametrerRegionATraiter ()
- {
- int retour;
- retour = 0;
-
- assert(m_nPtLongeantPlaque >= 2);
- // Vecteur entre le 1° et le dernier pt utilisateur
- CVector vGlobal (m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y,
- m_tPtLongeantPlaque [m_nPtLongeantPlaque - 1].x, m_tPtLongeantPlaque [m_nPtLongeantPlaque - 1].y),
- // Dernier vecteur tracé (peut être égal à vGlobal)
- vFirst (m_tPtLongeantPlaque[0].x, m_tPtLongeantPlaque[0].y,
- m_tPtLongeantPlaque[1].x, m_tPtLongeantPlaque[1].y),
- // Dernier vecteur tracé (peut être égal à vFirst)
- vLast (m_tPtLongeantPlaque[m_nPtLongeantPlaque - 2].x, m_tPtLongeantPlaque[m_nPtLongeantPlaque - 2].y,
- m_tPtLongeantPlaque[m_nPtLongeantPlaque - 1].x, m_tPtLongeantPlaque[m_nPtLongeantPlaque - 1].y);
-
- Point ptProjected;
- int nLongueurPlaque, nDistanceAPtInferieur;
- bool fResult;
- CalculerSensVecteurs ();
- // Longueur de la plaque indiquée par l'utilisateur
- nLongueurPlaque = int(vGlobal.Norm());
-
- // Limiter la longueur des segments de côté
- Point pti( m_ptInferieur.x, m_ptInferieur.y );
- ptProjected.x = vGlobal.Projected (pti).x;
- ptProjected.y = vGlobal.Projected (pti).y;
- nDistanceAPtInferieur = int (CVector (ptProjected.x, ptProjected.y, m_ptInferieur.x,m_ptInferieur.y).Norm () + 5);
- if (nDistanceAPtInferieur > nLongueurPlaque)
- nLongueurPlaque = nDistanceAPtInferieur;
- // pour optimiser, on diminue la taille des droites orthogonales d'encadrement
- // pour que la tache soit à la limite
- nLongueurPlaque++;
- do
- {
- nLongueurPlaque--;
- fResult = SetRegion (vFirst, vLast, nLongueurPlaque);
- } while ((fResult == true) && m_rgnATraiter.PtInRegion (&m_ptInferieur) && (nLongueurPlaque > 1));
- if ((fResult == true) && (nLongueurPlaque > 1))
- {
- nLongueurPlaque++;
- fResult = SetRegion (vFirst, vLast, nLongueurPlaque);
- }
- if (fResult == true)
- {
- retour = 40;
-
- m_debug1 = nLongueurPlaque;
- m_debug2 = ptProjected.x;
- m_debug3 = ptProjected.y;
- m_debug4 = nDistanceAPtInferieur;
- m_debug5 = 2222;
- }
- if ((fResult == false) || (nLongueurPlaque <= 1))
- {
- retour = 41;
- m_Etape = etapeSegments;
- m_nPtLongeantPlaque = 0;
- }
- else if (m_rgnATraiter.PtInRegion(&m_ptInferieur) == false)
- {
- retour = 42;
- m_Etape = etapeTacheSeuil; // Recommencer cette étape
- }
- return retour;
- }
- /*----------------------------------------------------------\
- | TraiterPoint |
- |-----------------------------------------------------------|
- | DESCRIPTION : |
- | Propagation à partir du pt minimal : colorer en vert les |
- | points sous le seuil indiqué |
- | |
- | modifié pour limiter la profondeur de récursion |
- |-----------------------------------------------------------|
- | PARAMETRES : |
- \----------------------------------------------------------*/
- int CPlaqueBase::TraiterPoint (int x, int y)
- {
- unsigned char bCheck[9];
- int i, xx, yy, xMin, yMin, xMax, yMax;
- int retour;
- bool bool0;
- bool bool1;
- bool bc0;
- retour = 0;
- m_debug1++;
- // m_wimg.SaveImgAsRaw();
- // if (m_debug1 == 40700)
- if (((m_debug1 % 2500) == 0) && (m_debug1 != 0))
- {
- m_debug1 = m_debug1;
- }
- assert(PointInBufferResult(x, y) && (m_type != typeUndefined));
- SetPixelResult(x, y);
- xMin = max(0, x - 1);
- xMax = min(x + 1, GetWidth() - 1);
- yMin = max(0, y - 1);
- yMax = min(y + 1, GetHeight() - 1);
-
- i = 0;
- for (xx = xMin; xx <= xMax; xx++)
- {
- for (yy = yMin; yy <= yMax; yy++)
- {
- assert (PointInBufferResult(xx, yy));
- /* bCheck [i] = ((xx != x) || (yy != y))
- && ((m_type == typeRGB) ?
- IsColor (xx, yy) :
- (GetIntensityResult(xx, yy) <= m_iMax)
- )
- && (GetPixelResult(xx, yy) != m_clrVert) // [LAU - 13/1/2006]
- && m_rgnATraiter.PtInRegion0(xx, yy);
- */
- bool0 = ((xx != x) || (yy != y));
- if ((bool0) && (m_type == typeRGB))
- {
- bc0 = IsColor (xx, yy);
- }
- else
- {
- bc0 = (GetIntensityResult(xx, yy) <= m_iMax);
- }
-
- bool1 = (bool0) && (bc0) && (GetPixelResult(xx, yy) != m_clrVert) && m_rgnATraiter.PtInRegion0(xx, yy);
-
- bCheck [i] = bool1 ? 1:0;
- i++;
- }
- }
-
- i = 0;
- for (xx = xMin; xx <= xMax; xx++)
- {
- for (yy = yMin; yy <= yMax; yy++)
- {
- if ((int) bCheck [i++] > 0)
- {
- TraiterPoint(xx, yy);
- }
- }
- }
- return retour;
- }
- int CPlaqueBase::Threshold( int iMax )
- {
- int retour;
-
- // AffectLeadResult();
- // Décompte de la répartition des points
- m_iMax = iMax;
- if (!SuiviContour())
- {
- m_debug1 = 0;
- retour = TraiterPoint(m_ptInferieur.x, m_ptInferieur.y);
- }
- // Fermeture et effacement des petites régions.
- DoClosing();
- DoBlobColoring();
-
- return retour;
- } // fin de Threshold
- /*----------------------------------------------------------\
- | Surface de la plaque |
- |-----------------------------------------------------------|
- | DESCRIPTION : |
- | Crée une région polygonale, composée des segments |
- | indiqués par l'utilisateur, des extrémités trouvées. |
- |-----------------------------------------------------------|
- | PARAMETRES : |
- \----------------------------------------------------------*/
- int CPlaqueBase::CalculerSurfaceEtIntensitePlaque (bool bManuelle)
- {
- int nIntensite;
- Rect rectEnglobant;
- Point pt;
- int retour;
- retour = 0;
- if (bManuelle)
- {
- m_nSensTrigo = 0;
- assert (m_nVecteursTrouves == 0); // Pour être sûr
- }
- // Suppression de l'utilisation d'une region pour la mesure:
- // la figure est trop complexe et beaucoup de points sont oubliés
- // (il suffit de l'afficher dans OnDraw pour s'en rendre compte).
- // seule la région de traitement se monte fiable (peu de points, points éloignés)
- rectEnglobant = m_rgnATraiter.GetRgnBox();
- m_nPointsDansPlaque = 0;
- m_iSommeIntensitesPlaque = 0;
- memset (m_IntervallesIntensite, 0, sizeof (m_IntervallesIntensite));
-
- GraphMeanInit();
- // Calculer la surface & l'intensité & l'Histogramme.
- for (pt.y = rectEnglobant.top; pt.y < rectEnglobant.bottom; pt.y++)
- {
- for (pt.x = rectEnglobant.left; pt.x < rectEnglobant.right; pt.x++)
- {
- if ((GetPixelResult(pt.x, pt.y) != m_clrVert) && (m_rgnATraiter.PtInRegion(&pt)))
- {
- nIntensite = GetIntensityResult(pt); // - m_iTache;
- m_nPointsDansPlaque++;
- GraphMeanAddMeasure(true, nIntensite);
- m_iSommeIntensitesPlaque += nIntensite;
- if (nIntensite < 120)
- m_IntervallesIntensite [0]++;
- else if (nIntensite < 200)
- m_IntervallesIntensite [1]++;
- else
- m_IntervallesIntensite [2]++;
- }
- }
- }
- if (m_iSommeIntensitesPlaque < 0)
- {
- retour = 50;
- }
- if (bManuelle)
- {
- int i1, i2;
- int nPt1 = -1, nPt2 = -1;
- int nDistance = 0, nDistanceMax = 0;
- int iSegment, iOrtho1, iOrtho2;
- // Calculer la longueur de la plaque (les 2 pts les + éloignés)
- for (i1 = 0; i1 < m_nPtLongeantPlaque - 1; i1++)
- for (i2 = i1 + 1; i2 < m_nPtLongeantPlaque; i2++)
- if ((nDistance = Distance2D (m_tPtLongeantPlaque [i1], m_tPtLongeantPlaque [i2]))
- > nDistanceMax)
- {
- nDistanceMax = nDistance;
- nPt1 = i1;
- nPt2 = i2;
- }
- if (!bManuelle) GraphMeanInit();
- m_nLongueurMax = 0;
- m_nSommeLongueurs = 0;
- m_nMesures = 0;
- // Calculer la largeur
- if (nDistanceMax)
- {
- // Vecteur le long de la plaque
- CVector vectLong (m_tPtLongeantPlaque [nPt1].x,m_tPtLongeantPlaque [nPt1].y,
- m_tPtLongeantPlaque [nPt2].x, m_tPtLongeantPlaque [nPt2].y);
- CVector vectOrtho;
- // Pour essai
- if (m_rgnATraiter.PtInRegion0(vectLong [5].x, vectLong [5].y) )
- {
- retour = 52;
- }
- if (m_rgnATraiter.PtInRegion0(vectLong [0].x, vectLong [0].y))
- {
- retour = 52;
- }
- for (iSegment = 0; iSegment < vectLong.Norm () - 1; iSegment ++)
- {
- vectOrtho = vectLong.Orthogonal (vectLong [iSegment], 0);
- for ( iOrtho1 = 0;
- iOrtho1 < vectLong.Norm () && (m_rgnATraiter.PtInRegion0(vectOrtho [iOrtho1].x,vectOrtho [iOrtho1].y));
- iOrtho1 ++);
- for ( iOrtho2 = 0;
- iOrtho2 > -vectLong.Norm () && (m_rgnATraiter.PtInRegion0(vectOrtho [iOrtho2].x,vectOrtho [iOrtho2].y));
- iOrtho2 --);
- if (iOrtho1 - iOrtho2 > ((long) m_nLongueurMax))
- m_nLongueurMax = iOrtho1 - iOrtho2;
- m_nSommeLongueurs += iOrtho1 - iOrtho2;
- if (!bManuelle)
- {
- if (iOrtho1 - iOrtho2)
- GraphMeanAddMeasure(true, iOrtho1 - iOrtho2);
- }
- m_nMesures++;
- }
- }
- }
- return retour;
- }
- int CPlaqueBase::calculPlaque2(ExtendedImage *h_image, int nbPts, unsigned char *points)
- {
- unsigned char *dadd;
- unsigned char a, b, c, d;
- Point point;
- int npt;
- int retour;
- m_result = h_image;
- if ( !m_etudie )
- {
- m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
-
- }
- m_wimg.Del();
- m_wimg.Create(TYPE_UCHAR, GetWidth(), GetHeight());
- m_wimg.Fill(0);
- m_type = typeManual;
- retour = 0;
- npt = 0;
-
- dadd = points;
- do
- {
- a = *dadd;
- dadd++;
- b = *dadd;
- dadd++;
- c = *dadd;
- dadd++;
- d = *dadd;
- dadd++;
-
- point.x = d;
- point.x = point.x | (c << 8);
- point.x = point.x | (b << 16);
- point.x = point.x | (a << 24);
- a = *dadd;
- dadd++;
- b = *dadd;
- dadd++;
- c = *dadd;
- dadd++;
- d = *dadd;
- dadd++;
-
- point.y = d;
- point.y = point.y | (c << 8);
- point.y = point.y | (b << 16);
- point.y = point.y | (a << 24);
-
- // if (m_nPtLongeantPlaque < NBPTSLONGEANTMAX)
- {
- m_tPtLongeantPlaque [m_nPtLongeantPlaque] = point;
- m_nPtLongeantPlaque++;
- }
- npt++;
- } while (npt < nbPts);
- m_tPtLongeantPlaque [m_nPtLongeantPlaque] = m_tPtLongeantPlaque [0];
- m_nPtLongeantPlaque++;
- retour = CalculerPlaqueManuelle();
- return retour;
- }
- /*----------------------------------------------------------\
- | Surface de la plaque |
- |-----------------------------------------------------------|
- | DESCRIPTION : |
- | Crée une région polygonale, composée des segments |
- | indiqués par l'utilisateur, des extrémités trouvées. |
- |-----------------------------------------------------------|
- | PARAMETRES : |
- \----------------------------------------------------------*/
- int CPlaqueBase::CalculerPlaqueManuelle ()
- {
- int retour;
- // AffectLeadResult();
- // Créer le polygone
- m_rgnATraiter.DeleteObject();
-
- if (!m_rgnATraiter.CreatePolygonRgn(m_tPtLongeantPlaque, m_nPtLongeantPlaque))
- {
- retour = 31;
- return retour;
- }
-
- retour = CalculerSurfaceEtIntensitePlaque(true);
- return retour;
- }
- bool CPlaqueBase::IsBorder(int x, int y)
- {
- if (!((m_type == typeRGB) ? !IsColor(x, y) :
- (GetIntensityResult(x, y) > m_iMax)))
- { // On considère qu'il faut être dans la plaque!
- return false;
- }
- // L'aspect static de ces 7 variables est purement dans un but d'économie de mémoire...
- static int Xmin, Xmax, xx, Ymin, Ymax, yy, NbPoints;
- Xmin = max(0, x-1);
- Xmax = min(x+1, GetWidth() - 1);
- Ymin = max(0, y-1);
- Ymax = min(y+1, GetHeight() - 1);
- // On compte le nombre de points en-plaque autour du point étudié
- NbPoints = 0;
- for(xx = Xmin; xx <= Xmax; xx++)
- {
- for(yy = Ymin; yy <= Ymax; yy++)
- {
- if (((xx != x) || (yy != y)) &&
- ((m_type == typeRGB) ? !IsColor(xx, yy) :
- (GetIntensityResult(xx, yy) > m_iMax)))
- {
- NbPoints++;
- }
- }
- }
- // Ce point est considéré comme faisant partie de la frontière s'il possède
- // plus de 3 points en-plaque autour de lui, et s'il n'est pas au milieu de
- // la plaque (id est tout point autour de lui en-plaque!)
- if ((NbPoints < 3) || (NbPoints == (Xmax-Xmin+1)*(Ymax-Ymin+1)-1))
- {
- return false;
- }
- return true;
- }
- bool CPlaqueBase::SuiviContourLocal(int x, int y, double Xd, double Yd, bool Initialise)
- {
- static CVector VectBordFin;
- static int Width;
- static bool* TabPtParcourus = NULL;
- // (TabPtParcourus[x+Width*y] == true) s'il le point (x,y) à été parcourus
- if (Initialise)
- {
- Width = GetWidth();
- delete [] TabPtParcourus;
- TabPtParcourus = new bool[Width * GetHeight()];
- memset(TabPtParcourus, 0, Width * GetHeight());
- VectBordFin = CVector(m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].x,m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].y,
- m_pointLimite1.x,m_pointLimite1.y);
- return true;
- }
- static int xx, yy; // L'aspect static est purement dans un but d'économie de mémoire...
- // On marque ce point comme parcourus
- TabPtParcourus[x+y*Width] = true;
- // On conserve l'ancienne valeur de la couleur pour pouvoir la restaurer
- unsigned long OldPixelColor = GetPixelEtudie(x, y);
- // On dessine en bleu le point étudié (appartenant à priori au contour)
- SetPixelEtudie(x, y, m_clrBleue);
- // On a fini avec succes la mesure si le point étudié touche le 2nd bord jaune!
- Point pt = VectBordFin.Projected(Point(x,y));
- if (Distance2D(Point(pt.x,pt.y) , Point(x,y)) < 2) return true;
- int Xbest, Ybest;
- Xbest = 0;
- Ybest = 0;
-
- // L'aspect static de ces 6 variables est purement dans un but d'économie de mémoire...
- static double Vbest;
- static bool Valide;
- static int M;
- static double XdNew;
- static double YdNew;
- static double PScal;
- int dimension = 1;
- Valide = false; Vbest = 1;
- while (!Valide)
- {
- Vbest = 0.25 * (4 - dimension);
- // On cherche les coordonnées du point ou la "pertinence" est la plus elevé
- for(xx = -dimension; xx <= dimension; xx++)
- {
- for(yy = -dimension; yy <= dimension; yy++)
- {
- // On regarde la pertinence de ce point environnant...
- if ((xx) || (yy))
- {
- // PScal = (Xd *xx + Yd *yy)/sqrt(xx*xx+yy*yy);
- PScal = (Xd *xx + Yd *yy) / sqrt((double) xx * xx + (double) yy * yy); // MAJ2005
- if ((PScal > Vbest) &&
- (m_rgnATraiter.PtInRegion0(x+xx, y+yy)) &&
- (!TabPtParcourus[(x+xx)+(y+yy)*Width]) &&
- (IsBorder(x+xx, y+yy)))
- {
- Vbest = PScal;
- Xbest = xx;
- Ybest = yy;
- }
- }
- }
- }
- if (Vbest != 0.25*(4 - dimension))
- {
- M = max(abs(Xbest), abs(Ybest));
- XdNew = Xbest * M + Xd * 3 * dimension;
- YdNew = Ybest * M + Yd * 3 * dimension;
- PScal = sqrt(XdNew * XdNew + YdNew * YdNew);
- if (SuiviContourLocal(x + Xbest / M, y + Ybest / M, XdNew / PScal, YdNew / PScal))
- {
- Valide = true;
- break;
- }
- else
- {
- Valide = false; // On restaure cette variable static au cas où...
- TabPtParcourus[(x + Xbest) + (y + Ybest) * Width] = true;
- }
- }
- else
- {
- // On agrandi la fenetre de recherche...
- if (dimension < 4) dimension++;
- else break;
- }
- }
- if (!Valide)
- {
- // On remet la couleur initial du point
- SetPixelEtudie(x, y, OldPixelColor);
- return false;
- }
- return true;
- }
- bool CPlaqueBase::SuiviContour()
- {
- // On cherche le début de la plaque le long du 1er bord jaune
- CVector vectSegment(m_pointLimite2.x, m_pointLimite2.y, m_tPtLongeantPlaque[0].x, m_tPtLongeantPlaque[0].y);
- int i = 0;
- // On prend le premier point entrant dans la plaque!
- while(!((m_type == typeRGB) ?
- !IsColor(vectSegment[i].x, vectSegment[i].y) :
- (GetIntensityResult(vectSegment[i].x, vectSegment[i].y) > m_iMax)))
- {
- i++;
- if (!PointInBufferResult(vectSegment[i].x, vectSegment[i].y)) return false;
- }
- double Xd, Yd, d; // Direction initiale de recherche de contour...
- Xd = m_tPtLongeantPlaque[1].x - m_tPtLongeantPlaque[0].x;
- Yd = m_tPtLongeantPlaque[1].y - m_tPtLongeantPlaque[0].y;
- d = sqrt(Xd * Xd + Yd * Yd);
- Xd = Xd/d;
- Yd = Yd/d;
- int Compteur = 0;
- bool MesureValide = false;
- while ((!MesureValide) && (Compteur++ < 5)) // On fait 5 essais maximum...
- {
- CopyResultDansEtudie();
-
- // On espère avoir une frontière de la plaque valide en ce point...
- SuiviContourLocal(0, 0, 0, 0, true); // Initialisation de la fonction!
- MesureValide = SuiviContourLocal(vectSegment[i].x, vectSegment[i].y, Xd, Yd);
- if (!MesureValide)
- {
- // La première mesure n'est pas valide...
- // On cherche le premier point sortant de la plaque précedemment détectée!
- while ((m_type == typeRGB) ?
- !IsColor(vectSegment[i].x, vectSegment[i].y) :
- (GetIntensityResult(vectSegment[i].x, vectSegment[i].y) > m_iMax))
- {
- i++;
- if (!PointInBufferResult(vectSegment[i].x, vectSegment[i].y)) return false;
- }
- // On cherche le premier point entrant dans la plaque!
- while(!((m_type == typeRGB) ?
- !IsColor(vectSegment[i].x, vectSegment[i].y) :
- (GetIntensityResult(vectSegment[i].x, vectSegment[i].y) > m_iMax)))
- {
- i++;
- if (!PointInBufferResult(vectSegment[i].x, vectSegment[i].y)) return false;
- }
- }
- }
- if (!MesureValide) return false;
- #ifdef _DEBUG
- // On affiche le résultat de l'algo de repérage du contour plaque.
- // m_pLeadResult->Copy(m_LeadEtudie);
- #endif // _DEBUG
- // Remplissage de la partie hors-plaque en vert
- SuiviContourRemplis(m_ptInferieur.x, m_ptInferieur.y);
- return true;
- }
- void CPlaqueBase::SuiviContourRemplis(int x, int y)
- {
- assert(PointInBufferResult(x, y) && (m_type != typeUndefined));
- assert(GetPixelEtudie(x, y) != m_clrBleue);
- assert(GetPixelResult(x, y) != m_clrVert);
- int xx, Xmin, Xmax, yy, Ymin, Ymax;
- // On dessine en vert le point hors-plaque étudié
- SetPixelResult(x, y);
- Xmin = max(0, x-2);
- Xmax = min(x+2, GetWidth() - 1);
- Ymin = max(0, y-2);
- Ymax = min(y+2, GetHeight() - 1);
- // On compte le nombre de points frontière autour du point étudié
- double NbPoints = 0;
- for(xx = Xmin; xx <= Xmax; xx++)
- {
- for(yy = Ymin; yy <= Ymax; yy++)
- {
- if (((xx != x) || (yy != y)) &&
- (GetPixelEtudie(xx, yy) == m_clrBleue))
- {
- NbPoints++;
- }
- }
- }
- // Ce point est à la fin de l'arbre de parcours si il possède 2 points ou plus
- // appartenant à la frontières à coté de lui
- if (NbPoints > 0) return;
- Xmin = max(0, x-1);
- Xmax = min(x+1, GetWidth() - 1);
- Ymin = max(0, y-1);
- Ymax = min(y+1, GetHeight() - 1);
- for (xx = Xmin; xx <= Xmax; xx++)
- {
- for (yy = Ymin; yy <= Ymax; yy++)
- {
- if (((xx != x) || (yy != y)) &&
- (m_rgnATraiter.PtInRegion0(xx, yy)) &&
- (GetPixelEtudie(xx, yy) != m_clrBleue) &&
- (GetPixelResult(xx, yy) != m_clrVert))
- { // Le point (xx, yy) est donc hors-plaque et non traité
- SuiviContourRemplis(xx, yy);
- }
- }
- }
- }
- // [LAU - 2/5/2006] Calcule la somme des longeurs entre les points enregistrés longeant la plaque
- double CPlaqueBase::Get_SommeLongueurs()
- {
- double dist = 0;
- if (m_Etape == etapeRien)
- {
- return (int)dist;
- }
- for (int i = 0; i < m_nPtLongeantPlaque-1; i++)
- {
- dist += CVector (m_tPtLongeantPlaque[i].x, m_tPtLongeantPlaque[i].y, m_tPtLongeantPlaque[i+1].x, m_tPtLongeantPlaque[i+1].y).Norm (g_pCurrentScale);
- }
- return (int) dist;
- }
- // Algorithme de coloriage de blobs sur l'image d'entrée
- // Objectif : enlever les petites régions dans l'image seuillée
- bool CPlaqueBase::DoBlobColoring()
- {
- int x, y, i, indblob, nblob, realblob, ng;
- long taille;
- img lwimg, lwimg1;
- int wdimh, wdimv;
- blob m_tblob[MAXBLOB];
- Rect rectEnglobant;
- rectEnglobant = m_rgnATraiter.GetRgnBox();
- wdimh = GetWidth();
- wdimv = GetHeight();
- lwimg.Create(TYPE_UCHAR, wdimh, wdimv);
- lwimg1.Create(TYPE_INT, wdimh, wdimv); // On prend des ints
- lwimg.Fill(0);
- indblob = 0;
- nblob = 0;
- // Générer l'image binaire qui va aller à l'algo. du blob coloring
- // lwimg
- for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
- {
- for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
- {
- bool fGreen;
- fGreen = (GetPixelResult(x, y) == m_clrVert);
- if (!fGreen)
- {
- lwimg.SetValue(x, y, 1);
- }
- }
- }
- // Résultat : les blobs sont dans wimg1
- nblob = lwimg.BlobColoring(m_tblob, &lwimg1);
- // Elimination des petits blobs.
- realblob = nblob;
- for (i = 1; i <= nblob; i++)
- {
- taille = lwimg1.GetBlobSize(i);
- if ((taille < (wdimh * wdimv) - 1) && (taille <= 50))
- {
- lwimg1.RemplaceCouleur(i, MAXBLOB+1); // Sur int
- }
- }
- // Dans lwimg1, les pixels à la valeur MAXBLOB+1, sont ceux des régions à supprimer
- // Mise à jour de lwimg, puis transfert dans l'image d'origine
- for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
- {
- for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
- {
- ng = lwimg1.GetValue(x, y);
- if (ng == (MAXBLOB + 1))
- {
- SetPixelResult(x, y);
- }
- }
- }
- if (lwimg.init == 1) lwimg.Del();
- if (lwimg1.init == 1) lwimg1.Del();
- return true;
- }
- // Algorithme de fermeture
- bool CPlaqueBase::DoClosing()
- {
- int x, y, ng;
- img lwimg, lwimg1;
- int wdimh, wdimv;
- Rect rectEnglobant;
- rectEnglobant = m_rgnATraiter.GetRgnBox();
- wdimh = GetWidth();
- wdimv = GetHeight();
- lwimg.Create(TYPE_USHORT, wdimh, wdimv);
- lwimg1.Create(TYPE_USHORT, wdimh, wdimv); // On prend des ints
- lwimg.Fill(0);
- // Générer l'image binaire qui va aller à l'algo. du blob coloring
- // lwimg
- for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
- {
- for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
- {
- if (GetPixelResult(x, y) == m_clrVert)
- {
- lwimg.SetValue(x, y, 1);
- }
- }
- }
- lwimg.BinaryClosing(&lwimg1);
- // Dans lwimg1, les pixels à la valeur MAXBLOB+1, sont ceux des régions à supprimer
- // Mise à jour de lwimg, puis transfert dans l'image d'origine
- for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
- {
- for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
- {
- ng = lwimg1.GetValue(x, y);
- if (ng == 1)
- {
- SetPixelResult(x, y);
- }
- }
- }
- if (lwimg.init == 1) lwimg.Del();
- if (lwimg1.init == 1) lwimg1.Del();
-
- return true;
- }
- bool CPlaqueBase::PointInBufferResult(const int& x, const int& y)
- {
- Point pt(x, y);
- // pt.x = x;
- // pt.y = y;
- return PointInBufferResult(pt);
- }
- bool CPlaqueBase::PointInBufferResult(const Point& pt)
- {
- assert( m_result );
- int dx = GetWidth();
- int dy = GetHeight();
- return ( (pt.x >= 0) && (pt.y >= 0) && (pt.x < dx) && (pt.y < dy) );
- }
-
- bool CPlaqueBase::IsColor(int x, int y)
- {
- unsigned char bRed;
- unsigned char bGreen;
- unsigned char bBlue;
- int iRed;
- int iGreen;
- int iBlue;
- // AffectLeadResult();
- bRed = m_result->GetPixelRGB( x, y, 0);
- bGreen = m_result->GetPixelRGB( x, y, 1);
- bBlue = m_result->GetPixelRGB( x, y, 2);
- iRed = (int) bRed;
- iGreen = (int) bGreen;
- iBlue = (int) bBlue;
- // un niveau de gris implique bRed = bGreen = bBlue
- // étant donné que l'image a été numérisé on autorise un delta de 10 entre chaque couleur
- // ex : 190 197 185 est gris, 190 201 190 est en couleur
- return ( (abs (iRed - iGreen) > 30)
- || (abs (iRed - iBlue ) > 30)
- || (abs (iGreen - iBlue ) > 30)
- );
- }
- int CPlaqueBase::GetIntensityResult(const int& x, const int& y)
- {
- Point pt;
- pt.x = x;
- pt.y = y;
- return GetIntensityResult(pt);
- }
- int CPlaqueBase::GetIntensityResult(const Point& pt)
- {
- assert( m_result );
- return m_result->GetPixelGray( pt.x, pt.y );
- /*
- value = (char) m_result->GetPixel( pt.x, pt.y );
-
- col = (unsigned char)(value & 0xff);
-
- return col;
- */
- /*
- #if defined( WIN32 ) && !defined( IMT_DLL ) && !defined( PLAQUE_DLL )
- return GetRValue( m_result->GetPixel( pt.x, pt.y ) );
- #else
- return *m_result->GetPixel( pt.x, pt.y );
- #endif
- */
- }
- unsigned int CPlaqueBase::GetErrorID(void)
- {
- return m_uErrorID;
- }
- int CPlaqueBase::TestFantome(ExtendedImage *h_image, CPlaqueResult *)
- {
- int i, x, y, nbPts;
- unsigned char *points, *dadd;
- int *input;
- Point pts[12];
- int retour;
- m_result = h_image;
- // m_result.Create(768, 576, 24);
- // m_result.CopyFrom2(h_image);
- CopieResultSvg();
- nbPts = 6;
- retour = 0;
- points = (unsigned char *) malloc( nbPts * sizeof(unsigned char *) );
- input = (int *) malloc( 4 * sizeof(int) );
-
- x = 372;
- y = 177;
- pts[0].x = 267;
- pts[0].y = 218;
- pts[1].x = 300;
- pts[1].y = 227;
- pts[2].x = 364;
- pts[2].y = 232;
- pts[3].x = 446;
- pts[3].y = 238;
- pts[4].x = 509;
- pts[4].y = 238;
- pts[5].x = 561;
- pts[5].y = 234;
- /* double a, b;
- a = g_pCurrentScale->m_dblHor;
- b = g_pCurrentScale->m_dblVer;
- */
- dadd = points;
- for (i = 0; i < nbPts; i++)
- {
- input[0] = ((pts[i].x & 0xFF000000) >> 24);
- input[1] = ((pts[i].x & 0x00FF0000) >> 16);
- input[2] = ((pts[i].x & 0x0000FF00) >> 8);
- input[3] = ((pts[i].x & 0x000000FF));
- *dadd = input[0];
- dadd++;
- *dadd = input[1];
- dadd++;
- *dadd = input[2];
- dadd++;
- *dadd = input[3];
- dadd++;
- input[0] = ((pts[i].y & 0xFF000000) >> 24);
- input[1] = ((pts[i].y & 0x00FF0000) >> 16);
- input[2] = ((pts[i].y & 0x0000FF00) >> 8);
- input[3] = ((pts[i].y & 0x000000FF));
- *dadd = input[0];
- dadd++;
- *dadd = input[1];
- dadd++;
- *dadd = input[2];
- dadd++;
- *dadd = input[3];
- dadd++;
- }
-
- retour = calculPlaque(h_image, x, y, nbPts, points, 60, 120);
- // m_res->allocate_vectors(m_nPtLongeantPlaque);
- return retour;
- }
- int CPlaqueBase::calculPlaque(ExtendedImage *h_image, int x, int y, int nbPts, unsigned char *points, int seuil1, int seuil2)
- {
- Point point;
- int npt;
- int retour;
- unsigned char *dadd;
- retour = 0;
- unsigned char a, b, c, d;
-
- m_result = h_image;
- // m_result.Create(768, 576, 24 );
- // m_result.CopyFrom2(h_image);
- m_Etape = etapeRien;
-
- // C'est le premier octet qui est pris : le rouge.
- m_debug1 = (int) GetIntensityResult(100, 125);
- m_debug2 = (int) GetIntensityResult(200, 170);
- m_debug3 = (int) GetIntensityResult(300, 460);
- m_debug4 = (int) m_result->GetWidth();
- m_debug5 = (int) 1;
-
- //retour = 1999;
- // return retour;
-
- // Création de m_etudie
- if ( m_Etape == etapeRien )
- {
- if ( !m_etudie )
- {
- m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
-
- }
- /* if ( m_etudie )
- {
- m_etudie->Create( GetWidth(), GetHeight(), 24 );
- }
- */
- // 1er Point
- m_Etape = etapeSegments;
- m_wimg.Del();
- m_wimg.Create(TYPE_UCHAR, GetWidth(), GetHeight());
- m_wimg.Fill(0);
- }
-
- retour = 0;
- dadd = points;
-
- if (m_Etape == etapeSegments)
- {
- npt = 0;
- do
- {
-
- a = *dadd;
- dadd++;
- b = *dadd;
- dadd++;
- c = *dadd;
- dadd++;
- d = *dadd;
- dadd++;
-
- point.x = d;
- point.x = point.x | (c << 8);
- point.x = point.x | (b << 16);
- point.x = point.x | (a << 24);
- a = *dadd;
- dadd++;
- b = *dadd;
- dadd++;
- c = *dadd;
- dadd++;
- d = *dadd;
- dadd++;
-
- point.y = d;
- point.y = point.y | (c << 8);
- point.y = point.y | (b << 16);
- point.y = point.y | (a << 24);
-
- if (m_nPtLongeantPlaque < NBPTSLONGEANTMAX)
- {
- if ( m_nPtLongeantPlaque
- && ( (CVector (point.x, point.y, m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x,m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y).Norm () <= 5)
- || ((m_type == typeManual) && (CVector (point.x, point.y, m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y).Norm () <= 5))
- )
- )
- {
- // si la distance entre deux points est inférieure à 5 pixels, on considère que
- // c'est la fin de la paroi
- if (m_type == typeManual)
- {
- m_tPtLongeantPlaque [m_nPtLongeantPlaque] = m_tPtLongeantPlaque [0];
- m_nPtLongeantPlaque++;
- retour = CalculerPlaqueManuelle();
- break;
- }
- m_Etape = etapeTacheSeuil;
- }
- else
- {
- m_tPtLongeantPlaque [m_nPtLongeantPlaque] = point;
- m_nPtLongeantPlaque++;
- }
- }
- npt++;
-
- } while (npt < nbPts);
- m_Etape = etapeTacheSeuil; // Ajouter voir interface
- }
-
- if (m_Etape == etapeTacheSeuil)
- {
- // Pt indiquant la limite inférieure
- m_ptInferieur.x = x;
- m_ptInferieur.y = y;
- // Calculer la région dans laquelle on coloriera
- retour = ParametrerRegionATraiter ();
-
- if (retour == 40)
- {
- retour = 20;
- if ( TestCouleur() )
- {
- m_type = typeRGB;
- }
- else
- {
- m_type = typeBW;
- retour = 23;
- }
- // Afficher le bitmap LeadResult seulement si la région est OK
- // est PAS en Release, afin de dissimuler, un peu, la méthode de détection
- m_Etape = etapeReglage;
- // s'il y a une phase de réglage (il n'y en a pas pour la plaque couleur)
- if (m_type == typeRGB)
- {
- m_debug1 = 100;
- retour = Mesurer_3(0); // mesure immédiate
- // retour = m_nVecteursTrouves;
- }
- else
- {
- m_debug1 = 200;
- m_iTache = GetIntensityTache (m_ptInferieur, 7);
- // Calculer le seuil inferieur
- Mesurer_3(m_iTache + 10);
- }
- // AnalysePlaque(seuil1, seuil2);
- }
- }
-
- return retour;
- }
- int CPlaqueBase::OnLButtonUp(ExtendedImage *h_image, int x, int y)
- {
- m_result = h_image;
- // m_result.Create(768, 576, 24 );
- // m_result.CopyFrom2(h_image);
- // Création de m_etudie
- if (m_Etape == etapeRien)
- {
- if ( !m_etudie )
- {
- m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
- }
- /* m_etudie = new ExtendedImage;
- if ( m_etudie )
- {
- m_etudie->Create( GetWidth(), GetHeight(), 24 );
- }
- */
- }
-
- return OnLButtonUp(x, y);
- }
-
- int CPlaqueBase::OnLButtonUp(int x, int y)
- {
- Point point;
- point.x = x;
- point.y = y;
- return OnLButtonUp(point);
- }
- int CPlaqueBase::OnLButtonUp(Point& point)
- {
- int retour;
- int x, y;
- x = point.x;
- y = point.y;
- retour = 0;
- if (m_Etape == etapeRien)
- {
- // 1er Point
- m_Etape = etapeSegments;
- m_wimg.Del();
- m_wimg.Create(TYPE_UCHAR, GetWidth(), GetHeight());
- m_wimg.Fill(0);
- }
-
- if (m_Etape == etapeSegments)
- {
- retour = 9;
- if (m_nPtLongeantPlaque < NBPTSLONGEANTMAX)
- {
- if ( m_nPtLongeantPlaque
- && ( (CVector (point.x, point.y, m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x,m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y).Norm () <= 5)
- || ((m_type == typeManual) && (CVector (point.x, point.y, m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y).Norm () <= 5))
- )
- )
- {
- // si la distance entre deux points est inférieure à 5 pixels, on considère que
- // c'est la fin de la paroi
- if (m_type == typeManual)
- {
- m_tPtLongeantPlaque [m_nPtLongeantPlaque] = m_tPtLongeantPlaque [0];
- m_nPtLongeantPlaque++;
- retour = CalculerPlaqueManuelle();
- // return (retour);
- }
- m_Etape = etapeTacheSeuil;
- // retour = 10;
- // return (retour);
- }
- retour = 11;
- m_tPtLongeantPlaque [m_nPtLongeantPlaque] = point;
- m_nPtLongeantPlaque++;
- }
- }
- else if (m_Etape == etapeTacheSeuil)
- {
- // Pt indiquant la limite inférieure
- m_ptInferieur = point;
- // Calculer la région dans laquelle on coloriera
- retour = ParametrerRegionATraiter ();
- if (retour == 40)
- {
- retour = 20;
- if ( TestCouleur() )
- {
- m_type = typeRGB;
- }
- else
- {
- m_type = typeBW;
- retour = 23;
- }
- //? cursor.Clip (m_pView, NULL); // Cesser le clipping
- // Afficher le bitmap LeadResult seulement si la région est OK
- // est PAS en Release, afin de dissimuler, un peu, la méthode de détection
- m_Etape = etapeReglage;
- // s'il y a une phase de réglage (il n'y en a pas pour la plaque couleur)
- if (m_type == typeRGB)
- {
- Mesurer_3(0); // mesure immédiate
- retour = 22;
- }
- else
- {
- m_iTache = GetIntensityTache (m_ptInferieur, 7);
- // Calculer le seuil inferieur
- Mesurer_3(m_iTache + 10);
- retour = 21;
- }
- }
- }
- else if (m_Etape == etapeReglage)
- {
- retour = 30;
- }
-
- return retour; // Tous les clics ne sont pas faits
- }
- unsigned char CPlaqueBase::GetIntensityTache(Point& ptCentre, int nRayonTache)
- {
- int nIntensiteTache = 0;
- // Quelle est l'intensité monochrome de la tache autour de ce pt ?
- for (int iX = min (GetWidth()-1, max (0, ptCentre.x - nRayonTache));
- iX <= min (GetWidth()-1, ptCentre.x + nRayonTache); iX++)
- {
- for (int iY = min (GetHeight()-1, max (0, ptCentre.y - nRayonTache));
- iY <= min (GetHeight()-1, ptCentre.y + nRayonTache); iY++)
- {
- nIntensiteTache += GetIntensityResult(iX, iY);
- }
- }
- return (nIntensiteTache / ((nRayonTache * 2 + 1) * (nRayonTache * 2 + 1)));
- }
- double CPlaqueBase::Mean()
- {
- return (m_nMesures ? g_pCurrentScale->DistanceX (double (m_nSommeLongueurs) / m_nMesures) : 0.);
- }
- double CPlaqueBase::Max()
- {
- return (g_pCurrentScale->DistanceX ((long)m_nLongueurMax));
- }
- unsigned char CPlaqueBase::Density()
- {
- int res;
- if (m_nPointsDansPlaque != 0)
- {
- res = max(m_iSommeIntensitesPlaque, 0) / m_nPointsDansPlaque;
- }
- else
- {
- res = 0;
- }
- return ((unsigned char) res);
- }
- // Surface != DistanceX (m_nPointsDansPlaque) !!
- double CPlaqueBase::Surface()
- {
- double dblSide = sqrt ((double) m_nPointsDansPlaque);
- return (g_pCurrentScale->Surface (dblSide, dblSide));
- }
- bool CPlaqueBase::TestCouleur()
- {
- bool isCouleur = false;
- Rect rc;
- int x, y;
- rc = m_rgnATraiter.GetRgnBox();
- m_debug2 = rc.left;
- m_debug3 = rc.left;
- m_debug4 = rc.top;
- m_debug5 = rc.bottom;
- for (x = rc.left; ((x < rc.right) && (isCouleur == false)); x++)
- {
- for (y = rc.top; ((y < rc.bottom) && (isCouleur == false)); y++)
- {
- if ( m_rgnATraiter.PtInRegion0( x, y ) )
- {
- isCouleur = IsColor(x, y);
- if (isCouleur == true)
- {
- x = x;
- y = y;
- isCouleur = IsColor(x, y);
- }
- }
- }
- }
- return isCouleur;
- }
- unsigned long CPlaqueBase::GetPixelResult(const int& x, const int& y)
- {
- Point pt;
- pt.x = x;
- pt.y = y;
- return GetPixelResult(pt);
- }
- unsigned long CPlaqueBase::GetPixelResult(const Point& pt)
- {
- unsigned long color;
- color = 0;
- if (m_wimg.GetValue(pt.x, pt.y) == 1)
- {
- color = m_clrVert;
- }
-
- // m_wimg.SaveImgAsRaw();
- return color;
- /*
- assert( m_result );
- #if defined( WIN32 ) && !defined( PLAQUE_DLL )
- return m_result->GetPixel( pt.x, pt.y );
- #else
- return *m_result->GetPixel( pt.x, pt.y );
- #endif
- */
- }
- unsigned long CPlaqueBase::GetPixelEtudie(const int& x, const int& y)
- {
- Point pt;
- pt.x = x;
- pt.y = y;
- return GetPixelEtudie(pt);
- }
- unsigned long CPlaqueBase::GetPixelEtudie(const Point& pt)
- {
- assert( m_etudie );
- //#if defined( WIN32 ) && !defined( IMT_DLL ) && !defined( PLAQUE_DLL )
- // return m_etudie->GetPixel( pt.x, pt.y );
- //#else
- //return *m_etudie->GetPixel( pt.x, pt.y );
- return m_etudie[ pt.x + GetWidth() * pt.y ];
- //#endif
- }
-
- void CPlaqueBase::SetPixelResult(int x, int y)
- {
- m_wimg.SetValue(x, y, 1);
- // m_wimg.SaveImgAsRaw();
- }
- void CPlaqueBase::SetPixelEtudie(Point& pt, unsigned long vColor)
- {
- int x, y;
- x = pt.x;
- y = pt.y;
-
- // m_etudie->SetPixel(vColor, x, y);
- m_etudie[ x + GetWidth() * y ] = vColor;
- }
- void CPlaqueBase::SetPixelEtudie(int x, int y, unsigned long vColor)
- {
- // m_etudie->SetPixel(vColor, x, y);
- m_etudie[ x + GetWidth() * y ] = vColor;
- }
- int CPlaqueBase::GetWidth()
- {
- return m_result->GetWidth();
- }
- int CPlaqueBase::GetHeight()
- {
- return m_result->GetHeight();
- }
- // Copie de m_result dans m_etudie
- void CPlaqueBase::CopyResultDansEtudie()
- {
- // m_etudie->Copy2(GetWidth(), GetHeight(), m_result);
- if ( !m_etudie )
- {
- m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
- }
- int w, h;
- int width = GetWidth();
- int height = GetHeight();
- unsigned long* ptr = m_etudie;
- for ( h = 0; h < height; h++ )
- {
- for ( w = 0; w < width; w++ )
- {
- *ptr++ = GetPixelResult( w, h );
- }
- }
- }
- void CPlaqueBase::CopieResultSvg()
- {
- int width = m_result->GetWidth();
- int height = m_result->GetHeight();
- m_result2.Create(width, height, 24 );
- m_result2.CopyFrom2(m_result);
- // m_result.SaveImgAsRaw();
- }
- void CPlaqueBase::AffectLeadResult()
- {
- m_result->CopyFrom2(&m_result2);
- }
- void CPlaqueBase::AnalysePlaque(int seuil1, int seuil2)
- {
- int i, x, y;
- // double dng;
- // int gray;
- int ngLumiere, ngAdventitia;
- // Si la lumière est en Doppler couleur
- if (IsColor(m_ptInferieur.x, m_ptInferieur.y))
- {
- ngLumiere = 0;
- }
- else
- {
- ngLumiere = GetIntensityResult(m_ptInferieur.x, m_ptInferieur.y);
- }
- ngAdventitia = 0;
- for (i = 0; i < m_nPtLongeantPlaque; i++)
- {
- ngAdventitia += GetIntensityResult(m_tPtLongeantPlaque[i].x, m_tPtLongeantPlaque[i].y);
- }
- ngAdventitia = 255;
- Rect rectEnglobant;
- rectEnglobant = m_rgnATraiter.GetRgnBox();
- for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
- {
- for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
- {
- bool fGreen;
-
- fGreen = (GetPixelResult(x, y) == m_clrVert);
-
- if ( m_rgnATraiter.PtInRegion0( x, y ) && (!fGreen))
- {
- m_wimg.SetValue(x, y, 2);
-
- // On récupére le niveau de gris de l'image originale
- /* gray = GetIntensityResult(x, y);
- dng = ((double) (gray - ngLumiere) * 195.0 ) / (double) ngAdventitia;
- if (dng < 0) dng = 0;
- if (dng > 195.0) dng = 195.0;
-
- if (dng <= seuil1)
- {
- m_wimg.SetValue(x, y, 2);
- }
- else if ((dng > seuil1) && (dng <= seuil2))
- {
- m_wimg.SetValue(x, y, 3);
- m_nbPixelsB++;
- }
- else if (dng > seuil2)
- {
- m_wimg.SetValue(x, y, 4);
- m_nbPixelsV++;
- }
- */ }
- }
- }
- // CalculScoreRepartition();
- }
- /*
- void CPlaqueBase::CalculScoreRepartition()
- {
- int nbConnexesR, nbConnexesB, nbConnexesV;
- int nbConnections, x, y, i, offset[8];
- // Tableau des Offsets
- // 4 0 5
- // 3 1
- // 7 2 6
- offset[0] = - m_imgPlaque.dimh;
- offset[1] = 1;
- offset[2] = m_imgPlaque.dimh;
- offset[3] = - 1;
- offset[4] = - 1 - m_imgPlaque.dimh;
- offset[5] = 1 - m_imgPlaque.dimh;
- offset[6] = 1 + m_imgPlaque.dimh;
- offset[7] = - 1 + m_imgPlaque.dimh;
- m_scoreRepartitionR = 0;
- m_scoreRepartitionB = 0;
- m_scoreRepartitionV = 0;
- m_scoreRepartition = 0;
- // Scrutation du rectangle englobant de la plaque
- nbConnexesR = 0;
- nbConnexesB = 0;
- nbConnexesV = 0;
- nbConnections = 0;
- for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
- {
- for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
- {
- bool fGreen;
-
- fGreen = (GetPixelResult(x, y) == m_clrVert);
-
- if ( m_rgnATraiter.PtInRegion0( x, y ) && (!fGreen))
- {
- for (i = 0; i < m_connexite; i++)
- {
- dadd3 = dadd1 + offset[i];
- if (*dadd3 == 1) // L'autre pixel appartient également à la plaque
- {
- dadd4 = dadd2 + offset[i];
-
- nbConnections++;
- // Si les 2 couleurs des pixels sont dans la même zone
- if ((*dadd2 <= m_SeuilCouleur1) && (*dadd4 <= m_SeuilCouleur1))
- {
- // Les 2 sont dans le seuil du bas
- nbConnexesR++;
- }
- else if ((*dadd2 > m_SeuilCouleur1) && (*dadd4 > m_SeuilCouleur1) && (*dadd2 <= m_SeuilCouleur2) && (*dadd4 <= m_SeuilCouleur2))
- {
- // Les 2 sont dans le seuil du milieu
- nbConnexesB++;
- }
- else if ((*dadd2 > m_SeuilCouleur2) && (*dadd4 > m_SeuilCouleur2))
- {
- // Les 2 sont dans le seuil du haut
- nbConnexesV++;
- }
- }
- }
- }
- }
- }
- // Score = 0 : tous les pixels sont de la même couleur
- // Score = 100% : Aucun pixel connexe
- if (nbConnections != 0)
- {
- m_scoreRepartitionR = 100.0 - (((double) nbConnexesR / (double) nbConnections) * 100.0);
- m_scoreRepartitionB = 100.0 - (((double) nbConnexesB / (double) nbConnections) * 100.0);
- m_scoreRepartitionV = 100.0 - (((double) nbConnexesV / (double) nbConnections) * 100.0);
- }
- // Score répartition globale
- m_scoreRepartition = ((m_scoreRepartitionR + m_scoreRepartitionB + m_scoreRepartitionV) / 3.0);
- }
- */
-
|