Détéction des blobs(contours) et filtre median-traitement d'image-

Signaler
Messages postés
4
Date d'inscription
lundi 22 février 2010
Statut
Membre
Dernière intervention
24 mars 2011
-
Messages postés
1
Date d'inscription
lundi 20 février 2006
Statut
Membre
Dernière intervention
1 juillet 2010
-
bonjour
comme le titre l'indique, je cherche de l'aide pour la creation d'un filtre median en C d'une part, et d'une autre part , une idée pour la détection des blobs (contours)
si qqu'un a un exemple surtout pour la détection des blobs ca sera sympa, je travaille sur un projet de détection de panneaux routiers a l'aide d'une camera installé sur une vehicule. mais je me suis bloqué surtout sur la detection des blobs( detection des formes dans une images)

merci

1 réponse

Messages postés
1
Date d'inscription
lundi 20 février 2006
Statut
Membre
Dernière intervention
1 juillet 2010

// récupération des infos des blobs
if (m_NbBlobs>0)
{
// ajout des blobs dans la liste
// pour tous les blobs supérieurs au seuil des gros défauts
for(int ii=0; ii<m_NbBlobs; ii++)
{
if(m_pBlobArea[ii] > m_pParams->m_SurfSeuilGrosDefautsPix)
{
// parmis tous les blobs trouvés, certains blobs peuvent
// être des blobs "coupés en morceaux" qui vont être reconstitués par le
// traitement d'"extension", donc pour ne pas enregistrer plusieurs défauts
// à la place d'un seul, on ne traite que le plus gros blob d'un ensemble
// de blobs dont les box englobantes (agrandies) se recouvrent
nbGrosDefauts++;

idBlob = ii;
if(ii+1<m_NbBlobs)
{
do
{
// imagette blob en cours
rectblob1 = CalcRectImagette(m_pBlobCenterY[idBlob],Tx,Ty);

// recherche de l'index du gros défaut suivant
idBlobNext = ii+1;
while(idBlobNext<m_NbBlobs && m_pBlobArea[idBlobNext] <= m_pParams->m_SurfSeuilGrosDefautsPix)
idBlobNext++;

if(idBlobNext<=m_NbBlobs)
{
// imagette blob suivant
rectblob2 = CalcRectImagette(m_pBlobCenterY[idBlobNext],Tx,Ty);

// recherche de recouvrement
bIntersect = false;
if(recti.IntersectRect(&rectblob1,&rectblob2))
{
// si le recouvrement est supérieur à 50%, on ne garde que l'imagette
// du plus gros défaut
if(recti.Height()>=Tx/2)
{
bIntersect = true;
if(m_pBlobArea[idBlob]<m_pBlobArea[idBlobNext])
idBlob = idBlobNext;
ii = idBlobNext;
}
}
}
}
while(bIntersect && idBlobNext<=m_NbBlobs);
}
else
rectblob1 = CalcRectImagette(m_pBlobCenterY[idBlob],Tx,Ty);

/////////////////////
// IMAGETTE
/////////////////////

// imagette sur l'image d'origine mais en couleur pour pouvoir y dessiner le contour
child = M_NULL;
MbufChild2d(m_ImageSrc, rectblob1.left, rectblob1.top, rectblob1.Width(), rectblob1.Height(),&child);
MbufAllocColor(M_DEFAULT_HOST,3,m_pParams->m_TxBuf,m_pParams->m_TxBuf,8+M_UNSIGNED,M_IMAGE+M_PROC+M_RGB24+M_PLANAR,&(grosDefautsInfo.m_MilImagette));
MbufClear(grosDefautsInfo.m_MilImagette,0);
MbufCopyColor(child,grosDefautsInfo.m_MilImagette,M_ALL_BAND);
MbufFree(child);

// imagette sur l'image des blobs
child = M_NULL;
MbufChild2d(m_ImageTrt, rectblob1.left, rectblob1.top, rectblob1.Width(), rectblob1.Height(),&child);
MbufClear(m_CpyBufImagetteBinaire,0);
MbufCopy(child,m_CpyBufImagetteBinaire);
MbufFree(child);

// extension du blob pour "coller" au mieux au défaut réel
// Rq : l'algo "Extension" détermine d'abord les bords visibles du rail
// pour limiter l'extension au rail
Extension(grosDefautsInfo.m_MilImagette,m_CpyBufImagetteBinaire,xminRail,xmaxRail);

// nouvelle recherche de blob uniquement sur l'imagette pour dessiner son contour réel
// et recalcul de ses caractéristiques avant prise en compte dans le fichiers résultats
TraceBlob(grosDefautsInfo.m_MilImagette,
m_CpyBufImagetteBinaire,
m_pBlobArea[idBlob], m_pBlobRatioXY[idBlob], m_pBlobRatioXlargeurRail[idBlob],
xminRail,xmaxRail);


/////////////////////
// INFOS ASSOCIEES
/////////////////////

// recherche du pk interpolé à partir du pk de début d'image et de la position dans l'image
if(pLocalisationInfo->m_bPksCroissants)
PkBlob = pLocalisationInfo->m_Pk + m_pBlobCenterY[idBlob]*resolutionY / 1000000;
else
PkBlob = pLocalisationInfo->m_Pk - m_pBlobCenterY[idBlob]*resolutionY / 1000000;

if (idFile == -1)
grosDefautsInfo.m_File = pLocalisationInfo->m_File;
else
{
if (idFile == 1)
{
if(GetApp()->m_CurrentLanguage == "English")
{
if(pLocalisationInfo->m_File == "L/R")
grosDefautsInfo.m_File = "L";
else
grosDefautsInfo.m_File = "R";
}
else
{
if(pLocalisationInfo->m_File == "G/D")
grosDefautsInfo.m_File = "G";
else
grosDefautsInfo.m_File = "D";
}
}
else
{
if(GetApp()->m_CurrentLanguage == "English")
{
if(pLocalisationInfo->m_File == "L/R")
grosDefautsInfo.m_File = "R";
else
grosDefautsInfo.m_File = "L";
}
else
{
if(pLocalisationInfo->m_File == "G/D")
grosDefautsInfo.m_File = "D";
else
grosDefautsInfo.m_File = "G";
}
}

}


grosDefautsInfo.m_NumeroImage = pLocalisationInfo->m_NumeroImage;
grosDefautsInfo.m_Pk = (float)PkBlob;
grosDefautsInfo.m_NumLigneImage = (long)m_pBlobCenterY[idBlob];
grosDefautsInfo.m_bInverseData = pLocalisationInfo->m_bInverseData;
grosDefautsInfo.m_RatioXRailWidth = (float)m_pBlobRatioXlargeurRail[idBlob];
grosDefautsInfo.m_RatioXY = (float)m_pBlobRatioXY[idBlob];
grosDefautsInfo.m_Surface = (float)(m_pBlobArea[idBlob]*(resolutionX *resolutionY));

grosDefautsInfo.m_Time = pLocalisationInfo->m_Time;
grosDefautsInfo.m_IndexTrajet = pLocalisationInfo->m_IndexTrajet;

GrosDefsTab.Add(grosDefautsInfo);

}
}
}

