qreal restrictedAreaRadius( const Slice &slice, const iCoord2D &pithCoord, const uint &nbPolygonPoints, const int &intensityThreshold ) { Q_ASSERT_X( nbPolygonPoints>0 , "BillonTpl<T>::getRestrictedAreaMeansRadius", "nbPolygonPoints arguments equals to 0 => division by zero" ); const int width = slice.n_cols; const int height = slice.n_rows; const qreal angleIncrement = TWO_PI/static_cast<qreal>(nbPolygonPoints); rCoord2D center, edge; rVec2D direction; qreal orientation, radius, currentNorm; radius = width; center.x = pithCoord.x; center.y = pithCoord.y; orientation = width; while (orientation < TWO_PI) { orientation += angleIncrement; direction.x = qCos(orientation); direction.y = qSin(orientation); edge = center + direction*20; while ( edge.x>0 && edge.y>0 && edge.x<width && edge.y<height && slice.at(edge.y,edge.x) > intensityThreshold ) { edge += direction; } currentNorm = rVec2D(edge-center).norm(); if ( currentNorm < radius ) radius = currentNorm; } return radius; }
void writeInPgm3D( const Slice &slice, QDataStream &stream ) { uint i, j; for ( j=0 ; j<slice.n_rows ; ++j ) { for ( i=0 ; i<slice.n_cols ; ++i ) { stream << static_cast<qint16>(slice.at(j,i)); } } }
void draw( QPainter &painter, const Slice &slice, const uiCoord2D &pithCoord, const int &intensityThreshold, const TKD::ProjectionType &view ) { painter.save(); painter.setPen(QColor(255,255,255,127)); const uint width = painter.window().width(); const uint height = painter.window().height(); const qreal angularIncrement = TWO_PI/(qreal)(width); uint i, j, x, y; if ( view == TKD::Z_PROJECTION ) { for ( j=0 ; j<height ; ++j ) { for ( i=0 ; i<width ; ++i ) { if ( slice.at(j,i) > intensityThreshold ) painter.drawPoint(i,j); } } } else if ( view == TKD::CARTESIAN_PROJECTION ) { for ( j=0 ; j<height ; ++j ) { for ( i=0 ; i<width ; ++i ) { x = pithCoord.x + j * qCos(i*angularIncrement); y = pithCoord.y + j * qSin(i*angularIncrement); if ( slice.at(y,x) > intensityThreshold ) painter.drawPoint(i,j); } } } painter.restore(); }
void extractConnexComponents( Slice &resultSlice, const Slice & slice, const int & minimumSize, const int & threshold ) { const uint width = slice.n_cols; const uint height = slice.n_rows; QMap<int, QList<iCoord2D> > connexComponentList; QMap<int, int> tableEquiv; QList<int> voisinage; uint j, i; int mini, nbLabel, label, currentEquiv; Slice labels(height, width); labels.fill(0); nbLabel = 0; //On parcourt une première fois la tranche for ( j=1 ; j<height ; ++j) { for ( i=1 ; i<width-1 ; ++i) { //Si on a un voxel if ( slice.at(j,i) > threshold ) { //On sauvegarde la valeur des voisins non nuls voisinage.clear(); //Voisinage de la face courante if (labels.at(j,i-1)) voisinage.append(labels.at(j,i-1)); if (labels.at(j-1,i-1)) voisinage.append(labels.at(j-1,i-1)); if (labels.at(j-1,i)) voisinage.append(labels.at(j-1,i)); if (labels.at(j-1,i+1)) voisinage.append(labels.at(j-1,i+1)); //Si ses voisins n'ont pas d'étiquette if ( voisinage.isEmpty() ) { ++nbLabel; labels.at(j,i) = nbLabel; } //Si ses voisins ont une étiquette else if ( voisinage.size() == 1 ) { labels.at(j,i) = voisinage[0]; } else { QList<int>::ConstIterator iterVoisin = voisinage.constBegin(); mini = (*iterVoisin++); while ( iterVoisin != voisinage.constEnd() ) { mini = qMin(mini,(*iterVoisin++)); } labels.at(j,i) = mini; for ( iterVoisin = voisinage.constBegin() ; iterVoisin != voisinage.constEnd() ; ++iterVoisin ) { if ( (*iterVoisin) > mini ) { if ( tableEquiv.contains(*iterVoisin) ) { currentEquiv = tableEquiv[*iterVoisin]; if ( mini > currentEquiv ) { tableEquiv[*iterVoisin] = mini; while (tableEquiv.contains(mini)) { mini = tableEquiv[mini]; } if ( currentEquiv < mini ) { tableEquiv[mini] = currentEquiv; labels.at(j,i) = currentEquiv; } else if ( currentEquiv > mini ) { tableEquiv[currentEquiv] = mini; labels.at(j,i) = mini; } } else if ( mini < currentEquiv ) { tableEquiv[*iterVoisin] = currentEquiv; while (tableEquiv.contains(currentEquiv)) { currentEquiv = tableEquiv[currentEquiv]; } if ( currentEquiv > mini ) { tableEquiv[currentEquiv] = mini; labels.at(j,i) = mini; } else if ( currentEquiv < mini ) { tableEquiv[mini] = currentEquiv; labels.at(j,i) = currentEquiv; } } } else { tableEquiv[*iterVoisin] = mini; } } } } } } } //Résolution des chaines dans la table d'équivalence QMap<int, int>::ConstIterator iterTable; int value; for ( iterTable = tableEquiv.constBegin() ; iterTable != tableEquiv.constEnd() ; ++iterTable ) { value = iterTable.value(); while (tableEquiv.contains(value)) { value = tableEquiv[value]; } tableEquiv[iterTable.key()] = value; } for ( j=0 ; j<height ; ++j ) { for ( i=0 ; i<width ; ++i ) { label = labels.at(j,i); //Si on a un voxel if (label) { if (tableEquiv.contains(label)) { labels.at(j,i) = tableEquiv[label]; label = labels.at(j,i); } if (!connexComponentList.contains(label)) connexComponentList[label] = QList<iCoord2D>(); connexComponentList[label].append(iCoord2D(i,j)); } } } QMap<int, QList<iCoord2D> >::ConstIterator iterComponents; QList<iCoord2D>::ConstIterator iterCoords; int counter = 1; resultSlice.fill(0); for ( iterComponents = connexComponentList.constBegin() ; iterComponents != connexComponentList.constEnd() ; ++iterComponents ) { if ( iterComponents.value().size() > minimumSize ) { for ( iterCoords = iterComponents.value().constBegin() ; iterCoords != iterComponents.value().constEnd() ; ++ iterCoords ) { resultSlice.at((*iterCoords).y,(*iterCoords).x) = counter; } ++counter; } } }
iCoord2D findNearestPointOfThePith( const Slice &slice, const iCoord2D &sliceCenter, const int &intensityThreshold ) { // Find the pixel closest to the pith const int width = slice.n_cols; const int height = slice.n_rows; const int radiusMax = qMin( qMin(sliceCenter.x,width-sliceCenter.x), qMin(sliceCenter.y,height-sliceCenter.y) ); iCoord2D position, circlePoint; bool edgeFind = false; int currentRadius, d; currentRadius = 1; // Using Andres circle algorithm while ( !edgeFind && currentRadius < radiusMax ) { circlePoint.x = 0; circlePoint.y = currentRadius; d = currentRadius - 1; while ( circlePoint.y>=circlePoint.x && !edgeFind ) { edgeFind = true; if ( slice.at( sliceCenter.y+circlePoint.y, sliceCenter.x+circlePoint.x ) > intensityThreshold ) { position.x = sliceCenter.x+circlePoint.x; position.y = sliceCenter.y+circlePoint.y; } else if ( slice.at( sliceCenter.y+circlePoint.y, sliceCenter.x-circlePoint.x ) > intensityThreshold ) { position.x = sliceCenter.x-circlePoint.x; position.y = sliceCenter.y+circlePoint.y; } else if ( slice.at( sliceCenter.y+circlePoint.x, sliceCenter.x+circlePoint.y ) > intensityThreshold ) { position.x = sliceCenter.x+circlePoint.y; position.y = sliceCenter.y+circlePoint.x; } else if ( slice.at( sliceCenter.y+circlePoint.x, sliceCenter.x-circlePoint.y ) > intensityThreshold ) { position.x = sliceCenter.x-circlePoint.y; position.y = sliceCenter.y+circlePoint.x; } else if ( slice.at( sliceCenter.y-circlePoint.y, sliceCenter.x+circlePoint.x ) > intensityThreshold ) { position.x = sliceCenter.x+circlePoint.x; position.y = sliceCenter.y-circlePoint.y; } else if ( slice.at( sliceCenter.y-circlePoint.y, sliceCenter.x-circlePoint.x ) > intensityThreshold ) { position.x = sliceCenter.x-circlePoint.x; position.y = sliceCenter.y-circlePoint.y; } else if ( slice.at( sliceCenter.y-circlePoint.x, sliceCenter.x+circlePoint.y ) > intensityThreshold ) { position.x = sliceCenter.x+circlePoint.y; position.y = sliceCenter.y-circlePoint.x; } else if ( slice.at( sliceCenter.y-circlePoint.x, sliceCenter.x-circlePoint.y ) > intensityThreshold ) { position.x = sliceCenter.x-circlePoint.y; position.y = sliceCenter.y-circlePoint.x; } else { edgeFind = false; if ( d >= 2*circlePoint.x ) { d -= 2*circlePoint.x; circlePoint.x++; } else if ( d <= 2*(currentRadius-circlePoint.y) ) { d += 2*circlePoint.y; circlePoint.y--; } else { d += 2*(circlePoint.y-circlePoint.x); circlePoint.y--; circlePoint.x++; } } } currentRadius++; } if ( edgeFind ) { //qDebug() << "Pixel le plus proche de la moelle : ( " << position.x << ", " << position.y << " )"; return position; } else { qDebug() << "Aucun pixel et donc aucune composante connexe"; return iCoord2D(-1,-1); } }