bool IPLGradientOperator::roberts(IPLImage* image)
{
    static float rxf[2][2] = {{1.0,0},{0,-1.0}};
    static cv::Mat rxKernel(2,2,CV_32FC1,rxf);
    static float ryf[2][2] = {{0,1.0},{-1.0,0}};
    static cv::Mat ryKernel(2,2,CV_32FC1,ryf);

    int width = image->width();
    int height = image->height();

    // fast gradient
    int progress = 0;
    int maxProgress = height*width;

    notifyProgressEventHandler(-1);

    cv::Mat input;
    cv::Mat gX;
    cv::Mat gY;
    cvtColor(image->toCvMat(),input,CV_BGR2GRAY);

    filter2D(input,gX,CV_32F,rxKernel);
    filter2D(input,gY,CV_32F,ryKernel);

    for(int x=1; x<width; x++)
    {
        // progress
        notifyProgressEventHandler(100*progress++/maxProgress);
        for(int y=1; y<height; y++)
        {
          ipl_basetype gx = gX.at<cv::Vec<float,1>>(y,x).val[0] * FACTOR_TO_FLOAT ;
          ipl_basetype gy = gY.at<cv::Vec<float,1>>(y,x).val[0] * FACTOR_TO_FLOAT ;

          double phase = (gx!=0.0 || gy!=0.0 )? atan2( -gy, gx ) : 0.0;

          while( phase > 2.0 * PI ) phase -= 2.0 * PI;
          while( phase < 0.0 ) phase += 2.0 * PI;

          // phase 0.0-1.0
          phase /= 2 * PI;

          _result->phase(x,y) = phase;
          _result->magnitude(x,y) = sqrt(gx*gx + gy*gy);
        }
    }

   return true;
}
bool IPLGradientOperator::fastGradient(IPLImage* image)
{
    int width = image->width();
    int height = image->height();

    // fast gradient
    int progress = 0;
    int maxProgress = height*width;
    for(int x=1; x<width; x++)
    {
        // progress
        notifyProgressEventHandler(100*progress++/maxProgress);
        for(int y=1; y<height; y++)
        {
            double Dx = image->plane(0)->p(x,y) - image->plane(0)->p(x-1, y);
            double Dy = image->plane(0)->p(x,y) - image->plane(0)->p(x, y-1);
            double magnitude = sqrt( Dx * Dx + Dy * Dy );
            double phase = (Dx!=0.0 || Dy!=0.0 )? atan2( -Dy, Dx ) : 0.0;

            while( phase > 2.0 * PI ) phase -= 2.0 * PI;
            while( phase < 0.0 ) phase += 2.0 * PI;

            // phase 0.0-1.0
            phase /= 2 * PI;

            _result->phase(x,y) = phase;
            _result->magnitude(x,y) = magnitude;
        }
    }

    return true;
}
Exemplo n.º 3
0
bool IPLCompassMask::processInputData(IPLImage* image , int, bool)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width = image->width();
    int height = image->height();
    _result = new IPLImage( image->type(), width, height );

    // get properties
    int maskType = getProcessPropertyInt("maskType");
    int direction = getProcessPropertyInt("direction");

    int progress = 0;
    int maxProgress = image->height() * image->getNumberOfPlanes();
    int nrOfPlanes = image->getNumberOfPlanes();

    int startDir = ( direction == 8 )? 0 : direction;
    int endDir = ( direction == 8 )? 7 : direction+1;

    #pragma omp parallel for
    for( int planeNr=0; planeNr < nrOfPlanes; planeNr++ )
    {
        IPLImagePlane* plane = image->plane( planeNr );
        IPLImagePlane* newplane = _result->plane( planeNr );
        {
            for(int y=0; y<height; y++)
            {
                // progress
                notifyProgressEventHandler(100*progress++/maxProgress);
                for(int x=0; x<width; x++)
                {
                    int dirCount = 0;
                    long sum = 0;
                    long total = 0;
                    for( int dir = startDir; dir<endDir; dir++ )
                    {
                        dirCount++;
                        sum = 0;
                        for( int kx=-1; kx<=1; kx++ )
                        {
                            for( int ky=-1; ky<=1; ky++ )
                            {
                                int mask = _mask[maskType][dir][ky+1][kx+1];
                                sum += (long) (plane->cp(x+kx, y+ky) * FACTOR_TO_UCHAR) * (long) mask;
                            }
                        }
                        total += sum;
                    }
                    total /= dirCount;
                    total += 128;
                    total = (total>255)? 255 : (total<0)? 0 : total;
                    newplane->p(x,y) = total * FACTOR_TO_FLOAT;
                }
            }
        }
    }
    return true;
}
Exemplo n.º 4
0
bool IPLUndistort::processInputData(IPLImage* image, int, bool)
{
    // get properties
    float k1 = getProcessPropertyDouble("k1");
    float k2 = getProcessPropertyDouble("k2");
    float k3 = getProcessPropertyDouble("k3");
    float p1 = getProcessPropertyDouble("p1");
    float p2 = getProcessPropertyDouble("p2");

    float c1 = getProcessPropertyInt("f");
    float c2 = c1;

    notifyProgressEventHandler(-1);

    cv::Mat cameraMatrix = (cv::Mat_<double>(3,3) << c1, 0, image->width()*0.5, 0, c2, image->height()*0.5, 0, 0, 1);


    cv::Mat distCoeffs(5, 1, CV_32FC1);
    distCoeffs.at<float>(0,0) = k1;
    distCoeffs.at<float>(1,0) = k2;
    distCoeffs.at<float>(2,0) = p1;
    distCoeffs.at<float>(3,0) = p2;
    distCoeffs.at<float>(4,0) = k3;

    cv::Mat result;
    cv::undistort(image->toCvMat(), result, cameraMatrix, distCoeffs);

    delete _result;
    _result = new IPLImage(result);

    return true;
}
bool IPLGradientOperator::sobel(IPLImage* image)
{
   int width = image->width();
   int height = image->height();

   const int kSize = 3;

   // fast gradient
   int progress = 0;
   int maxProgress = height*width;

   notifyProgressEventHandler(-1);

   cv::Mat input;
   cv::Mat gX;
   cv::Mat gY;
   cvtColor(image->toCvMat(),input,CV_BGR2GRAY);
 
   Sobel(input,gX,CV_32F,1,0,kSize);
   Sobel(input,gY,CV_32F,0,1,kSize);
 
   for(int x=1; x<width; x++)
   {
       for(int y=1; y<height; y++)
       {
       // progress
       notifyProgressEventHandler(100*progress++/maxProgress);
         ipl_basetype gx = gX.at<cv::Vec<float,1>>(y,x).val[0] * FACTOR_TO_FLOAT ;
         ipl_basetype gy = gY.at<cv::Vec<float,1>>(y,x).val[0] * FACTOR_TO_FLOAT ;
         
         double phase = (gx!=0.0 || gy!=0.0 )? atan2( -gy, gx ) : 0.0;
 
         while( phase > 2.0 * PI ) phase -= 2.0 * PI;
         while( phase < 0.0 ) phase += 2.0 * PI;
 
         phase /= 2.0 * PI;
 
         _result->phase(x,y) = phase;
         _result->magnitude(x,y) = sqrt(gx*gx + gy*gy);
       }
    }
    return true;
}
Exemplo n.º 6
0
bool IPLIFFT::processInputData(IPLImage* data , int, bool)
{
    IPLComplexImage* complexImageData = data->toComplexImage();
    if (NULL == complexImageData) {
        // TODO write an error message
        return false;
    }
    _complexImage = new IPLComplexImage(*complexImageData);

    // delete previous result
    delete _result;
    _result = NULL;

    int width = _complexImage->width();
    int height = _complexImage->height();

    _result = new IPLImage(IPL_IMAGE_GRAYSCALE, width, height);

    // get properties
    //int mode = getProcessPropertyInt("mode");

    int progress = 0;
    int maxProgress = height;

    _complexImage->IFFT();

    float dc = _complexImage->real(0,0);

    float min = _complexImage->minReal();
    float max = _complexImage->maxReal();

    float diff = max-min;

    for(int y=0; y<height; y++)
    {
        // progress
        notifyProgressEventHandler(100*progress++/maxProgress);
        for(int x=0; x<width; x++)
        {
            float value = (_complexImage->real(x,y) - min) / diff;
            value = (value < 0) ? 0 : value;
            value = (value > 1) ? 1 : value;
            _result->plane(0)->p(x, y) = value;
        }
    }

    std::stringstream s;
    s << "DC: ";
    s << dc;
    addInformation(s.str());

    return true;
}
void IPLMorphologyHitMiss::hitmiss(IPLImagePlane* workingPlane, IPLImagePlane* resultPlane)
{
    int kernelOffset = (int)sqrt((float)_kernel.size()) / 2;

    int width = workingPlane->width();
    int height = workingPlane->height();

    for(int y=0; y<height; y++)
    {
        // progress
        notifyProgressEventHandler(100*_progress++/_maxProgress);

        for(int x=0; x<width; x++)
        {
            int i = 0;
            bool success = true;
            for( int ky=-kernelOffset; ky<=kernelOffset && success; ky++ )
            {
                for( int kx=-kernelOffset; kx<=kernelOffset && success; kx++ )
                {
                    if(i >= (int) _kernel.size())
                        continue;

                    int kernelValue = _kernel[i++];
                    int r = x+kx;
                    int c = y+ky;
                    if(kernelValue > -1)
                        if(kernelValue != (workingPlane->bp(r,c) ? 1 : 0))
                            success = false; // breaks both for loops
                }
            }

            if(success)
                resultPlane->p(x,y) = 1.0f;
        }
    }
}
Exemplo n.º 8
0
bool IPLCanvasSize::processInputData(IPLImage* image , int, bool)
{
    // delete previous result
    delete _result;
    _result = NULL;
    int width  = image->width();
    int height = image->height();

    _result = new IPLImage(image->type(), width, height);

    // get properties
    int         new_width   = getProcessPropertyInt("width");
    int         new_height  = getProcessPropertyInt("height");
    IPLColor    color       = getProcessPropertyColor("color");
    int         anchor      = getProcessPropertyInt("anchor");

    _result = new IPLImage(image->type(), new_width, new_height);

    int progress = 0;
    int maxProgress = image->height() * image->getNumberOfPlanes();
    int nrOfPlanes = _result->getNumberOfPlanes();

    //Anchor:Top Left|Top|Top Right|Left|Center|Right|Bottom Left|Bottom|Bottom Right

    // Top Left
    int offset_x = 0;
    int offset_y = 0;
    if(anchor == 1)
    {
        // Top
        offset_x = (new_width-width) * 0.5;
        offset_y = 0;
    }
    else if(anchor == 2)
    {
        // Top Right
        offset_x = new_width-width;
        offset_y = 0;
    }
    else if(anchor == 3)
    {
        // Left
        offset_x = 0;
        offset_y = (new_height-height) * 0.5;
    }
    else if(anchor == 4)
    {
        // Center
        offset_x = (new_width-width) * 0.5;
        offset_y = (new_height-height) * 0.5;
    }
    else if(anchor == 5)
    {
        // Right
        offset_x = new_width-width;
        offset_y = (new_height-height) * 0.5;
    }
    else if(anchor == 6)
    {
        // Bottom Left
        offset_x = 0;
        offset_y = new_height-height;
    }
    else if(anchor == 7)
    {
        // Bottom
        offset_x = (new_width-width) * 0.5;
        offset_y = new_height-height;
    }
    else if(anchor == 8)
    {
        // Bottom Right
        offset_x = new_width-width;
        offset_y = new_height-height;
    }

    if(nrOfPlanes == 1)
    {
        addWarning("For grayscale images, the red slider is used as background value.");
    }

    #pragma omp parallel for
    for( int planeNr=0; planeNr < nrOfPlanes; planeNr++ )
    {
        IPLImagePlane* plane = image->plane( planeNr );
        IPLImagePlane* newplane = _result->plane( planeNr );
        ipl_basetype background = 0.0;

        if(planeNr == 0)
            background = color.red();
        else if(planeNr == 1)
            background = color.green();
        if(planeNr == 2)
            background = color.blue();

        for(int y=0; y<new_height; y++)
        {
            // progress
           notifyProgressEventHandler(100*progress++/maxProgress);

            for(int x=0; x<new_width; x++)
            {
                int from_x = x - offset_x;
                int from_y = y - offset_y;

                // check if inside source image
                if(from_x < 0 || from_y < 0 || from_x > plane->width() || from_y > plane->height())
                {
                    newplane->p(x, y) = background;
                }
                else
                {
                    newplane->p(x, y) = plane->p(from_x, from_y);
                }
            }
        }
    }

    return true;
}
Exemplo n.º 9
0
bool IPLBinarizeSavola::processInputData(IPLImage* image , int, bool)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width  = image->width();
    int height = image->height();

    _result = new IPLImage(image->type(), width, height);

    // get properties
    int window = getProcessPropertyInt("window");
    double aboveMean = getProcessPropertyDouble("aboveMean");


    IPLImage* mean = new IPLImage(image->type(), width, height);
    IPLImage* deviation = new IPLImage(image->type(), width, height);

    int progress = 0;
    int maxProgress = image->height() * image->getNumberOfPlanes();
    int nrOfPlanes = image->getNumberOfPlanes();

    #pragma omp parallel for
    for( int planeNr=0; planeNr < nrOfPlanes; planeNr++ )
    {
        IPLImagePlane* plane = image->plane( planeNr );
        IPLImagePlane* newplane = _result->plane( planeNr );

        int w2 = window/2;
        float area = (float)(w2*2)*(float)(w2*2);
        float minI = FLT_MAX;
        float maxDeviation = 0.0;

        for(int y=0; y<height; y++)
        {
            // progress
           notifyProgressEventHandler(100*progress++/maxProgress);

            for(int x=0; x<width; x++)
            {
                if( plane->p(x,y) < minI ) minI = plane->p(x,y);
                float localMean = 0.0;
                for( int kx=-w2; kx<=w2; kx++ )
                {
                    for( int ky=-w2; ky<=w2; ky++ )
                    {
                        localMean += (float)plane->cp(x+kx,y+ky);
                    }
                }
                localMean /= area;
                mean->plane(planeNr)->p(x,y) = localMean;

                float dev = 0.0;
                for( int kx=-w2; kx<=w2; kx++ )
                {
                    for( int ky=-w2; ky<=w2; ky++ )
                    {
                        float diff =  (float)plane->cp(x+kx, y+ky) - localMean;
                        dev += diff * diff;
                    }
                }
                dev = sqrt( dev / area );
                deviation->plane(planeNr)->p(x,y) = dev;
                if( dev > maxDeviation ) maxDeviation = dev;
            }

            for(int x=w2; x<width-w2; x++)
            {
                for(int y=w2; y<height-w2; y++)
                {
                    float alpha = 1.0 - deviation->plane(planeNr)->p(x,y) / maxDeviation;
                    int T = (int) ( mean->plane(planeNr)->p(x,y) - aboveMean * alpha *( mean->plane(planeNr)->p(x,y) - minI ) );
                    newplane->p(x,y) = ( plane->p(x,y) >= T ) ? 0.0 : 1.0;
                }
            }
        }
    }

    return true;
}
Exemplo n.º 10
0
bool IPLHarrisCorner::processInputData(IPLImage* image , int, bool useOpenCV)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width = image->width();
    int height = image->height();

    _result = new IPLImage( image->type(), width, height );

    // get properties
    int threshold           = getProcessPropertyInt("threshold");
    /*double sigma            = getProcessPropertyDouble("sigma");
    double lowThreshold     = getProcessPropertyDouble("lowThreshold");
    double highThreshold    = getProcessPropertyDouble("highThreshold");*/

    /*std::stringstream s;
    s << "Window: ";
    s << window;
    addInformation(s.str());*/

    notifyProgressEventHandler(-1);
    cv::Mat input;
    cv::Mat output;
    cvtColor(image->toCvMat(), input, CV_BGR2GRAY);

    /// Detector parameters
    int blockSize = 2;
    int apertureSize = 3;
    double k = 0.04;

    cv::Mat dst_norm;

    /// Detecting corners
    cv::cornerHarris(input, output, blockSize, apertureSize, k, cv::BORDER_DEFAULT );

    /// Normalizing
    cv::normalize( output, dst_norm, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat() );
    cv::convertScaleAbs( dst_norm, output );

    cvtColor(output, output, CV_GRAY2BGR);

    /// Drawing a circle around corners
    for( int j = 0; j < dst_norm.rows ; j++ )
    {
        for( int i = 0; i < dst_norm.cols; i++ )
        {
            if( (int) dst_norm.at<float>(j,i) > threshold )
            {
                cv::line(output, cv::Point(i-3, j), cv::Point(i+3, j), cv::Scalar(0,0,255));
                cv::line(output, cv::Point(i, j-3), cv::Point(i, j+3), cv::Scalar(0,0,255));
            }
        }
    }

    delete _result;
    _result = new IPLImage(output);

    return true;
}
Exemplo n.º 11
0
bool IPLFFT::processInputData(IPLImage* image , int, bool)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width = image->width();
    int height = image->height();
    int cWidth = IPLComplexImage::nextPowerOf2(width);
    int cHeight = IPLComplexImage::nextPowerOf2(height);
    int size = cHeight = cWidth = (cWidth>cHeight)? cWidth : cHeight;

    _result = new IPLComplexImage(cWidth, cHeight);

    // get properties
    int mode = getProcessPropertyInt("mode");

    int progress = 0;
    int maxProgress = image->height() * image->getNumberOfPlanes();

    // image center
    int dx = ( cWidth - width )/2;
    int dy = ( cHeight - height )/2;

    IPLImagePlane* plane = image->plane(0);
    for(int y=0; y<height; y++)
    {
        // progress
        notifyProgressEventHandler(100*progress++/maxProgress);
        for(int x=0; x<width; x++)
        {
            _result->c(x+dx, y+dy) = Complex(plane->p(x,y), 0.0);
        }
    }

    // windowing function
    switch(mode)
    {
        case 0: // rectangular
                break;

        case 1: // Hanning
                for( int y=0; y<size; y++ )
                    for( int x=0; x<size; x++ )
                        _result->c(x,y) *= Hanning(x, size) * Hanning(y, size);
                break;
        case 2: // Hamming
                for( int y=0; y<size; y++ )
                    for( int x=0; x<size; x++ )
                        _result->c(x,y) *= Hamming(x, size) * Hamming(y, size);
                break;
        case 3: // Blackman
                for( int y=0; y<size; y++ )
                    for( int x=0; x<size; x++ )
                        _result->c(x,y) *= Blackman(x, size) * Blackman(y, size);
                break;
        case 4: // Border only
                int border = size / 32;
                for( int y=0; y<border; y++ )
                    for( int x=0; x<size; x++ )
                    {
                        double factor = (0.54 - 0.46 * cos( 2.0 * PI * y / border / 2.0 ));
                        _result->c(x,y) *= factor;
                        _result->c(x,size-y-1) *= factor;
                    }
                for( int x=0; x<border; x++ )
                    for( int y=0; y<size; y++ )
                    {
                        double factor = (0.54 - 0.46 * cos( 2.0 * PI * x / border / 2.0 ));
                        _result->c(x,y) *= factor;
                        _result->c(size-x-1,y) *= factor;
                    }
                break;
    }

    _result->FFT();

    return true;
}
Exemplo n.º 12
0
bool IPLLocalThreshold::processInputData(IPLImage* image , int, bool)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width = image->width();
    int height = image->height();

    if(image->type() == IPLImage::IMAGE_GRAYSCALE)
        _result = new IPLImage(IPLImage::IMAGE_BW, width, height);
    else
        _result = new IPLImage(image->type(), width, height);

    // get properties
    int window = getProcessPropertyInt("window");
    float aboveMean = getProcessPropertyDouble("aboveMean");

    int progress = 0;
    int maxProgress = image->height() * image->getNumberOfPlanes();
    int nrOfPlanes = image->getNumberOfPlanes();

    #pragma omp parallel for
    for( int planeNr=0; planeNr < nrOfPlanes; planeNr++ )
    {
        IPLImagePlane* plane = image->plane( planeNr );
        IPLImagePlane* newplane = _result->plane( planeNr );

        int w2 = window/2;
        double area = (double)window*(double)window;

        for(int y=w2; y < height-w2; y++)
        {
            // progress
            notifyProgressEventHandler(100*progress++/maxProgress);
            for(int x=w2; x < width-w2; x++)
            {
                double localMean = 0.0;
                for( int kx=-w2; kx<=w2; kx++ )
                {
                    for( int ky=-w2; ky<=w2; ky++ )
                    {
                        localMean += (double)plane->p(x+kx,y+ky);
                    }
                }
                localMean /= area;
                double deviation = 0.0;
                for( int kx=-w2; kx<=w2; kx++ )
                {
                    for( int ky=-w2; ky<=w2; ky++ )
                    {
                        double diff =  (double)plane->p(x+kx, y+ky) - localMean;
                        deviation += diff * diff;
                    }
                }
                deviation = sqrt( deviation / area );
                double T = (localMean + aboveMean*deviation);

                newplane->p(x,y) = (plane->p(x,y) >= T) ? 1.0 : 0.0;
            }
        }
    }
    return true;
}
bool IPLConvolutionFilter::processInputData(IPLImage* image , int, bool useOpenCV)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width = image->width();
    int height = image->height();

    // get properties
    _kernel     = getProcessPropertyVectorInt("kernel");
    _divisor    = getProcessPropertyInt("divisor");
    _offset     = getProcessPropertyDouble("offset");
    _normalize  = getProcessPropertyBool("normalize");
    _borders    = getProcessPropertyInt("borders");

    if(_normalize)
    {
        int sum = 0;
        for(size_t i=0; i<_kernel.size(); i++)
        {
            sum += _kernel[i];
        }
        _divisor = (sum != 0 ? sum : 1);
    }

    if (_divisor == 0)
    {
        addError("Invalid divisor: 0");
        return false;
    }

    float divFactor = 1.0f/_divisor;

    int kernelWidth = (int)sqrt((float)_kernel.size());
    int kernelOffset = kernelWidth / 2;

    int progress = 0;
    int maxProgress = image->height() * image->getNumberOfPlanes();

    if (!useOpenCV)
    {
        _result = new IPLImage( image->type(), width, height );
        #pragma omp parallel for default(shared)
        for( int planeNr=0; planeNr < image->getNumberOfPlanes(); planeNr++ )
        {
            IPLImagePlane* plane = image->plane( planeNr );
            IPLImagePlane* newplane = _result->plane( planeNr );

            for(int y=0; y<plane->height(); y++)
            {
                // progress
                notifyProgressEventHandler(100*progress++/maxProgress);

                for(int x=0; x<plane->width(); x++)
                {
                    float sum = 0;
                    int i = 0;
                    for( int ky=-kernelOffset; ky<=kernelOffset; ky++ )
                    {
                        for( int kx=-kernelOffset; kx<=kernelOffset; kx++ )
                        {
                            int h = _kernel[i++];
                            if( h )
                            {
                                if(_borders == 0)
                                {
                                    // Crop borders
                                    sum += plane->cp(x+kx, y+ky) * h;
                                }
                                else if(_borders == 1)
                                {
                                    // Extend borders
                                    sum += plane->bp(x+kx, y+ky) * h;
                                } else {
                                    // Wrap borders
                                    sum += plane->wp(x+kx, y+ky) * h;
                                }
                            }
                        }
                    }
                    sum = sum * divFactor + _offset;
                    sum = (sum>1.0) ? 1.0 : (sum<0) ? 0.0 : sum; // clamp to 0.0 - 1.0
                    newplane->p(x,y) = sum;
                }
            }
        }
    }
    else
    {
        notifyProgressEventHandler(-1);

        cv::Mat src = image->toCvMat();
        cv::Mat dst;
        cv::Mat kernel(kernelWidth, kernelWidth, CV_32FC1 );

        int i = 0;
        for( int y=0; y < kernelWidth; y++ )
            for( int x=0; x < kernelWidth; x++ )
                kernel.at<float>(cv::Point(x,y)) = _kernel[i++];

        kernel *= divFactor;

        static const int BORDER_TYPES[3] = {
          cv::BORDER_CONSTANT,
          cv::BORDER_REPLICATE,
          cv::BORDER_WRAP
        };

        cv::filter2D(src, dst, -1, kernel, cv::Point(-1,-1), _offset, BORDER_TYPES[_borders]);
        _result = new IPLImage(dst);
    }

    return true;
}
Exemplo n.º 14
0
bool IPLMergePlanes::processInputData(IPLImage* image , int imageIndex, bool)
{
    // save the inputs
    if(imageIndex == 0)
    {
        delete _inputA;
        _inputA = new IPLImage(*image);
    }
    if(imageIndex == 1)
    {
        delete _inputB;
        _inputB = new IPLImage(*image);
    }
    if(imageIndex == 2)
    {
        delete _inputC;
        _inputC = new IPLImage(*image);
    }

    // only continue if we have 2 valid inputs
    if(!(_inputA && _inputB && _inputC))
    {
        return false;
    }

    // get properties
    int inputType = getProcessPropertyInt("input_type");

    int width   = std::max(std::max(_inputA->width(), _inputB->width()), _inputC->width());
    int height  = std::max(std::max(_inputA->height(), _inputB->height()), _inputC->height());

    delete _result;
    _result =  new IPLImage(IPLData::IMAGE_COLOR, width, height);

    int progress = 0;
    int maxProgress = image->height() * _result->getNumberOfPlanes();

    // copy data
    for(int y=0; y<height; y++)
    {
        // progress
        notifyProgressEventHandler(100*progress++/maxProgress);

        for(int x=0; x<width; x++)
        {
            // RGB
            float r = _inputA->plane(0)->cp(x, y);
            float g = _inputB->plane(0)->cp(x, y);
            float b = _inputC->plane(0)->cp(x, y);

            // HSV
            if(inputType == 1)
            {
                float rgb[3];
                IPLColor::hsvToRgb(r, g, b, rgb);
                r = rgb[0];
                g = rgb[1];
                b = rgb[2];
            }
            // HSL
            else if(inputType == 2)
            {
                float rgb[3];
                IPLColor::hslToRgb(r, g, b, rgb);
                r = rgb[0];
                g = rgb[1];
                b = rgb[2];
            }
            _result->plane(0)->p(x, y) = r;
            _result->plane(1)->p(x, y) = g;
            _result->plane(2)->p(x, y) = b;
        }
    }

    return true;
}
Exemplo n.º 15
0
bool IPLSynthesize::processInputData(IPLImage*, int, bool)
{
    if(isResultReady())
    {
        //return true;
    }

    // delete previous result
    delete _result;
    _result = NULL;

    // get properties
    _type       = getProcessPropertyInt("type");
    _width      = getProcessPropertyInt("width");
    _height     = getProcessPropertyInt("height");
    _amplitude  = getProcessPropertyDouble("amplitude");
    _offset     = getProcessPropertyDouble("offset");
    _wavelength = getProcessPropertyInt("wavelength");
    _direction  = getProcessPropertyInt("plane_direction");
    _decay      = getProcessPropertyInt("decay");

    IPLColor color = getProcessPropertyColor("flat_color");

    if( _type == 0 )
        _result = new IPLImage( IPL_IMAGE_COLOR, _width, _height );
    else
        _result = new IPLImage( IPL_IMAGE_GRAYSCALE, _width, _height );

    double dx = (double)_width / 2.0;
    double dy = (double)_height / 2.0;
    double direction = _direction / 180.0 * PI; // deg to rad

    IPLImagePlane* plane = _result->plane( 0 );

    int progress = 0;
    int maxProgress = _result->height();

    switch( _type )
    {
    case 0: // flat plane
        for( int y=0; y<_height; y++ )
        {
            notifyProgressEventHandler(100*progress++/maxProgress);
            for( int x=0; x<_width; x++ )
            {
                _result->plane(0)->p(x,y) = color.red();
                _result->plane(1)->p(x,y) = color.green();
                _result->plane(2)->p(x,y) = color.blue();
            }
        }
        break;
    case 1: // plane wave
        for( int y=0; y<_height; y++ )
        {
            notifyProgressEventHandler(100*progress++/maxProgress);
            for( int x=0; x<_width; x++ )
            {
                double dist = (x)*cos( direction ) + (_height-y)*sin( direction );
                double fade = (_decay!=0) ? exp( -dist/_decay ) : 1.0;
                double value = _amplitude * cos(dist/_wavelength * PI * 2.0) * fade + _offset;
                plane->p(x,y) = ( (value<0.0)? 0.0 : (value>1.0)? 1.0 : value );
            }
        }
        break;
    case 2:// center wave
        for( int y=0; y<_height; y++ )
        {
            notifyProgressEventHandler(100*progress++/maxProgress);
            for( int x=0; x<_width; x++ )
            {
                double dist = sqrt( (x-dx)*(x-dx) + (y-dy)*(y-dy) );
                double fade = (_decay!=0) ? exp( -dist/_decay ) : 1.0;
                double value = _amplitude * cos( dist/_wavelength * PI * 2.0 ) * fade + _offset;
                plane->p(x,y) = ( (value<0.0)? 0.0 : (value>1.0)? 1.0 : value );
            }
        }
        break;
    }

    return true;
}
Exemplo n.º 16
0
bool IPLMorphologyBinary::processInputData(IPLImage* image, int, bool useOpenCV)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width = image->width();
    int height = image->height();

    // get properties
    _kernel     = getProcessPropertyVectorInt("kernel");
    _iterations = getProcessPropertyInt("iterations");
    _operation  = getProcessPropertyInt("operation");

    if (std::accumulate(_kernel.begin(),_kernel.end(),0) == 0)
    {
        //Add an empty image - The image viewer currently may trigger
        //a segfault if we return NULL.
        _result = new IPLImage( IPLImage::IMAGE_BW, width, height);
        addError("Empty kernel.");
        return false;
    }

    // TODO: implement manhattan distance threshold instead of stupid iterations...
    // TODO: implement border interpolation properties

    enum Operation
    {
        DILATE = 0,
        ERODE,
        OPEN,
        CLOSE
    };

    if (!useOpenCV)
    {
        _result = new IPLImage( IPLImage::IMAGE_BW, width, height);

        //std::vector<bool> packs its elements bitwise into a vector of
        //bytes. The kernel therefore uses much less cpu cache this way.
        std::vector<bool> kernel;
        kernel.reserve(_kernel.size());
        for (auto &i: _kernel) kernel.push_back(i > 0);

        std::atomic<int> progress(0);
        int totalLines = image->height()*_iterations;
        auto updateProgress = [&]() {
            notifyProgressEventHandler(100*((float)++progress)/totalLines);
        };

        switch(_operation)
        {
        case DILATE:
            dilate(*image->plane(0),*_result->plane(0),_iterations,kernel,updateProgress);
            break;
        case ERODE:
            erode (*image->plane(0),*_result->plane(0),_iterations,kernel,updateProgress);
            break;
        case OPEN:
            totalLines *= 2;
            open  (*image->plane(0),*_result->plane(0),_iterations,kernel,updateProgress);
            break;
        case CLOSE:
            totalLines *= 2;
            close (*image->plane(0),*_result->plane(0),_iterations,kernel,updateProgress);
            break;
        }
    }
    else
    {
        notifyProgressEventHandler(-1);

        int kernelSize = (int)sqrt((float)_kernel.size());
        cv::Mat src = image->toCvMat();
        cv::Mat dst;

        cv::Mat kernel(kernelSize,kernelSize,CV_8UC1);
        int i = 0;
        for (auto pixel: _kernel)
            kernel.at<unsigned char>(i++) = pixel;

        static const int OPERATIONS[4] = {
            cv::MORPH_DILATE,
            cv::MORPH_ERODE,
            cv::MORPH_OPEN,
            cv::MORPH_CLOSE
        };

        cv::morphologyEx(src,dst,OPERATIONS[_operation],kernel,cv::Point(-1,-1),_iterations);
        _result = new IPLImage(dst);
    }

    return true;
}
Exemplo n.º 17
0
bool IPLMedian::processInputData(IPLImage* image , int, bool useOpenCV)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width = image->width();
    int height = image->height();

    // get properties
    int window = getProcessPropertyInt("window");

    int progress = 0;
    int maxProgress = image->height() * image->getNumberOfPlanes();
    int nrOfPlanes = image->getNumberOfPlanes();

    int w2 = window/2;
    int area = window*window;

    if (!useOpenCV)
    {
        _result = new IPLImage( image->type(), width, height );

        #pragma omp parallel for
        for( int planeNr=0; planeNr < nrOfPlanes; planeNr++ )
        {
            IPLImagePlane* plane = image->plane( planeNr );
            IPLImagePlane* newplane = _result->plane( planeNr );

            ipl_basetype* list = new ipl_basetype[area];

            for(int y=0; y<height; y++)
            {
                // progress
                notifyProgressEventHandler(100*progress++/maxProgress);

                for(int x=0; x<width; x++)
                {
                    int i =0;
                    for( int ky=-w2; ky<=w2; ky++ )
                    {
                        for( int kx=-w2; kx<=w2; kx++ )
                        {
                            list[i++] = plane->bp(x+kx, y+ky);
                        }
                    }

                    // insert sort list
                    for( int k=area; k>=0; k--)
                    {
                        int j = k+1;
                        ipl_basetype temp = list[k];
                        while( j < area && temp > list[j] )
                        {
                            list[j-1] = list[j];
                            j++;
                        }
                        list[j-1] = temp;
                    }
                    newplane->p(x,y) = list[area/2];
                }
            }
        }
    }
    else
    {
        notifyProgressEventHandler(-1);

        auto src = image->toCvMat();
        cv::Mat dst;

        cv::medianBlur(src,dst,window);
        _result = new IPLImage(dst);
    }
    return true;
}
bool IPLGradientOperator::cubicSpline(IPLImage* image)
{
   static float k1f[4][4] = {{-0.5,1.5,-1.5,0.5},{1.0,-2.5,2.0,-0.5},{-0.5,0,0.5,0},{0,1.0,0,0}};
   static cv::Mat k1(4,4,CV_32FC1,k1f);
   static float k2f[4][4] = {{-0.5,1.0,-0.5,0},{1.5,-2.5,0,1},{-1.5,2.0,0.5,0},{0.5,-0.5,0,0}};
   static cv::Mat k2(4,4,CV_32FC1,k2f);
 
   int width = image->width();
   int height = image->height();
   int progress = 0;
   int maxProgress = height*width;
 
   notifyProgressEventHandler(-1);

   cv::Mat input = image->toCvMat();
   cv::Mat coeffFull = cv::Mat::zeros(height,width,CV_32FC1);
   cv::Mat coeff = cv::Mat::zeros(height,width,CV_32FC1);

   for (int i=0;i<width;i++)
      for (int j=0;j<height;j++)
         coeffFull.at<cv::Vec<float,1>>(i,j)[0] = static_cast<float>(input.at<cv::Vec<unsigned char,4>>(i,j).val[0]) * FACTOR_TO_FLOAT ;
 
   float dx,dy,x3,x2,y3,y2,xf,yf;
   
   for (int x=1; x < width - 2; x++){
     for (int y = 1; y < height - 2; y++){
       // progress
       notifyProgressEventHandler(100*progress++/maxProgress);
 
       coeffFull(cv::Range(y-1,y+3),cv::Range(x-1,x+3)).copyTo(coeff);

//std::cout << coeff << std::endl;

       coeff = k1*coeff;
       coeff = coeff*k2;
       xf = static_cast<float>(x)/static_cast<float>(width);
       x2 = xf*xf;
       x3 = x2*xf;
       yf = static_cast<float>(y)/static_cast<float>(height);
       y2 = yf*yf;
       y3 = y2*yf;
       float dyMatf[4][4] = {{3.f*y2*x3,3.f*y2*x2,3.f*y2*xf,3.f*y2},
		{2.f*yf*x3,2.f*yf*x2,2.f*yf*xf,2.f*yf},
		{x3,x2,xf,1.f},
		{0.f,0.f,0.f,0.f}};
       float dxMatf[4][4] = {{3.f*x2*y3,2.f*xf*y3,y3,0.f},
		{3.f*x2*y2,2.f*xf*y2,y2,0.f},
		{3.f*x2*yf,2.f*xf*yf,yf,0.f},
		{3.f*x2,2.f*xf,1.f,0.f}};
       cv::Mat dxMat(4,4,CV_32FC1,dxMatf);
       cv::Mat dyMat(4,4,CV_32FC1,dyMatf);
       dx = coeff.dot(dxMat);
       dy = coeff.dot(dyMat);

       double phase = (dx!=0.0 || dy!=0.0 )? atan2( -dy, dx ) : 0.0;

        while( phase > 2.0 * PI ) phase -= 2.0 * PI;
        while( phase < 0.0 ) phase += 2.0 * PI;

        // phase 0.0-1.0
        phase /= 2 * PI;

        _result->phase(x,y) = phase;
        _result->magnitude(x,y) = sqrt(dx*dx + dy*dy);
   }
  }

  return true;
}
Exemplo n.º 19
0
bool IPLBinarizeUnimodal::processInputData(IPLImage* image , int, bool)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width = image->width();
    int height = image->height();
    if( image->type() == IPL_IMAGE_GRAYSCALE )
        _result = new IPLImage( IPL_IMAGE_BW, width, height );
    else
        _result = new IPLImage( image->type(), width, height );

    int progress = 0;
    int maxProgress = image->height() * image->getNumberOfPlanes();
    int nrOfPlanes = image->getNumberOfPlanes();

    #pragma omp parallel for
    for( int planeNr=0; planeNr < nrOfPlanes; planeNr++ )
    {
        IPLImagePlane* plane = image->plane( planeNr );
        IPLImagePlane* newplane = _result->plane( planeNr );

        int p[256] = { 0 };

        for( int y = 0; y < height; ++y )
        {
            for( int x = 0; x < width; ++x )
            {
                int index = plane->p(x,y) * 255;
                p[index]++;
            }
        }

        // determine maxEntry
        int maxBin = 0;
        int maxFrequency = 0;
        for( int k=1; k<255; ++k )
        {
            if( p[k] > maxFrequency )
            {
                maxFrequency = p[k];
                maxBin = k;
            }
        }

        // determine zeroEntry
        int zeroBin = 0;
        int x0, x1;
        if( maxBin >= 128 )
        {
            zeroBin = 0;
            while( p[zeroBin]==0 ) ++zeroBin;
            x0 = zeroBin;
            x1 = maxBin;
        }
        else
        {
            zeroBin = 255;
            while( p[zeroBin]==0 ) --zeroBin;
            x0 = maxBin;
            x1 = zeroBin;
        }

        int y0 = p[x0];
        int y1 = p[x1];
        double a = y0 - y1;
        double b = x1 - x0;
        double c = x0*y1 - x1*y0;
        double d = sqrt( a*a + b*b );

        int T = 0;
        if( d != 0.0 )
        {
            double maxDist = 0.0;
            for( int k=x0; k<=x1; ++k )
            {
                double distance = std::abs( ( a*k + b*p[k] + c ) / d );
                if( distance > maxDist )
                {
                    maxDist = distance;
                    T = k;
                }
            }
        }

        ipl_basetype threshold = T * FACTOR_TO_FLOAT;

        std::stringstream s;
        s << "Automatic Threshold: ";
        s << threshold;
        addInformation(s.str());

        for(int y = 0; y < height; y++)
        {            // progress
            notifyProgressEventHandler(100*progress++/maxProgress);
            for(int x = 0; x < width; x++)
            {
                newplane->p(x,y)= (plane->p(x,y) > threshold)? 1.0 : 0.0;
            }
        }
    }
    return true;
}
bool IPLMorphologicalEdge::processInputData(IPLImage* image , int, bool)
{
    // delete previous result
    delete _result;
    _result = NULL;

    int width = image->width();
    int height = image->height();
    _result = new IPLImage( image->type(), width, height );

    // get properties
    int window = getProcessPropertyInt("window");

    int progress = 0;
    int maxProgress = image->height() * image->getNumberOfPlanes() * 2;
    int nrOfPlanes = image->getNumberOfPlanes();

    int w2 = window/2;
    int area = window*window;

    #pragma omp parallel for
    for( int planeNr=0; planeNr < nrOfPlanes; planeNr++ )
    {
        IPLImagePlane* plane = image->plane( planeNr );
        IPLImagePlane* newplane = _result->plane( planeNr );
        IPLImagePlane* average = new IPLImagePlane(width, height);

        for(int x=w2; x<width-w2; x++)
        {
            // progress
            notifyProgressEventHandler(100*progress++/maxProgress);
            for(int y=w2; y<height-w2; y++)
            {
                ipl_basetype sum = 0;
                for( int kx=-w2; kx<=w2; kx++ )
                {
                    for( int ky=-w2; ky<=w2; ky++ )
                    {
                        if( kx || ky ) sum += plane->p(x+kx, y+ky);
                    }
                }
                average->p(x,y) = sum;
            }
        }
        for(int x=w2; x<width-w2; x++)
        {
            // progress
            notifyProgressEventHandler(100*progress++/maxProgress);

            for(int y=w2; y<height-w2; y++)
            {
                float minc = (area-1);
                float maxc = 0;
                for( int kx=-w2; kx<=w2; kx++ )
                {
                    for( int ky=-w2; ky<=w2; ky++ )
                    {
                        ipl_basetype img = average->bp(x+kx, y+ky);
                        if( img > maxc) maxc = img;
                        if( img < minc) minc = img;
                    }
                }
                ipl_basetype img = average->p(x,y);
                ipl_basetype d1 = img - minc;
                ipl_basetype d2 = maxc - img;
                ipl_basetype min = (d1 < d2)? d1 : d2;
                min = (min<1.0)? min : 1.0;
                min = (min>0.0)? min : 0.0;
                newplane->p(x,y) = min;
            }
        }
        delete average;
    }
    return true;
}
Exemplo n.º 21
0
bool IPLCanny::processInputData(IPLImage* image , int, bool useOpenCV)
{
    // delete previous result
    delete _result;
    _result = NULL;
    delete _binaryImage;
    _binaryImage = NULL;

    int width = image->width();
    int height = image->height();

    _result = new IPLImage( image->type(), width, height );
    _binaryImage = new IPLImage( IPLData::IMAGE_BW, width, height );

    // get properties
    int window              = getProcessPropertyInt("window");
    double sigma            = getProcessPropertyDouble("sigma");
    double lowThreshold     = getProcessPropertyDouble("lowThreshold");
    double highThreshold    = getProcessPropertyDouble("highThreshold");

    std::stringstream s;
    s << "Window: ";
    s << window;
    addInformation(s.str());

    //! @todo currently only the opencv implementation works
    if(useOpenCV || true)
    {
        notifyProgressEventHandler(-1);
        cv::Mat input;
        cv::Mat output;
        cvtColor(image->toCvMat(), input, CV_BGR2GRAY);
        cv::Canny(input, output, lowThreshold*255, highThreshold*255, window);

        delete _result;
        _result = new IPLImage(output);

        return true;
    }

    return false;

    // Create a Gaussian 1D filter
    int N = ceil( sigma * sqrt( 2.0*log( 1.0/0.015 ) ) + 1.0 );
    double ssq = sigma*sigma;
    double* gau = new double [window];
    double* dgau = new double [window];
    for( int k = -N; k <= N; ++k )
    {
        gau[k+N] = gauss ( (double)k, ssq );
        dgau[k+N] = dGauss ( (double)k, 0, ssq );
    }

    // Create a directional derivative of 2D Gaussian (along X-axis)
    // Since the result is symmetric along X, we can get the derivative along
    // Y-axis simply by transposing the result for X direction.
//		DoubleImage* dgau = new DoubleImage( window, window );
//		for( int y = -N; y <= N; ++y )
//			for( int x = -N; x <= N; ++x )
//				dgau->f(x+N, y+N) = dGauss( x, y, ssq );

    int progress = 0;
    int maxProgress = width * image->getNumberOfPlanes();
    int nrOfPlanes = image->getNumberOfPlanes();

    //#pragma omp parallel for
    for( int planeNr=0; planeNr < nrOfPlanes; planeNr++ )
    {
        IPLImagePlane* plane = image->plane( planeNr );
        IPLImagePlane* newplane = _result->plane( planeNr );

// ******** Gaussian filtering of input image
        IPLImagePlane* gI = new IPLImagePlane( width, height );

        // horizontal run (normalizing original image)
        IPLImagePlane* tmpI = new IPLImagePlane( width, height );
        for(int x=0; x<width; x++)
        {            // progress
            notifyProgressEventHandler(100*progress++/maxProgress);

            for(int y=0; y<height; y++)
            {
                double sum = 0;
                int i = 0;
                for( int kx=-N; kx<=N; kx++ )
                {
                        double img = (double) plane->bp(x+kx, y);
                        sum += (img * gau[i++]);
                }
                tmpI->p(x,y) = (double) (sum);
            }
        }
        // vertiacl run
        for(int x=0; x<width; x++)
        {
            for(int y=0; y<height; y++)
            {
                double sum = 0;
                int i = 0;
                for( int ky=-N; ky<=N; ky++ )
                {
                        double img = tmpI->bp(x, y+ky);
                        sum += (img * gau[i++]);
                }
                gI->p(x,y) = sum;
            }
        }
        //delete tmpI;

// ******** Apply directional derivatives ...

        // ... in x-direction
        IPLImagePlane* dx = new IPLImagePlane( width, height );
        for(int x=0; x<width; x++)
        {
            for(int y=0; y<height; y++)
            {
                dx->p(x,y) = 0.0;
                for( int k=1; k<N; k++ )
                {
                    dx->p(x,y) += ( gI->bp(x-k,y) - gI->bp(x+k,y) ) * dgau[k];
                }
            }
        }
//			double maxVal = 0.0;
//			for(int x=0; x<width; x++)
//				for(int y=0; y<height; y++)
//					if( dx->f(x,y) > maxVal ) maxVal = dx->f(x,y);

        // ... in y-direction
        IPLImagePlane* dy = new IPLImagePlane( width, height );
        for(int x=0; x<width; x++)
        {
            for(int y=0; y<height; y++)
            {
                dy->p(x,y) = 0.0;
                for( int k=1; k<N; k++ )
                {
                    dy->p(x,y) += ( gI->bp(x,y-k) - gI->bp(x,y+k) ) * dgau[k];
                }
            }
        }

// ******** Compute magnitude and binarization thresholds
        IPLImagePlane* mag = new IPLImagePlane( width, height );
        double magMax = 0.0;
        double magMin = 999999999.0;
        for(int x=0; x<width; x++)
        {
            for(int y=0; y<height; y++)
            {
                double val = sqrt( dx->p(x,y)*dx->p(x,y) + dy->p(x,y)*dy->p(x,y) );
                mag->p(x,y) = val;
                if( val > magMax ) magMax = val;
                if( val < magMin ) magMin = val;
            }
        }

//// ******** Non-maxima suppression - edge pixels should be a local maximum
        _orientedImage = new IPLOrientedImage( width, height );
        for(int x=0; x<width; x++)
        {
            for(int y=0; y<height; y++)
            {
                double ix = dx->p(x,y);
                double iy = dy->p(x,y);
                double g = mag->p(x,y);

                // determine 4-neighbor direction of gradient
                int dir4 = 0;
                if( (iy<=0.0 && ix>-iy) || (iy>=0.0 && ix<-iy) )
                    dir4 = 1;
                else if( (ix>0.0 && -iy>=ix) || (ix<0.0 && -iy<=ix) )
                    dir4 = 2;
                else if( (ix<=0.0 && ix>iy) || (ix>=0.0 && ix<iy) )
                    dir4 = 3;
                else if( (iy<0.0 && ix<=iy) || (iy>0.0 && ix>=iy) )
                    dir4 = 4;
                else
                    continue;

                double gradmag1, gradmag2, d;
                switch(dir4)
                {
                    case 1: d = std::fabs(iy/ix);
                            gradmag1 = mag->bp(x+1,y)*(1-d) + mag->bp(x+1,y-1)*d;
                            gradmag2 = mag->bp(x-1,y)*(1-d) + mag->bp(x-1,y+1)*d;
                            break;
                    case 2: d = std::fabs(ix/iy);
                            gradmag1 = mag->bp(x,y-1)*(1-d) + mag->bp(x+1,y-1)*d;
                            gradmag2 = mag->bp(x,y+1)*(1-d) + mag->bp(x-1,y+1)*d;
                            break;
                    case 3: d = std::fabs(ix/iy);
                            gradmag1 = mag->bp(x,y-1)*(1-d) + mag->bp(x-1,y-1)*d;
                            gradmag2 = mag->bp(x,y+1)*(1-d) + mag->bp(x+1,y+1)*d;
                            break;
                    case 4: d = std::fabs(iy/ix);
                            gradmag1 = mag->bp(x-1,y)*(1-d) + mag->bp(x-1,y-1)*d;
                            gradmag2 = mag->bp(x+1,y)*(1-d) + mag->bp(x+1,y+1)*d;
                            break;
                }

                if( g > gradmag1 && g > gradmag2 )
                {
                    _orientedImage->magnitude(x,y) = g;
                    _orientedImage->phase(x,y) = atan2(iy,ix);
                }
            }

        }


        for(int x=0; x<width; x++)
        {
            for(int y=0; y<height; y++)
            {
                _orientedImage->magnitude(x,y) /= magMax;
                double val = _orientedImage->magnitude(x,y)*255.0;
//					double val = mag->f(x,y)/magMax*255.0;
                if (val > 255.0 ) val = 255.0;
                if (val < 0.0 ) val = 0.0;
                newplane->p(x,y) = (unsigned char ) val;
            }
        }

// ******** Binarize with hysteresis threshold
        double hist[ 256 ];
        for( int i=0; i<256; ++i )
            hist[i] = 0;
        int pixCount = 0;
        for(int x=0; x<width; x++)
        {
            for(int y=0; y<height; y++)
            {
                if( _orientedImage->magnitude(x,y) > 0.0 )
                {
                    int index = floor( _orientedImage->magnitude(x,y)*256.0+0.5 );
                    ++hist[ index ];
                    ++pixCount;
                }
            }
        }
        double PercentOfPixelsNotEdges = 0.7*pixCount;
        double highThresh = 0.0;
        double cumsum = 0.0;
        for( int i=0; i<256; ++i )
        {
            cumsum += hist[i];
            if( cumsum > PercentOfPixelsNotEdges )
            {
                highThresh = (double)i / 256.0;
                break;
            }
        }
        double lowThresh = 0.4 * highThresh;
        IPLImagePlane* binPlane = _binaryImage->plane( 0 );
        for(int x=0; x<width; x++)
        {
            for(int y=0; y<height; y++)
            {
                if(_orientedImage->magnitude(x,y) >= highThresh)
                    trace(x, y, lowThresh, _orientedImage, binPlane);
            }
        }
        //delete dx;
        //delete dy;
        //delete gI;

        thinning(_orientedImage, binPlane, newplane );
    }

    //delete [] gau;
    //delete [] dgau;

    return true;
}