return true;
}

//*****************************************************************************
// FastProcess
//*****************************************************************************

bool CRailImageProcessing::FastProcess(MIL_ID childFile)
{
bool bTraiteFileOK = true;

// recopie de l'image de la file
MbufGet(childFile,(void*)m_pBufImageSrc);

CString msg;
msg.Format("je traite le child n° %d",childFile);
// MessageInfo(msg);


// fast process : recherche de variations locales
SearchForLocalVariations(m_pBufImageSrc,m_pBufImageTrt);

// morpho et blobs
TraiteMorphBlobs(m_ImageTrt,m_MilResults);

// récupération des résultats des blobs pour les mettre à disposition des fonctions
// de création des résultats stats et des imagettes des gros défauts
GetBlobsResults();

return bTraiteFileOK;
}

//*******************************************************************************
// GetBlobResults
//*******************************************************************************

void CRailImageProcessing::GetBlobsResults()
{
// lecture des résultats des blobs de la file
m_NbBlobs = 0;
MblobGetNumber(m_MilResults, &m_NbBlobs);
if(m_NbBlobs>0)
{
// surface
m_pBlobArea = new double[m_NbBlobs];
if(m_pBlobArea!=NULL)
MblobGetResult(m_MilResults, M_AREA, m_pBlobArea);

// numéro de ligne dans l'image
m_pBlobCenterY = new double[m_NbBlobs];
if(m_pBlobCenterY!=NULL)
MblobGetResult(m_MilResults, M_CENTER_OF_GRAVITY_Y, m_pBlobCenterY);

// ratios pour les gros défauts
m_pBlobRatioXY = new double[m_NbBlobs];
m_pBlobRatioXlargeurRail = new double[m_NbBlobs];
}
}

