Exemplo n.º 1
0
bool FIPAdaptiveThreshold::init()
{
    bool rValue=ImageProcessor::init();
    //Note: SharedImageBuffer of downstream producer is initialised with storage in ImageProcessor::init.
    
    size_t maxScratchDataSize=0;
    size_t maxScratchDataValues=0;
    
    for (uint32_t i=0; i<ImagesPerSlot_; i++)
    {
        const ImageFormat imFormat=getUpstreamFormat(i);
        
        const size_t width=imFormat.getWidth();
        const size_t height=imFormat.getHeight();
        
        const size_t bytesPerPixel=imFormat.getBytesPerPixel();
        const size_t componentsPerPixel=imFormat.getComponentsPerPixel();
        
        const size_t scratchDataSize = width * height * bytesPerPixel;
        const size_t scratchDataValues = width * height * componentsPerPixel;
        
        if (scratchDataSize>maxScratchDataSize)
        {
            maxScratchDataSize=scratchDataSize;
        }
        
        if (scratchDataValues>maxScratchDataValues)
        {
            maxScratchDataValues=scratchDataValues;
        }
    }
    
    //Allocate a buffer big enough for any of the image slots.
    _noiseFilteredInputData=new uint8_t[maxScratchDataSize];
    _scratchData=new uint8_t[maxScratchDataSize];
    memset(_noiseFilteredInputData, 0, maxScratchDataSize);
    memset(_scratchData, 0, maxScratchDataSize);
    
    _integralImageScratchData=new double[maxScratchDataValues];
    memset(_integralImageScratchData, 0, maxScratchDataValues*sizeof(double));
    
    return rValue;
}
Exemplo n.º 2
0
bool FIPDPT::trigger()
{
    if ((getNumReadSlotsAvailable())&&(getNumWriteSlotsAvailable()))
    {//There are images to consume and the downstream producer has space to produce.
        std::vector<Image**> imvRead=reserveReadSlot();
        std::vector<Image**> imvWrite=reserveWriteSlot();
        
        //Start stats measurement event.
        ProcessorStats_->tick();
        
        for (size_t imgNum=0; imgNum<1; ++imgNum)//For now, only process one image in each slot.
        {
            Image const * const imRead = *(imvRead[imgNum]);
            Image * const imWrite = *(imvWrite[imgNum]);
            
            uint8_t const * const dataRead=imRead->data();
            uint8_t * const dataWrite=imWrite->data();
            
            const ImageFormat imFormat=getDownstreamFormat(imgNum);
            
            const size_t width=imFormat.getWidth();
            const size_t height=imFormat.getHeight();
            
            memset(dataWrite, 0, width*height);//Clear the downstream image.
            
            
            //=== Setup the initial nodes ===//
            for (size_t y=0; y<height; ++y)
            {
                const size_t lineOffset=y * width;
                
                for (size_t x=0; x<width; ++x)
                {
                    const auto writeValue=dataRead[lineOffset + x];
                    
                    Node &node=nodeVect_[lineOffset + x];
                    node.index_=lineOffset + x;
                    node.value_=writeValue;
                    node.size_=1;
                    
#ifdef RUN_ARCS
                    node.arcIndices_.clear();
#else
                    node.neighbourIndices_.clear();
#endif
                    
                    node.pixelIndices_.clear();
                    node.pixelIndices_.push_back(lineOffset + x);
                }
            }
            //===  ==//
            
            
            //=== Setup the initial arcs or node neighbours ===//
            {
#ifdef RUN_ARCS
                size_t arcIndex=0;
#endif
                
                for (size_t y=0; y<height; ++y)
                {
                    const size_t lineOffset=y * width;
                    
                    for (size_t x=1; x<width; ++x)
                    {
#ifdef RUN_ARCS
                        Arc &arc=arcVect_[arcIndex];
                        arc.index_=arcIndex;
                        arc.active_=true;
                        
                        arc.nodeIndices_[0]=lineOffset+x-1;
                        arc.nodeIndices_[1]=lineOffset+x;
                        
                        nodeVect_[arc.nodeIndices_[0]].arcIndices_.push_back(arcIndex);
                        nodeVect_[arc.nodeIndices_[1]].arcIndices_.push_back(arcIndex);
                        arcIndex++;
#else
                        nodeVect_[lineOffset+x-1].neighbourIndices_.push_back(lineOffset+x);
                        nodeVect_[lineOffset+x].neighbourIndices_.push_back(lineOffset+x-1);
#endif
                    }
                    
                    if (y<(height-1))
                    {
                        for (size_t x=0; x<width; ++x)
                        {
#ifdef RUN_ARCS
                            Arc &arc=arcVect_[arcIndex];
                            arc.index_=arcIndex;
                            arc.active_=true;
                            
                            arc.nodeIndices_[0]=lineOffset+x;
                            arc.nodeIndices_[1]=lineOffset+x+width;
                            
                            nodeVect_[arc.nodeIndices_[0]].arcIndices_.push_back(arcIndex);
                            nodeVect_[arc.nodeIndices_[1]].arcIndices_.push_back(arcIndex);
                            arcIndex++;
#else
                            nodeVect_[lineOffset+x].neighbourIndices_.push_back(lineOffset+x+width);
                            nodeVect_[lineOffset+x+width].neighbourIndices_.push_back(lineOffset+x);
#endif
                        }
                    }
                }
            }
            //=== ===
            
            size_t policyCounter=0;
            
            size_t numBumpsRemoved=0;
            size_t numPitsRemoved=0;
            
            size_t numPulsesMerged=mergeFromAll();//Initial merge.
            
            updatePotentiallyActiveNodeIndexVect();
            
            std::vector<int32_t> nodeIndicesToMerge;
            
            size_t loopCounter = 0;
            int32_t previousSmallestPulse = 0;
            
            while ((previousSmallestPulse<filterPulseSize_)&&(potentiallyActiveNodeIndexVect_.size()>1))
            {
                nodeIndicesToMerge.clear();
                
                //=== Find smallest pulse ===//
                int32_t smallestPulse=0;
                
                for (const auto & potentiallyActiveNodeIndex : potentiallyActiveNodeIndexVect_)
                {
                    Node &node=nodeVect_[potentiallyActiveNodeIndex];
                    
                    if (node.size_>0)
                    {
                        if ((smallestPulse==0)||(node.size_<smallestPulse))
                        {
                            //if (isBump(node.index_)||isPit(node.index_))
                            //if (node.size_>previousSmallestPulse)
                            {
                                smallestPulse=node.size_;
                            }
                        }
                    }
                }
                //std::cout << "Smallest pulse is " << smallestPulse << ".\n";
                //std::cout.flush();
                //=== ===//
                
                
                //=== Implement DPT pit/bump policy ===//
                if (previousSmallestPulse!=smallestPulse)
                {
                    policyCounter=0;
                }
                //=== ===//
                
                
                //=== Remove pits and bumps according to policy ===//
                for (const auto & potentiallyActiveNodeIndex : potentiallyActiveNodeIndexVect_)
                {
                    Node &node=nodeVect_[potentiallyActiveNodeIndex];
                    
                    if ((node.size_>0)&&(node.size_<=smallestPulse))
                    {
                        if ((policyCounter%2)==0)
                        {
                            //if (isPit(node.index_))
                            {
                                //=== Remove pits ===//
                                flattenToNearestNeighbour(node.index_);
                                //flattenToFirstNeighbour(node.index_);
                                nodeIndicesToMerge.push_back(node.index_);
                                ++numPitsRemoved;
                            }
                        } else
                        {
                            //if (isBump(node.index_))
                            {
                                //=== Remove bumps ===//
                                flattenToNearestNeighbour(node.index_);
                                //flattenToFirstNeighbour(node.index_);
                                nodeIndicesToMerge.push_back(node.index_);
                                ++numBumpsRemoved;
                            }
                        }
                    }
                }
                //=== ===//
                
                
                //std::cout << "Pulses merged = " << numPulsesMerged << ".\n";
                //std::cout << "Pits removed = " << numPitsRemoved << ".\n";
                //std::cout << "Bumps removed = " << numBumpsRemoved << ".\n";
                //std::cout << "\n";
                //std::cout.flush();
                
                
                //=== Merge over arcs of removed nodes ===//
                numPulsesMerged=mergeFromList(nodeIndicesToMerge);
                //=== ===//
                
                ++policyCounter;
                previousSmallestPulse=smallestPulse;
                
                if ((loopCounter&15)==0) updatePotentiallyActiveNodeIndexVect();
                ++loopCounter;
            }
            
            
            //=============================================//
            //=============================================//
            //=============================================//
            
            
            {
                //=== Find smallest pulse ==
                int32_t smallestPulse=0;
                for (const auto & node : nodeVect_)
                {
                    if (node.size_>0)
                    {
                        if ((smallestPulse==0)||(node.size_<smallestPulse))
                        {
                            //if (isBump(node.index_)||isPit(node.index_))
                            {
                                smallestPulse=node.size_;
                            }
                        }
                    }
                }
                //=== ===
                
                //std::cout << "Drawing pulses of size " << smallestPulse << "+.\n";
                //std::cout.flush();
                
                //=== Draw the pulses on the sceen ==
                for (const auto & node : nodeVect_)
                {
                    if (node.size_>0)
                    {
                        //if (node.size_==smallestPulse)
                        {
                            for (const auto pixelIndex : node.pixelIndices_)
                            {
                                dataWrite[pixelIndex]=node.value_;
                            }
                        }
                    }
                }
                
                //std::cout << "\n";
                //std::cout.flush();
                //=== ===
            }
        }
        
        //Stop stats measurement event.
        ProcessorStats_->tock();
        
        releaseWriteSlot();
        releaseReadSlot();
        
        return true;
    }
    
    return false;
}
Exemplo n.º 3
0
bool FIPAdaptiveThreshold::trigger()
{
    if ((getNumReadSlotsAvailable())&&(getNumWriteSlotsAvailable()))
    {
        std::vector<Image**> imvRead=reserveReadSlot();
        std::vector<Image**> imvWrite=reserveWriteSlot();
        
        //Start stats measurement event.
        ProcessorStats_->tick();
        
        for (size_t imgNum=0; imgNum<ImagesPerSlot_; ++imgNum)
        {
            Image const * const imReadUS = *(imvRead[imgNum]);
            Image * const imWriteDS = *(imvWrite[imgNum]);
            const ImageFormat imFormat=getDownstreamFormat(imgNum);//down stream and up stream formats are the same.
            
            if (!_enabled)
            {
                uint8_t const * const dataReadUS=(uint8_t const * const)imReadUS->data();
                uint8_t * const dataWriteDS=(uint8_t * const)imWriteDS->data();
                const size_t bytesPerImage=imFormat.getBytesPerImage();
                memcpy(dataWriteDS, dataReadUS, bytesPerImage);
            } else
            {
                const size_t width=imFormat.getWidth();
                const size_t height=imFormat.getHeight();
                const size_t numElements=width * height * imFormat.getComponentsPerPixel();
                
                if (imFormat.getPixelFormat()==ImageFormat::FLITR_PIX_FMT_Y_F32)
                {
                    float const * const dataReadUS=(float const * const)imReadUS->data();
                    float * const dataWriteDS=(float * const)imWriteDS->data();
                    
                    //Small kernel noise filter.
                    _noiseFilter.filter((float *)_noiseFilteredInputData, dataReadUS, width, height,
                                        _integralImageScratchData, true);
                    
                    for (short i=1; i<_numIntegralImageLevels; ++i)
                    {
                        memcpy(_scratchData, _noiseFilteredInputData, width*height*sizeof(uint8_t));
                        
                        _noiseFilter.filter((float *)_noiseFilteredInputData, (float *)_scratchData, width, height,
                                            _integralImageScratchData, true);
                    }
                    
                    
                    for (size_t i=0; i<numElements; ++i)
                    {
                        dataWriteDS[i]=1.0;
                    }
                    
                    
                    //Large kernel adaptive reference.
                    _boxFilter.filter(dataWriteDS, dataReadUS, width, height,
                                      _integralImageScratchData, true);
                    
                    for (short i=1; i<_numIntegralImageLevels; ++i)
                    {
                        memcpy(_scratchData, dataWriteDS, width*height*sizeof(float));
                        
                        _boxFilter.filter(dataWriteDS, (float *)_scratchData, width, height,
                                          _integralImageScratchData, true);
                    }
                    
                    
                    const float tovF32=_thresholdOffset * 1.0f;
                    size_t tpc=0;
                    
                    for (size_t i=0; i<numElements; ++i)
                    {
                        if (( ((float *)_noiseFilteredInputData)[i] - tovF32) > dataWriteDS[i])
                        {
                            dataWriteDS[i]=1.0;
                            ++tpc;
                        } else
                        {
                            dataWriteDS[i]=0.0;
                        }
                    }
                    
                    _thresholdAvrg=tpc;// / double(width*height);
                } else
                    if (imFormat.getPixelFormat()==ImageFormat::FLITR_PIX_FMT_Y_8)
                    {
                        uint8_t const * const dataReadUS=(uint8_t const * const)imReadUS->data();
                        uint8_t * const dataWriteDS=(uint8_t * const)imWriteDS->data();
                        
                        //Small kernel noise filter.
                        _noiseFilter.filter((uint8_t *)_noiseFilteredInputData, dataReadUS, width, height,
                                            _integralImageScratchData, true);
                        
                        for (short i=1; i<_numIntegralImageLevels; ++i)
                        {
                            memcpy(_scratchData, _noiseFilteredInputData, width*height*sizeof(uint8_t));
                            
                            _noiseFilter.filter((uint8_t *)_noiseFilteredInputData, (uint8_t *)_scratchData, width, height,
                                                _integralImageScratchData, true);
                        }
                        
                        
                        for (size_t i=0; i<numElements; ++i)
                        {
                            dataWriteDS[i]=255;
                        }
                        
                        
                        //Large kernel adaptive reference.
                        _boxFilter.filter(dataWriteDS, dataReadUS, width, height,
                                          _integralImageScratchData, true);
                        
                        for (short i=1; i<_numIntegralImageLevels; ++i)
                        {
                            memcpy(_scratchData, dataWriteDS, width*height*sizeof(uint8_t));
                            
                            _boxFilter.filter(dataWriteDS, (uint8_t *)_scratchData, width, height,
                                              _integralImageScratchData, true);
                        }
                        
                        
                        const uint8_t tovUInt8=_thresholdOffset * 255.5;
                        size_t tpc=0;
                        
                        for (size_t i=0; i<numElements; ++i)
                        {
                            if (( ((uint8_t *)_noiseFilteredInputData)[i] - tovUInt8) > dataWriteDS[i])
                            {
                                dataWriteDS[i]=255;
                                ++tpc;
                            } else
                            {
                                dataWriteDS[i]=0;
                            }
                        }
                        
                        _thresholdAvrg=tpc / double(width*height);
                    }
            }
        }
        
        //Stop stats measurement event.
        ProcessorStats_->tock();
        
        releaseWriteSlot();
        releaseReadSlot();
        
        return true;
    }
    
    return false;
}