void
DistanceTransformInv(vector<double>& D, 
					  const vector<unsigned char>& L, 
					  int mode,
					  int ndim, 
					  const int* dims) {

  vector<unsigned char> invL(L.size());
  int i;
  for(i=0; i<L.size(); ++i) {
    if(L[i]==0)
      invL[i]=1;
    else
      invL[i]=0;
  }

  DistanceTransform(D,invL,mode,ndim,dims);
}
示例#2
0
void GenerateDistanceFieldMap(const unsigned char* const imagePixels, const Size& imageSize,
                              unsigned char* const distanceMap, const Size& distanceMapSize,
                              const unsigned int fieldBorder,
                              const Vector2& maxSize,
                              bool highQuality)
{
  // constants to reduce redundant calculations
  const int originalWidth( static_cast<int>(imageSize.width) );
  const int originalHeight( static_cast<int>(imageSize.height) );
  const int paddedWidth( originalWidth + (fieldBorder * 2 ) );
  const int paddedHeight( originalHeight + (fieldBorder * 2 ) );
  const int scaledWidth( static_cast<int>(distanceMapSize.width) );
  const int scaledHeight( static_cast<int>(distanceMapSize.height) );
  const int maxWidth( static_cast<int>(maxSize.width) + (fieldBorder * 2 ));
  const int maxHeight( static_cast<int>(maxSize.height) + (fieldBorder * 2 ) );

  const int bufferLength( std::max( maxWidth, std::max(paddedWidth, scaledWidth) ) *
                          std::max( maxHeight, std::max(paddedHeight, scaledHeight) ) );

  std::vector<float> outsidePixels( bufferLength, 0.0f );
  std::vector<float> insidePixels( bufferLength, 0.0f );

  float* outside( outsidePixels.data() );
  float* inside( insidePixels.data() );

  for( int y = 0; y < paddedHeight; ++y )
  {
    for ( int x = 0; x < paddedWidth; ++x)
    {
      if( y < (int)fieldBorder || y >= (paddedHeight - (int)fieldBorder) ||
          x < (int)fieldBorder || x >= (paddedWidth - (int)fieldBorder) )
      {
        outside[ y * paddedWidth + x ] = MAX_DISTANCE;
        inside[ y * paddedWidth + x ] = 0.0f;
      }
      else
      {
        unsigned int pixel( imagePixels[ (y - fieldBorder) * originalWidth + (x - fieldBorder) ] );
        outside[ y * paddedWidth + x ] = (pixel == 0) ? MAX_DISTANCE : SQUARE((255 - pixel) / 255.0f);
        inside[ y * paddedWidth + x ] = (pixel == 255) ? MAX_DISTANCE : SQUARE(pixel / 255.0f);
      }
    }
  }

  // perform distance transform if high quality requested, else use original figure
  if( highQuality )
  {
    // create temporary buffers for DistanceTransform()
    const int tempBufferLength( std::max(paddedWidth, paddedHeight) );
    std::vector<float> tempSourceBuffer( tempBufferLength, 0.0f );
    std::vector<float> tempDestBuffer( tempBufferLength, 0.0f );

    // Perform distance transform for pixels 'outside' the figure
    DistanceTransform( outside, paddedWidth, paddedHeight, tempSourceBuffer.data(), tempDestBuffer.data() );

    // Perform distance transform for pixels 'inside' the figure
    DistanceTransform( inside, paddedWidth, paddedHeight, tempSourceBuffer.data(), tempDestBuffer.data() );
  }

  // distmap = outside - inside; % Bipolar distance field
  for( int y = 0; y < paddedHeight; ++y)
  {
    for( int x = 0; x < paddedWidth; ++x )
    {
      const int offset( y * paddedWidth + x );
      float pixel( sqrtf(outside[offset]) - sqrtf(inside[offset]) );
      pixel = 128.0f + pixel * 16.0f;
      pixel = Clamp( pixel, 0.0f, 255.0f );
      outside[offset] = (255.0f - pixel) / 255.0f;
    }
  }

  // scale the figure to the distance field tile size
  ScaleField( paddedWidth, paddedHeight, outside, scaledWidth, scaledHeight, inside );

  // convert from floats to integers
  for( int y = 0; y < scaledHeight; ++y )
  {
    for( int x = 0; x < scaledWidth; ++x )
    {
      float pixel( inside[ y * scaledWidth + x ] );
      distanceMap[y * scaledWidth + x ] = static_cast< unsigned char >(pixel * 255.0f);
    }
  }
}