//*****************************************************************************
// InitApplication
// Alloc des buffers de traitement
//*****************************************************************************

void CRailImageProcessing::InitApplication(CRailImageProcessingParams* pParams)
{
if(pParams == NULL)
AfxMessageBox("pas possible!!!!");

m_pParams = pParams;

// allocations de la ligne de projection pour le traitement
m_pProjBuf = NULL;
m_pProjBuf = (long *)malloc(m_pParams->m_TxBuf*sizeof(long));

// buffers de copie du child sur file (8 bits N&B)
m_pBufImageSrc = NULL;
m_pBufImageSrc = (unsigned char *)GlobalAlloc(GMEM_FIXED, m_pParams->m_TxBuf*m_pParams->m_TyBuf);
if(m_pBufImageSrc == NULL)
AfxMessageBox("CRailImageProcessing::Init() Echec allocation buffer de recopie");
else
{
m_ImageSrc = M_NULL;
MbufCreate2d(M_DEFAULT_HOST,
m_pParams->m_TxBuf,m_pParams->m_TyBuf,
8+M_UNSIGNED,
M_IMAGE+M_PROC,
M_DEFAULT, M_DEFAULT,
m_pBufImageSrc,
&m_ImageSrc);
if(m_ImageSrc == M_NULL)
AfxMessageBox("CRailImageProcessing::Init() Echec allocation buffer de traitement");
}

// buffer destination de traitement (8 bits BINAIRE)
m_pBufImageTrt = NULL;
m_pBufImageTrt = (unsigned char *)GlobalAlloc(GMEM_FIXED, m_pParams->m_TxBuf*m_pParams->m_TyBuf);
if(m_pBufImageTrt == NULL)
AfxMessageBox("CRailImageProcessing::Init() Echec allocation buffer de traitement");
else
{
m_ImageTrt = M_NULL;
MbufCreate2d(M_DEFAULT_HOST,
m_pParams->m_TxBuf,m_pParams->m_TyBuf,
8+M_UNSIGNED,
M_IMAGE+M_PROC,
M_DEFAULT, M_DEFAULT,
m_pBufImageTrt,
&m_ImageTrt);
if(m_ImageTrt == M_NULL)
AfxMessageBox("CRailImageProcessing::Init() Echec allocation buffer de traitement (2)");
}

// buffers pour l'extension du contour
// buffer imagette gros défaut (8 bits BINAIRE pour le contour)
// buffer imagette gros défaut (24 bits COULEUR pour le contour)
m_CpyBufImagetteBinaire = M_NULL;
MbufAlloc2d(M_DEFAULT_HOST,m_pParams->m_TxBuf,m_pParams->m_TxBuf,8+M_UNSIGNED,M_IMAGE+M_PROC,&m_CpyBufImagetteBinaire);
if(m_CpyBufImagetteBinaire == M_NULL)
AfxMessageBox("CRailImageProcessing::Init() Echec allocation buffers pour l'extension");

// traitement morpho défauts files
MblobAllocFeatureList(M_DEFAULT_HOST, &m_FeatureList);
MblobSelectFeature(m_FeatureList, M_AREA);
MblobSelectFeature(m_FeatureList, M_CENTER_OF_GRAVITY_Y);

// traitement morpho gros défauts
MblobAllocFeatureList(M_DEFAULT_HOST, &m_FeatureListDefauts);
MblobSelectFeature(m_FeatureListDefauts, M_AREA);
MblobSelectFeature(m_FeatureListDefauts, M_CENTER_OF_GRAVITY_X);
MblobSelectFeature(m_FeatureListDefauts, M_CENTER_OF_GRAVITY_Y);
MblobSelectFeature(m_FeatureListDefauts, M_BOX_X_MIN);
MblobSelectFeature(m_FeatureListDefauts, M_BOX_Y_MIN);
MblobSelectFeature(m_FeatureListDefauts, M_BOX_X_MAX);
MblobSelectFeature(m_FeatureListDefauts, M_BOX_Y_MAX);

//affinage du traitement directement sur l'imagette du gros defaut
MblobAllocFeatureList(M_DEFAULT_HOST, &m_FeatureListeImagetteDefaut);
MblobAllocResult(M_DEFAULT_HOST, &m_MilResultsImagettes); // imagettes de blob
MblobSelectFeature(m_FeatureListeImagetteDefaut, M_MEAN_PIXEL);

MblobAllocResult(M_DEFAULT_HOST, &m_MilResultsDefauts); // imagettes de blob
MblobAllocResult(M_DEFAULT_HOST, &m_MilResults);

// buffer pour l'extension de contours
m_ProjTab=(signed long *)malloc(m_pParams->m_TxBuf*4);
}

