| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614 |
- /*******************************************************************\
- Fichier : StenoseNBBase.cpp
- Date : 4/01/10
- Version : 1.000
- Description : classe de calcul d'une sténose N&B
- |*******************************************************************|
- Bugs:
- Notes:
- |*******************************************************************|
- Historique :
- 10/02/98 1.000 : Première version
- \*******************************************************************/
- /*----------------------------------------------------------\
- Includes
- \----------------------------------------------------------*/
- #include <limits>
- #include "StenoseNBBase.h"
- #include "Ressource.h"
- //#include "../IMT/MeanEstimate.h"
- #include "../Object/regionEllipse.h"
- #include "../Object/point.h"
- #include "../NR/ToolsMath.h"
- #include "../Container/extendedimage.h"
- #include "../TRIM/img.h"
- #ifndef max
- #define max(a,b) (((a) > (b)) ? (a) : (b))
- #endif
- #ifndef min
- #define min(a,b) (((a) < (b)) ? (a) : (b))
- #endif
- CStenoseNBBase::CStenoseNBBase (void)
- {
- // Couleur des points à afficher pour le degré de sténose
- m_rcStenose.SetRectEmpty();
- m_step = stepNone;
- m_clrVert = 0 | (255 << 16) | (0 << 8);
- m_clrOrange = 216 | (216 << 16) | (28 << 8);
- m_pPoints = NULL;
- m_SeuilBlobColoring = 40;
- }
- CStenoseNBBase::~CStenoseNBBase()
- {
- Release ();
- }
- void CStenoseNBBase::Release()
- {
- if (m_pPoints)
- {
- delete [] m_pPoints;
- m_pPoints = NULL;
- }
- m_dwPoints = 0; // requis par la routine de mesure
- }
- double CStenoseNBBase::Ratio()
- {
- return (100.0 * m_dwOther / (m_dwGreen + m_dwOther));
- }
- double CStenoseNBBase::Surface()
- {
- return m_dblSurface;
- }
- int CStenoseNBBase::Density()
- {
- return m_dwMean;
- }
- bool CStenoseNBBase::ParametrerRegionATraiter (Rect &rcStenose, Point ptStenose)
- {
- // Région à traiter
- m_ptStenose = ptStenose;
- m_rcStenose = rcStenose;
- m_rgnATraiter.DeleteObject();
- m_rgnATraiter.CreateEllipticRgn(rcStenose);
- return true;
- }
- /*----------------------------------------------------------\
- | Mesurer |
- |-----------------------------------------------------------|
- | DESCRIPTION : |
- | On a saisi un segment. Mesurer l'épaisseur de droites |
- | perpendiculaires. |
- |-----------------------------------------------------------|
- | PARAMETRES : |
- | ... |
- \----------------------------------------------------------*/
- void CStenoseNBBase::TraiterPoint (int x, int y)
- {
- assert(PointInBufferResult(x, y));
- if (PointInBufferResult(x, y))
- {
- int xx, yy, xMax, yMax;
- // Colorer ce point en vert
- // SetPixelResult(y, x, m_clrVert);
- SetPixelResult(x, y, m_clrOrange);
- // Pour optimiser le temps de calcul, on effectue les tests les plus rapides en premier
- xMax = min (x + 1, GetWidth() - 1);
- yMax = min (y + 1, GetHeight() - 1);
- for (xx = max (0, x - 1); xx <= xMax; xx++)
- {
- for (yy = max (0, y - 1); yy <= yMax; yy++)
- {
- if ((xx != x) || (yy != y))
- {
- assert(PointInBufferResult(xx, yy));
- // <= sur les intensités sinon à 255 tout n'est pas rempli
- if ( (GetIntensityResult(xx, yy) <= m_iMax)
- // && (GetPixelResult(xx, yy) != m_clrVert)
- && (GetPixelResult(xx, yy) != m_clrOrange)
- && m_rgnATraiter.PtInRegion0(xx, yy)
- )
- {
- TraiterPoint (xx, yy); // Pas de max
- }
- }
- }
- }
- }
- }
- int CStenoseNBBase::GetIntensityTache(int ptCentrex, int ptCentrey, int nRayonTache)
- {
- int nIntensiteTache = 0;
- // Quelle est l'intensité monochrome de la tache autour de ce pt ?
- for (int iX = min (m_result->GetWidth()-1, max (0, ptCentrex - nRayonTache));
- iX <= min (m_result->GetWidth()-1, ptCentrex + nRayonTache); iX++)
- {
- for (int iY = min (m_result->GetHeight()-1, max (0, ptCentrey - nRayonTache));
- iY <= min (m_result->GetHeight()-1, ptCentrey + nRayonTache); iY++)
- {
- nIntensiteTache += m_result->GetPixelRGB( iX, iY, 0);
- }
- }
- return (nIntensiteTache / ((nRayonTache * 2 + 1) * (nRayonTache * 2 + 1)));
- }
- int CStenoseNBBase::Threshold_2(ExtendedImage *h_image, int iMax, Rect &rcEllipse, int ptx, int pty)
- {
- int dwColor;
- int retour;
- iMax = 0; // Unused
- m_result = h_image;
- m_wimg.Del();
- m_wimg.Create(TYPE_UCHAR, GetWidth(), GetHeight());
- m_wimg.Fill(0);
- Release();
- m_ptStenose.x = ptx;
- m_ptStenose.y = pty;
- m_step = stepSettings;
- m_rcStenose = rcEllipse;
- m_rcStenose.right++;
- m_rcStenose.bottom++;
- // nombre maximal de points qui pourraient être affichés
- m_pPoints = new Point [m_rcStenose.Width() * m_rcStenose.Height()];
- m_rgnATraiter.DeleteObject ();
- m_rgnATraiter.CreateEllipticRgn(m_rcStenose);
-
- // GetIntensityTache inclus dans la librairie
- m_iMax = GetIntensityTache(ptx, pty, 7) + 10;
-
- TraiterPoint(m_ptStenose.x, m_ptStenose.y);
- // Fermeture et Effacement des petites régions
- DoClosing();
- DoBlobColoring();
- //***** Afficher les résultats
- GraphMeanInit();
-
- dwColor = 0;
- m_dwGreen = 0;
- m_dwOther = 0;
- m_dwMean = 0;
-
- m_dblVesselArea = g_pCurrentScale->Surface (m_rcStenose.Width(), m_rcStenose.Height()) * M_PI / 4;
- for (int x = m_rcStenose.left; x < m_rcStenose.right; x++)
- {
- for (int y = m_rcStenose.top; y < m_rcStenose.bottom; y++)
- {
- bool fGreen;
- // Même en dehors de la région sinon le bord inférieur droit est exclu
- // fGreen = (GetPixelResult(x, y) == m_clrVert);
- fGreen = (GetPixelResult(x, y) == m_clrOrange);
- if (fGreen)
- {
- m_dwGreen++;
- m_pPoints[m_dwPoints].x = x;
- m_pPoints[m_dwPoints].y = y;
- m_dwPoints++;
- }
-
- if (m_rgnATraiter.PtInRegion0(x, y))
- {
- if (!fGreen)
- {
- dwColor += IsColor (x, y) ? 1 : 0;
- m_dwOther++;
- m_dwMean += GetIntensityResult(x, y);
- GraphMeanAddMeasure(true, GetIntensityResult(x, y));
- }
- }
- }
- }
- if (m_dwOther)
- {
- m_dwMean /= m_dwOther;
- }
- assert(m_dwMean <= 255);
- m_dblSurface = m_dblVesselArea * Ratio () / 100.0;
-
- if (dwColor > 50)
- {
- retour = 10;
- }
- else
- {
- retour = 11;
- }
- return retour;
- } // fin de Threshold_2
- // Algorithme de coloriage de blobs sur l'image d'entrée
- // Objectif : enlever les petites régions dans l'image seuillée
- bool CStenoseNBBase::DoBlobColoring()
- {
- int x, y, i, indblob, nblob, realblob, ng;
- long taille;
- img lwimg, lwimg1;
- int wdimh, wdimv;
- blob m_tblob[MAXBLOB];
- 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 = m_rcStenose.left; x < m_rcStenose.right; x++)
- {
- for (y = m_rcStenose.top; y < m_rcStenose.bottom; y++)
- {
- if (m_rgnATraiter.PtInRegion0(x, y))
- {
- bool fGreen;
-
- fGreen = (GetPixelResult(x, y) == m_clrOrange);
-
- 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 <= m_SeuilBlobColoring))
- {
- 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 = m_rcStenose.left; x < m_rcStenose.right; x++)
- {
- for (y = m_rcStenose.top; y < m_rcStenose.bottom; y++)
- {
- if (m_rgnATraiter.PtInRegion0(x, y))
- {
- ng = lwimg1.GetValue(x, y);
- if (ng == (MAXBLOB+1))
- {
- SetPixelResult(x, y, m_clrOrange);
- }
- }
- }
- }
- if (lwimg.init == 1) lwimg.Del();
- if (lwimg1.init == 1) lwimg1.Del();
- return true;
- }
- // Algorithme de fermeture
- bool CStenoseNBBase::DoClosing()
- {
- int x, y, ng;
- img lwimg, lwimg1;
- int wdimh, wdimv;
- 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 = m_rcStenose.left; x < m_rcStenose.right; x++)
- {
- for (y = m_rcStenose.top; y < m_rcStenose.bottom; y++)
- {
- if (m_rgnATraiter.PtInRegion0(x, y))
- {
- bool fGreen;
-
- fGreen = (GetPixelResult(x, y) == m_clrOrange);
-
- if (fGreen)
- {
- 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 = m_rcStenose.left; x < m_rcStenose.right; x++)
- {
- for (y = m_rcStenose.top; y < m_rcStenose.bottom; y++)
- {
- if (m_rgnATraiter.PtInRegion0(x, y))
- {
- ng = lwimg1.GetValue(x, y);
- if (ng == 1)
- {
- SetPixelResult(x, y, m_clrOrange);
- }
- }
- }
- }
- if (lwimg.init == 1) lwimg.Del();
- if (lwimg1.init == 1) lwimg1.Del();
- return true;
- }
- int CStenoseNBBase::GetWidth()
- {
- return m_result->GetWidth();
- }
- int CStenoseNBBase::GetHeight()
- {
- return m_result->GetHeight();
- }
- unsigned long CStenoseNBBase::GetPixelResult(const int& x, const int& y)
- {
- Point pt;
- pt.x = x;
- pt.y = y;
- return GetPixelResult(pt);
- }
- unsigned long CStenoseNBBase::GetPixelResult(const Point& pt)
- {
- unsigned long color;
- color = 0;
- if (m_wimg.GetValue(pt.x, pt.y) == 1)
- {
- color = m_clrOrange;
- }
-
- // 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
- */
- }
- void CStenoseNBBase::SetPixelResult(Point& pt, unsigned long vColor)
- {
- int x, y;
- x = pt.x;
- y = pt.y;
- SetPixelResult(x, y, vColor);
- }
- void CStenoseNBBase::SetPixelResult(int x, int y, unsigned long vColor)
- {
- m_wimg.SetValue(x, y, 1);
- // m_wimg.SaveImgAsRaw();
- }
- bool CStenoseNBBase::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)
- );
- }
- unsigned char CStenoseNBBase::GetIntensityResult(const int& x, const int& y)
- {
- Point pt;
- pt.x = x;
- pt.y = y;
- return GetIntensityResult(pt);
- }
- unsigned char CStenoseNBBase::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
- */
- }
- bool CStenoseNBBase::PointInBufferResult(const int& x, const int& y)
- {
- Point pt;
- pt.x = x;
- pt.y = y;
- return PointInBufferResult(pt);
- }
- bool CStenoseNBBase::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 );
- }
- void CStenoseNBBase::PutPixEllipse(float xc,float yc,float x,float y)
- {
- WritePixel( (int) (xc + x), (int) (yc + y));
- WritePixel( (int) (xc - x), (int) (yc - y));
- WritePixel( (int) (xc + x), (int) (yc - y));
- WritePixel( (int) (xc - x), (int) (yc + y));
- }
- void CStenoseNBBase::WritePixel(int x, int y)
- {
- }
- // Algorithme MidPoint de dessin d'une Ellipse
- void CStenoseNBBase::myDrawEllipse()
- {
- float x = 0, y = 0;
- double p1, p2, t1, t2;
- int k;
- float rx, ry, xc, yc;
- rx = (float) (m_rcStenose.right - m_rcStenose.left) / 2;
- ry = (float) (m_rcStenose.bottom - m_rcStenose.top) / 2;
- xc = m_rcStenose.left + rx;
- yc = m_rcStenose.top + ry;
- y = ry;
- p1 = ry * ry - rx * rx * ry + 0.25 * rx * rx;
-
- PutPixEllipse(xc, yc, x, y);
- for (k = 0; (2 * ry * ry * x) <= (2 * rx * rx * y); k++)
- {
- t1 = 2 * ry * ry * x + 2 * ry * ry;
- t2 = 2 * rx * rx * y - 2 * rx * rx;
-
- if (p1 < 0)
- {
- p1 = p1 + t1 + ry * ry;
- }
- else
- {
- p1 = p1 + t1 - t2 + ry * ry;
- y--;
- }
- x++;
- PutPixEllipse(xc, yc, x, y);
- }
- p2 = ry * ry * ( x + 0.5 ) * ( x + 0.5 ) + rx * rx * (y - 1) * (y - 1) - rx * rx * ry * ry;
-
- PutPixEllipse(xc, yc, x, y);
- for (k = 0 ; y >= 0 ; k++)
- {
- t1 = 2 * ry * ry * x + 2 * ry * ry;
- t2 = 2 * rx * rx * y - 2 * rx * rx;
-
- if (p2 > 0)
- {
- p2 = p2 - t2 + rx * rx;
- }
- else
- {
- p2 = p2 + t1 - t2 + rx * rx;
- x++;
- }
- y--;
- PutPixEllipse(xc, yc, x, y);
- }
- }
|