ZSwcTree* ZSwcGenerator::createSwc( const ZVoxelArray &voxelArray, ZSwcGenerator::EPostProcess option) { if (option == REGION_SAMPLING) { return createSwcByRegionSampling(voxelArray); } size_t startIndex = 0; size_t endIndex = voxelArray.size() - 1; Swc_Tree *tree = New_Swc_Tree(); const std::vector<ZVoxel> &voxelData = voxelArray.getInternalData(); ZVoxel prevVoxel = voxelData[startIndex]; Swc_Tree_Node *tn = New_Swc_Tree_Node(); SwcTreeNode::setPos(tn, prevVoxel.x(), prevVoxel.y(), prevVoxel.z()); SwcTreeNode::setRadius(tn, prevVoxel.value()); Swc_Tree_Node *prevTn = tn; for (size_t i = startIndex + 1; i < endIndex; i++) { double dist = voxelData[i].distanceTo(prevVoxel); bool sampling = true; if (option == SPARSE_SAMPLING) { if (dist < prevVoxel.value()) { sampling = false; } } if (sampling) { tn = New_Swc_Tree_Node(); SwcTreeNode::setPos(tn, voxelData[i].x(), voxelData[i].y(), voxelData[i].z()); SwcTreeNode::setRadius(tn, voxelData[i].value()); Swc_Tree_Node_Set_Parent(prevTn, tn); prevTn = tn; prevVoxel = voxelData[i]; } } if (endIndex - startIndex > 0) { //last node tn = New_Swc_Tree_Node(); SwcTreeNode::setPos(tn, voxelData[endIndex].x(), voxelData[endIndex].y(), voxelData[endIndex].z()); SwcTreeNode::setRadius(tn, voxelData[endIndex].value()); Swc_Tree_Node_Set_Parent(prevTn, tn); /* if (SwcTreeNode::hasOverlap(prevTn, tn) && SwcTreeNode::hasChild(prevTn)) { SwcTreeNode::mergeToParent(prevTn); } */ } tree->root = tn; ZSwcTree *treeWrapper = new ZSwcTree; treeWrapper->setData(tree); if (option == OPTIMAL_SAMPLING) { ZSwcResampler resampler; resampler.optimalDownsample(treeWrapper); } return treeWrapper; }
ZSwcTree* ZNeuronTracer::trace(Stack *stack, bool doResampleAfterTracing) { startProgress(); ZSwcTree *tree = NULL; //Extract seeds //First mask std::cout << "Binarizing ..." << std::endl; /* <bw> allocated */ Stack *bw = binarize(stack); C_Stack::translate(bw, GREY, 1); advanceProgress(0.05); std::cout << "Removing noise ..." << std::endl; /* <mask> allocated */ Stack *mask = bwsolid(bw); advanceProgress(0.05); /* <bw> freed */ C_Stack::kill(bw); //Thin line mask /* <mask2> allocated */ Stack *mask2 = NULL; if (m_enhancingMask) { std::cout << "Enhancing thin branches ..." << std::endl; mask2 = enhanceLine(stack); advanceProgress(0.05); } if (mask2 != NULL) { std::cout << "Making mask for thin branches ..." << std::endl; ZStackBinarizer binarizer; binarizer.setMethod(ZStackBinarizer::BM_LOCMAX); binarizer.setRetryCount(5); binarizer.setMinObjectSize(27); if (binarizer.binarize(mask2) == false) { std::cout << "Thresholding failed" << std::endl; C_Stack::kill(mask2); mask2 = NULL; } } /* <mask2> freed */ if (mask2 != NULL) { C_Stack::translate(mask2, GREY, 1); Stack_Or(mask, mask2, mask); C_Stack::kill(mask2); mask2 = NULL; } advanceProgress(0.05); //Trace each seed std::cout << "Extracting seed points ..." << std::endl; /* <seedPointArray> allocated */ Geo3d_Scalar_Field *seedPointArray = extractSeed(mask); m_mask = mask; advanceProgress(0.05); std::cout << "Sorting seeds ..." << std::endl; ZNeuronTraceSeeder seeder; setTraceScoreThreshold(TRACING_SEED); m_baseMask = seeder.sortSeed(seedPointArray, stack, m_traceWorkspace); #ifdef _DEBUG_2 C_Stack::write(GET_TEST_DATA_DIR + "/test.tif", m_baseMask); #endif advanceProgress(0.1); /* <seedPointArray> freed */ Kill_Geo3d_Scalar_Field(seedPointArray); std::vector<Local_Neuroseg>& locsegArray = seeder.getSeedArray(); std::vector<double>& scoreArray = seeder.getScoreArray(); std::cout << "Tracing ..." << std::endl; /* <chainArray> allocated */ std::vector<Locseg_Chain*> chainArray = trace(stack, locsegArray, scoreArray); if (m_recover > 0) { std::vector<Locseg_Chain*> newChainArray = recover(stack); chainArray.insert( chainArray.end(), newChainArray.begin(), newChainArray.end()); } advanceProgress(0.1); chainArray = screenChain(stack, chainArray); advanceProgress(0.3); /* <mask2> freed */ // C_Stack::kill(mask); std::cout << "Reconstructing ..." << std::endl; ZNeuronConstructor constructor; constructor.setWorkspace(m_connWorkspace); constructor.setSignal(stack); //Create neuron structure BOOL oldSpTest = m_connWorkspace->sp_test; if (chainArray.size() > 1000) { std::cout << "Too many chains: " << chainArray.size() << std::endl; std::cout << "Turn off shortest path test" << std::endl; m_connWorkspace->sp_test = FALSE; } /* free <chainArray> */ tree = constructor.reconstruct(chainArray); m_connWorkspace->sp_test = oldSpTest; advanceProgress(0.1); //Post process Swc_Tree_Remove_Zigzag(tree->data()); Swc_Tree_Tune_Branch(tree->data()); Swc_Tree_Remove_Spur(tree->data()); Swc_Tree_Merge_Close_Node(tree->data(), 0.01); Swc_Tree_Remove_Overshoot(tree->data()); if (doResampleAfterTracing) { ZSwcResampler resampler; resampler.optimalDownsample(tree); } advanceProgress(0.1); std::cout << "Done!" << std::endl; endProgress(); return tree; }