//*****************************************************************************
// FreeApplication
//*****************************************************************************

void CRailImageProcessing::FreeApplication()
{
if(m_MilResultsDefauts)
{
MblobFree(m_MilResultsDefauts);
m_MilResultsDefauts = M_NULL;
}
if(m_MilResults)
{
MblobFree(m_MilResults);
m_MilResults = M_NULL;
}
if(m_FeatureList)
{
MblobFree(m_FeatureList);
m_FeatureList = M_NULL;
}
if(m_FeatureListDefauts)
{
MblobFree(m_FeatureListDefauts);
m_FeatureListDefauts = M_NULL;
}

if(m_MilResultsImagettes)
{
MblobFree(m_MilResultsImagettes);
m_MilResultsImagettes = M_NULL;
}

if(m_FeatureListeImagetteDefaut)
{
MblobFree(m_FeatureListeImagetteDefaut);
m_FeatureListeImagetteDefaut = M_NULL;
}

// désallocation ligne de projection
free(m_pProjBuf);
m_pProjBuf = NULL;

// buffer source de recopie (8 bits N&B)
if(m_ImageSrc)
{
MbufFree(m_ImageSrc);
m_ImageSrc = M_NULL;
}
if(m_pBufImageSrc)
{
GlobalFree((HGLOBAL)m_pBufImageSrc);
m_pBufImageSrc = NULL;
}

// buffer destination de traitement (8 bits BINAIRE)
if(m_ImageTrt)
{
MbufFree(m_ImageTrt);
m_ImageTrt = M_NULL;
}
if(m_pBufImageTrt)
{
GlobalFree((HGLOBAL)m_pBufImageTrt);
m_pBufImageTrt = NULL;
}

// buffer imagette gros défaut (8 bits BINAIRE pour le contour)
if(m_CpyBufImagetteBinaire)
{
MbufFree(m_CpyBufImagetteBinaire);
m_CpyBufImagetteBinaire = M_NULL;
}

free(m_ProjTab);
}

//*****************************************************************************
// TraiteMorphBlobs
//*****************************************************************************

void CRailImageProcessing::TraiteMorphBlobs(MIL_ID MilBuf,MIL_ID resultBuf)
{
// Morphologies
MimErode(MilBuf, MilBuf,1,M_BINARY);
MimDilate(MilBuf, MilBuf,1,M_BINARY);

// Calcul de blobs
MblobControl(resultBuf, M_IDENTIFIER_TYPE, M_BINARY);
MblobCalculate(MilBuf, M_NULL, m_FeatureList, resultBuf);
}

//*****************************************************************************
// Connex
// Analyse dans un voisinnage V8
// Conditions de sortie de la fonction :
// - aucun des pixels voisins du pixel d'entrée [xx,yy]
// n'est en dehors du blob, donc le pixel d'entrée n'est pas élément
// du contour
//*****************************************************************************

void CRailImageProcessing::Connex(unsigned char *pimagette,
unsigned char *pimagetteBinaire,
long sizeXY,
int xx, int yy,
int xmin, int xmax,
int *pNbConnexions)
{
if(xx>1 && xx<(sizeXY-1) && yy>1 && yy<(sizeXY-1) && xx>xmin && xx<xmax)
{
// on cherche un voisin du pixel d'entrée:
// -> qui est en dehors du blob (imagette binarisée), donc le pixel d'entrée est un pixel de contour
// -> dont le niveau de gris est très faible dans l'imagette source
// (les défauts sont noirs sur la bande de roulement blanche)
// et qui est donc toujours un point du défaut réel
// dans ce cas, on l'affecte à 128 pour indiquer qu'il fait partie du blob
if(pimagette[(xx+1)+(yy)*sizeXY]<SEUIL_NG_CONNEXIONS && pimagetteBinaire[(xx+1)+(yy)*sizeXY]==0)
{
(*pNbConnexions)++;
//TRACE("\n*pNbConnexions = %d",*pNbConnexions);
pimagetteBinaire[(xx+1)+(yy)*sizeXY]=128;
if(*pNbConnexions<NB_CONNEXIONS_MAX)
Connex(pimagette,pimagetteBinaire,sizeXY,(xx+1),(yy),xmin,xmax,pNbConnexions);
}
if(pimagette[(xx-1)+(yy)*sizeXY]<SEUIL_NG_CONNEXIONS && pimagetteBinaire[(xx-1)+(yy)*sizeXY]==0)
{
(*pNbConnexions)++;
//TRACE("\n*pNbConnexions = %d",*pNbConnexions);
pimagetteBinaire[(xx-1)+(yy)*sizeXY]=128;
if(*pNbConnexions<NB_CONNEXIONS_MAX)
Connex(pimagette,pimagetteBinaire,sizeXY,(xx-1),(yy),xmin,xmax,pNbConnexions);
}
if(pimagette[(xx)+(yy+1)*sizeXY]<SEUIL_NG_CONNEXIONS && pimagetteBinaire[(xx)+(yy+1)*sizeXY]==0)
{
(*pNbConnexions)++;
//TRACE("\n*pNbConnexions = %d",*pNbConnexions);
pimagetteBinaire[(xx)+(yy+1)*sizeXY]=128;
if(*pNbConnexions<NB_CONNEXIONS_MAX)
Connex(pimagette,pimagetteBinaire,sizeXY,(xx),(yy+1),xmin,xmax,pNbConnexions);
}
if(pimagette[(xx)+(yy-1)*sizeXY]<SEUIL_NG_CONNEXIONS && pimagetteBinaire[(xx)+(yy-1)*sizeXY]==0)
{
(*pNbConnexions)++;
//TRACE("\n*pNbConnexions = %d",*pNbConnexions);
pimagetteBinaire[(xx)+(yy-1)*sizeXY]=128;
if(*pNbConnexions<NB_CONNEXIONS_MAX)
Connex(pimagette,pimagetteBinaire,sizeXY,(xx),(yy-1),xmin,xmax,pNbConnexions);
}
if(pimagette[(xx+1)+(yy+1)*sizeXY]<SEUIL_NG_CONNEXIONS && pimagetteBinaire[(xx+1)+(yy+1)*sizeXY]==0)
{
(*pNbConnexions)++;
//TRACE("\n*pNbConnexions = %d",*pNbConnexions);
pimagetteBinaire[(xx+1)+(yy+1)*sizeXY]=128;
if(*pNbConnexions<NB_CONNEXIONS_MAX)
Connex(pimagette,pimagetteBinaire,sizeXY,(xx+1),(yy+1),xmin,xmax,pNbConnexions);
}
if(pimagette[(xx+1)+(yy-1)*sizeXY]<SEUIL_NG_CONNEXIONS && pimagetteBinaire[(xx+1)+(yy-1)*sizeXY]==0)
{
(*pNbConnexions)++;
//TRACE("\n*pNbConnexions = %d",*pNbConnexions);
pimagetteBinaire[(xx+1)+(yy-1)*sizeXY]=128;
if(*pNbConnexions<NB_CONNEXIONS_MAX)
Connex(pimagette,pimagetteBinaire,sizeXY,(xx+1),(yy-1),xmin,xmax,pNbConnexions);
}
if(pimagette[(xx-1)+(yy+1)*sizeXY]<SEUIL_NG_CONNEXIONS && pimagetteBinaire[(xx-1)+(yy+1)*sizeXY]==0)
{
(*pNbConnexions)++;
//TRACE("\n*pNbConnexions = %d",*pNbConnexions);
pimagetteBinaire[(xx-1)+(yy+1)*sizeXY]=128;
if(*pNbConnexions<NB_CONNEXIONS_MAX)
Connex(pimagette,pimagetteBinaire,sizeXY,(xx-1),(yy+1),xmin,xmax,pNbConnexions);
}
if(pimagette[(xx-1)+(yy-1)*sizeXY]<SEUIL_NG_CONNEXIONS && pimagetteBinaire[(xx-1)+(yy-1)*sizeXY]==0)
{
(*pNbConnexions)++;
//TRACE("\n*pNbConnexions = %d",*pNbConnexions);
pimagetteBinaire[(xx-1)+(yy-1)*sizeXY]=128;
if(*pNbConnexions<NB_CONNEXIONS_MAX)
Connex(pimagette,pimagetteBinaire,sizeXY,(xx-1),(yy-1),xmin,xmax,pNbConnexions);
}
}
}

//*****************************************************************************
// Extension
// extension du contour des blobs pour "coller au mieux au défaut vrai"
// (visuel uniquement pour les imagettes sauvegardées des gros défauts)
//*****************************************************************************

void CRailImageProcessing::Extension(MIL_ID imagetteCouleur, // buffer source imagette
MIL_ID imagetteBinaire, // buffer binarisé imagette
int &xmin, int &xmax)
{
MIL_ID projbuf = M_NULL;
MIL_ID childMonochrome = M_NULL;
MbufChildColor(imagetteCouleur, M_GREEN, &childMonochrome);
unsigned char* pimagette = (unsigned char*)MbufInquire(childMonochrome,M_HOST_ADDRESS,M_NULL);
unsigned char* pimagetteBinaire = (unsigned char*)MbufInquire(imagetteBinaire,M_HOST_ADDRESS,M_NULL);
int xx,yy;
int Tx = MbufInquire(childMonochrome,M_SIZE_X,M_NULL);
int Ty = MbufInquire(childMonochrome,M_SIZE_Y,M_NULL);
int nbConnexions = 0;

// projection de l'imagette d'origine suivant les colonnes
MimAllocResult(M_DEFAULT_HOST,Tx,M_PROJ_LIST,&projbuf);
MimProject(childMonochrome,projbuf,M_0_DEGREE);
MimGetResult(projbuf,M_VALUE,m_ProjTab);

// recherche des colonnes de début et de fin de rail
for(xx=0; xx<Tx && m_ProjTab[xx]/Ty<SEUIL_NG_CONNEXIONS; xx++);
xmin=xx;
for(xx=(Tx-1); xx>=0 && m_ProjTab[xx]/Ty<SEUIL_NG_CONNEXIONS; xx--);
xmax=xx;

// extension du contour des blobs
for(yy=0; yy<Tx; yy++)
{
for(xx=0; xx<Tx; xx++)
{
// SI pixel elt du blob, ET pixel sur la bande de roulement
// ET pixel non déjà traité (255 non traité, 128 traité)
if(pimagetteBinaire[xx+yy*Tx]==255 && xx>xmin && xx<xmax)
{
nbConnexions=0;
pimagetteBinaire[xx+yy*Tx]=128;
Connex(pimagette,pimagetteBinaire,Tx,xx,yy,xmin,xmax,&nbConnexions);
}
}
}

MbufFree(childMonochrome);
MbufFree(projbuf);
}

//*****************************************************************************
// TraceBlob
//*****************************************************************************

bool CRailImageProcessing::TraceBlob(MIL_ID imagetteCouleur, // buffer source imagette
MIL_ID imagetteBinaire, // buffer binarisé imagette
double& areamax,
double& ratioXY,
double& ratioXlargeurRail,
int xminRail,
int xmaxRail)
{
MIL_ID childMonochrome = M_NULL;
MIL_ID childBlue = M_NULL;
long nbblobs = 0;
double* pBlobArea = NULL;
double* pBlobCentreY = NULL;
double* pBlobCentreX = NULL;
double* pBlobBoxXMin = NULL;
double* pBlobBoxYMin = NULL;
double* pBlobBoxXMax = NULL;
double* pBlobBoxYMax = NULL;
double* pBlobMean = NULL;
int indexblob = 0;
bool bOK = true;
double resX = theAppParams.m_ResolutionX;
double resY = theAppParams.m_ResolutionY;

MbufChildColor(imagetteCouleur, M_GREEN, &childMonochrome);
MbufChildColor(imagetteCouleur, M_BLUE, &childBlue);

// recherche des blobs "élargis"
MblobControl(m_MilResultsDefauts, M_IDENTIFIER_TYPE, M_BINARY);
MblobCalculate(imagetteBinaire, M_NULL, m_FeatureListDefauts, m_MilResultsDefauts);
MblobGetNumber(m_MilResultsDefauts, &nbblobs);

if(nbblobs>0)
{
pBlobArea = new double[nbblobs];
pBlobCentreY = new double[nbblobs];
pBlobCentreX = new double[nbblobs];
pBlobBoxXMin = new double[nbblobs];
pBlobBoxYMin = new double[nbblobs];
pBlobBoxXMax = new double[nbblobs];
pBlobBoxYMax = new double[nbblobs];
if(!pBlobArea || !pBlobCentreY || !pBlobCentreX || !pBlobBoxXMin || !pBlobBoxYMin || !pBlobBoxXMax || !pBlobBoxYMax)
{
ErrorMessage("TraceBlobs : echec allocation",ICON_STOP,GetApp()->m_bDebugGlobal);
bOK = false;
}
else
{
MblobGetResult(m_MilResultsDefauts, M_CENTER_OF_GRAVITY_Y, pBlobCentreY);
MblobGetResult(m_MilResultsDefauts, M_CENTER_OF_GRAVITY_X, pBlobCentreX);
MblobGetResult(m_MilResultsDefauts, M_AREA, pBlobArea);
MblobGetResult(m_MilResultsDefauts, M_BOX_X_MIN, pBlobBoxXMin);
MblobGetResult(m_MilResultsDefauts, M_BOX_Y_MIN, pBlobBoxYMin);
MblobGetResult(m_MilResultsDefauts, M_BOX_X_MAX, pBlobBoxXMax);
MblobGetResult(m_MilResultsDefauts, M_BOX_Y_MAX, pBlobBoxYMax);

// marquage du contour des blobs
MblobFill(m_MilResultsDefauts, childMonochrome, M_ALL_BLOBS + M_CONTOUR, 255);

// recherche du blob de plus grosse aire
areamax = 0;
for(int ii=0; ii<nbblobs; ii++)
if(pBlobArea[ii]>areamax)
{
areamax = pBlobArea[ii];
indexblob = ii;
}

// recherche des caractéristiques permettant le filtrage des joints
ratioXY = ((double)(pBlobBoxXMax[indexblob]-pBlobBoxXMin[indexblob])*resX)/((double)(pBlobBoxYMax[indexblob]-pBlobBoxYMin[indexblob])*resY);
ratioXlargeurRail = (double)(pBlobBoxXMax[indexblob]-pBlobBoxXMin[indexblob])/(double)(xmaxRail-xminRail);

//test d'elimination des defauts peus contrastés
//le blob concerné

//calcul de la moyenne locale
unsigned char* pDataImagette = (unsigned char*)MbufInquire(childBlue,M_HOST_ADDRESS,M_NULL);
int Ty,Tx;
MbufInquire(childBlue,M_SIZE_Y,&Ty);
MbufInquire(childBlue,M_SIZE_X,&Tx);
int moyenneLocaleRail = 0;
int indexPixelRail = 0;
int DebutX,FinX,DebutY,FinY;

if ((pBlobBoxXMin[indexblob]- MARGE_HORIZONTALE) < 0) DebutX = 0; else DebutX = (int)(pBlobBoxXMin[indexblob]- MARGE_HORIZONTALE);
if ((pBlobBoxXMax[indexblob]+ MARGE_HORIZONTALE) > Tx) FinX = Tx; else FinX = (int)(pBlobBoxXMax[indexblob]+ MARGE_HORIZONTALE);
if ((pBlobBoxYMin[indexblob]- MARGE_VERTICALE) < 0) DebutY = 0; else DebutY = (int)(pBlobBoxYMin[indexblob]- MARGE_VERTICALE);
if ((pBlobBoxYMax[indexblob]+ MARGE_VERTICALE) > Ty) FinY = Ty; else FinY = (int)(pBlobBoxYMax[indexblob]+ MARGE_VERTICALE);


MblobCalculate(imagetteBinaire,childBlue,m_FeatureListeImagetteDefaut,m_MilResultsImagettes);
long NbBlobs = 0;
MblobGetNumber(m_MilResultsImagettes, &NbBlobs);
pBlobMean = new double[NbBlobs];
MblobGetResult(m_MilResultsImagettes,M_MEAN_PIXEL,pBlobMean);

for (int ii=DebutX; ii<FinX;ii++)
for(int jj=DebutY;jj<FinY;jj++)
{
// on est en dehors du defaut
if (
(iipBlobBoxXMax[indexblob]) ||
(jjpBlobBoxYMax[indexblob])
)
{
indexPixelRail++;
moyenneLocaleRail += pDataImagette[ii+jj*FinX];
}
}

moyenneLocaleRail /= indexPixelRail;
float contraste = (float)abs((int)pBlobMean[indexblob] - moyenneLocaleRail)/(float)moyenneLocaleRail;
if ( contraste < m_pParams->m_SeuilContrasteGrosDefauts/100.0f)
bOK = false;


// tracé d'une croix au centre du blob principal
MgraColor(M_DEFAULT,M_RGB888(0, 255, 0));
MgraLine(M_DEFAULT,imagetteCouleur,
(int)pBlobCentreX[indexblob]-5,(int)pBlobCentreY[indexblob],
(int)pBlobCentreX[indexblob]+5,(int)pBlobCentreY[indexblob]);
MgraLine(M_DEFAULT,imagetteCouleur,
(int)pBlobCentreX[indexblob],(int)pBlobCentreY[indexblob]-5,
(int)pBlobCentreX[indexblob],(int)pBlobCentreY[indexblob]+5);

MblobSelect(m_MilResultsDefauts,M_DELETE,M_AREA,M_GREATER,0,M_NULL);


if(pBlobArea) delete pBlobArea;
if(pBlobCentreY) delete pBlobCentreY;
if(pBlobCentreX) delete pBlobCentreX;
if(pBlobBoxXMin) delete pBlobBoxXMin;
if(pBlobBoxYMin) delete pBlobBoxYMin;
if(pBlobBoxXMax) delete pBlobBoxXMax;
if(pBlobBoxYMax) delete pBlobBoxYMax;
if(pBlobMean) delete pBlobMean;
}
}
else
bOK = false;

MbufFree(childMonochrome);
MbufFree(childBlue);

return bOK;
}

//*******************************************************************************
// AddToResultatsDensites
// Sauvegarde des résultats statistiques par classe
//*******************************************************************************

void CRailImageProcessing::AddToResultatsDensites(CLocalisationInfo* pLocInfo,
CStatsInfo* ptabDensitesDefauts)
{
double resolution = theAppParams.m_ResolutionX*theAppParams.m_ResolutionY;
int ii;

ptabDensitesDefauts->m_NumeroImage = pLocInfo->m_NumeroImage;
ptabDensitesDefauts->m_Pk = pLocInfo->m_Pk;
ptabDensitesDefauts->m_Time = pLocInfo->m_Time;
ptabDensitesDefauts->m_IndexTrajet = pLocInfo->m_IndexTrajet;

// calcul du nombre de défauts de chaque classe pour cette image
ptabDensitesDefauts->m_Classe1 = 0;
ptabDensitesDefauts->m_Classe2 = 0;
ptabDensitesDefauts->m_Classe3 = 0;
ptabDensitesDefauts->m_Classe4 = 0;
for(ii=0; ii<m_NbBlobs; ii++)
{
if(m_pBlobArea[ii]*resolution < m_pParams->m_SurfSeuil1) ptabDensitesDefauts->m_Classe1++;
else if(m_pBlobArea[ii]*resolution < m_pParams->m_SurfSeuil2) ptabDensitesDefauts->m_Classe2++;
else if(m_pBlobArea[ii]*resolution < m_pParams->m_SurfSeuil3) ptabDensitesDefauts->m_Classe3++;
else ptabDensitesDefauts->m_Classe4++;
}
}

//*****************************************************************************
// DeleteAllBlobs
//*****************************************************************************

bool CRailImageProcessing::DeleteAllBlobs()
{
// reset des résultats d'analyse de blobs
MblobSelect(m_MilResults,M_DELETE,M_AREA,M_GREATER,0,M_NULL);

// tableau de résultats des blobs
DeleteBlobsResults();

return true;
}

//*******************************************************************************
// DeleteBlobsResults
//*******************************************************************************

void CRailImageProcessing::DeleteBlobsResults()
{
m_NbBlobs = 0;
if(m_pBlobArea)
{
delete m_pBlobArea;
m_pBlobArea = NULL;
}
if(m_pBlobCenterY)
{
delete m_pBlobCenterY;
m_pBlobCenterY = NULL;
}
if(m_pBlobRatioXY)
{
delete m_pBlobRatioXY;
m_pBlobRatioXY = NULL;
}
if(m_pBlobRatioXlargeurRail)
{
delete m_pBlobRatioXlargeurRail;
m_pBlobRatioXlargeurRail = NULL;
}


}