Example #1
0
/*!
  Compute the image addition: \f$ Ires = I1 - I2 \f$.

  \param I1 : The first image.
  \param I2 : The second image.
  \param Ires : \f$ Ires = I1 - I2 \f$
  \param saturate : If true, saturate the result to [0 ; 255] using vpMath::saturate, otherwise overflow may occur.
*/
void
vpImageTools::imageSubtract(const vpImage<unsigned char> &I1,
                            const vpImage<unsigned char> &I2,
                            vpImage<unsigned char> &Ires,
                            const bool saturate)
{
  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
    throw (vpException(vpException::dimensionError, "The two images do not have the same size"));
  }

  if ((I1.getHeight() != Ires.getHeight()) || (I1.getWidth() != Ires.getWidth())) {
    Ires.resize(I1.getHeight(), I1.getWidth());
  }

  unsigned char *ptr_I1   = I1.bitmap;
  unsigned char *ptr_I2   = I2.bitmap;
  unsigned char *ptr_Ires = Ires.bitmap;
  unsigned int cpt = 0;

#if VISP_HAVE_SSE2
  if (Ires.getSize() >= 16) {
    for (; cpt <= Ires.getSize() - 16 ; cpt += 16, ptr_I1 += 16, ptr_I2 += 16, ptr_Ires += 16) {
      const __m128i v1   = _mm_loadu_si128( (const __m128i*) ptr_I1);
      const __m128i v2   = _mm_loadu_si128( (const __m128i*) ptr_I2);
      const __m128i vres = saturate ? _mm_subs_epu8(v1, v2) : _mm_sub_epi8(v1, v2);

      _mm_storeu_si128( (__m128i*) ptr_Ires, vres );
    }
  }
#endif

  for (; cpt < Ires.getSize(); cpt++, ++ptr_I1, ++ptr_I2, ++ptr_Ires) {
    *ptr_Ires = saturate ? vpMath::saturate<unsigned char>( (short int) *ptr_I1 - (short int) *ptr_I2 ) : *ptr_I1 - *ptr_I2;
  }
}
Example #2
0
/*!
  Grabs a grayscale image from the selected camera. If the camera color
  coding differs from vp1394CMUGrabber::MONO8, the acquired image is
  converted in a gray level image to match the requested format.

  \param I : Acquired gray level image.
  */
void 
vp1394CMUGrabber::acquire(vpImage<unsigned char> &I)
{
  // get image data
  unsigned long length;
  unsigned char *rawdata = NULL ;
  int dropped;
  unsigned int size;

  open(I);

  camera->AcquireImageEx(TRUE,&dropped);
  rawdata = camera->GetRawData(&length);

  size = I.getSize();
  switch(_color) {
    case vp1394CMUGrabber::MONO8:
      memcpy(I.bitmap, (unsigned char *) rawdata, size);
      break;
    case vp1394CMUGrabber::MONO16:
      vpImageConvert::MONO16ToGrey(rawdata, I.bitmap, size);
      break;

    case vp1394CMUGrabber::YUV411:
      vpImageConvert::YUV411ToGrey(rawdata, I.bitmap, size);
      break;

    case vp1394CMUGrabber::YUV422:
      vpImageConvert::YUV422ToGrey(rawdata, I.bitmap, size);
      break;

    case vp1394CMUGrabber::YUV444:
      vpImageConvert::YUV444ToGrey(rawdata, I.bitmap, size);
      break;

    case vp1394CMUGrabber::RGB8:
      vpImageConvert::RGBToGrey(rawdata, I.bitmap, size);
      break;

    default:
      close();
      vpERROR_TRACE("Format conversion not implemented. Acquisition failed.");
      throw (vpFrameGrabberException(vpFrameGrabberException::otherError,
                                     "Format conversion not implemented. "
                                     "Acquisition failed.") );
      break;
  };

  //unsigned short depth = 0;
  //camera->GetVideoDataDepth(&depth);
  //std::cout << "depth: " << depth << " computed: " << (float)(length/(I.getHeight() * I.getWidth())) <<  std::endl;


  //memcpy(I.bitmap,rawdata,length);

}
Example #3
0
/*!
  \ingroup group_imgproc_contours

  Draw the input contours on the color image.

  \param I : Color image where we want to draw the input contours.
  \param contours : Detected contours.
  \param color : Drawing color.
*/
void vp::drawContours(vpImage<vpRGBa> &I, const std::vector<std::vector<vpImagePoint> > &contours, const vpColor &color) {
  if (I.getSize() == 0) {
    return;
  }

  for (std::vector<std::vector<vpImagePoint> >::const_iterator it1 = contours.begin(); it1 != contours.end(); ++it1) {
    for (std::vector<vpImagePoint>::const_iterator it2 = it1->begin(); it2 != it1->end(); ++it2) {
      unsigned int i = (unsigned int) it2->get_i();
      unsigned int j = (unsigned int) it2->get_j();
      I[i][j] = vpRGBa(color.R, color.G, color.B);
    }
  }
}
Example #4
0
/*!
  \ingroup group_imgproc_contours

  Draw the input contours on the binary image.

  \param I : Grayscale image where we want to draw the input contours.
  \param contours : Detected contours.
  \param grayValue : Drawing grayscale color.
*/
void vp::drawContours(vpImage<unsigned char> &I, const std::vector<std::vector<vpImagePoint> > &contours, unsigned char grayValue) {
  if (I.getSize() == 0) {
    return;
  }

  for (std::vector<std::vector<vpImagePoint> >::const_iterator it1 = contours.begin(); it1 != contours.end(); ++it1) {
    for (std::vector<vpImagePoint>::const_iterator it2 = it1->begin(); it2 != it1->end(); ++it2) {
      unsigned int i = (unsigned int) it2->get_i();
      unsigned int j = (unsigned int) it2->get_j();
      I[i][j] = grayValue;
    }
  }
}
Example #5
0
/*!
  \ingroup group_imgproc_sharpening

  Sharpen a grayscale image using the unsharp mask technique.

  \param I : The grayscale image to sharpen.
  \param size : Size (must be odd) of the Gaussian blur kernel.
  \param weight : Weight (between [0 - 1[) for the sharpening process.
 */
void vp::unsharpMask(vpImage<unsigned char> &I, const unsigned int size, const double weight) {
  if(weight < 1.0 && weight >= 0.0) {
    //Gaussian blurred image
    vpImage<double> I_blurred;
    vpImageFilter::gaussianBlur(I, I_blurred, size);

    //Unsharp mask
    for(unsigned int cpt = 0; cpt < I.getSize(); cpt++) {
      double val = (I.bitmap[cpt] - weight*I_blurred.bitmap[cpt]) / (1 - weight);
      I.bitmap[cpt] = vpMath::saturate<unsigned char>(val); //val > 255 ? 255 : (val < 0 ? 0 : val);
    }
  }
}
Example #6
0
/*!
  \ingroup group_imgproc_sharpening

  Sharpen a color image using the unsharp mask technique.

  \param I : The color image to sharpen.
  \param size : Size (must be odd) of the Gaussian blur kernel.
  \param weight : Weight (between [0 - 1[) for the sharpening process.
 */
void vp::unsharpMask(vpImage<vpRGBa> &I, const unsigned int size, const double weight) {
  if(weight < 1.0 && weight >= 0.0) {
    //Gaussian blurred image
    vpImage<double> I_blurred_R,  I_blurred_G,  I_blurred_B;
    vpImage<unsigned char> I_R, I_G, I_B;

    vpImageConvert::split(I, &I_R, &I_G, &I_B);
    vpImageFilter::gaussianBlur(I_R, I_blurred_R, size);
    vpImageFilter::gaussianBlur(I_G, I_blurred_G, size);
    vpImageFilter::gaussianBlur(I_B, I_blurred_B, size);

    //Unsharp mask
    for(unsigned int cpt = 0; cpt < I.getSize(); cpt++) {
      double val_R = (I.bitmap[cpt].R - weight*I_blurred_R.bitmap[cpt]) / (1 - weight);
      double val_G = (I.bitmap[cpt].G - weight*I_blurred_G.bitmap[cpt]) / (1 - weight);
      double val_B = (I.bitmap[cpt].B - weight*I_blurred_B.bitmap[cpt]) / (1 - weight);

      I.bitmap[cpt].R = vpMath::saturate<unsigned char>(val_R);
      I.bitmap[cpt].G = vpMath::saturate<unsigned char>(val_G);
      I.bitmap[cpt].B = vpMath::saturate<unsigned char>(val_B);
    }
  }
}
Example #7
0
/*!
  \ingroup group_imgproc_contours

  Extract contours from a binary image.

  \param I_original : Input binary image (0 means background, 1 means foreground, other values are not allowed).
  \param contours : Detected contours.
  \param contourPts : List of contours, each contour contains a list of contour points.
  \param retrievalMode : Contour retrieval mode.
*/
void vp::findContours(const vpImage<unsigned char> &I_original, vpContour &contours, std::vector<std::vector<vpImagePoint> > &contourPts,
                      const vpContourRetrievalType& retrievalMode) {
  if (I_original.getSize() == 0) {
    return;
  }

  //Clear output results
  contourPts.clear();

  vpImage<int> I(I_original.getHeight(), I_original.getWidth());
  for (unsigned int cpt = 0; cpt < I_original.getSize(); cpt++) {
    I.bitmap[cpt] = I_original.bitmap[cpt];
  }

  int nbd = 1; //Newest border
  int lnbd = 1; //Last newest border

  //Background contour
  //By default the root contour is a hole contour
  vpContour *root = new vpContour(vp::CONTOUR_HOLE);

  std::map<int, vpContour*> borderMap;
  borderMap[lnbd] = root;

  for (unsigned int i = 0; i < I.getHeight(); i++) {
    lnbd = 1; //Reset LNBD at the beginning of each scan row

    for (unsigned int j = 0; j < I.getWidth(); j++) {
      int fji = I[i][j];

      bool isOuter = isOuterBorderStart(I, i, j);
      bool isHole = isHoleBorderStart(I, i, j);

      if (isOuter || isHole) { //else (1) (c)
        vpContour *border = new vpContour;
        vpContour *borderPrime = NULL;
        vpImagePoint from(i, j);

        if (isOuter) {
          //(1) (a)
          nbd++;
          from.set_j(from.get_j() - 1);
          border->m_contourType = vp::CONTOUR_OUTER;
          borderPrime = borderMap[lnbd];

          //Table 1
          switch (borderPrime->m_contourType) {
            case vp::CONTOUR_OUTER:
              border->setParent(borderPrime->m_parent);
              break;

            case vp::CONTOUR_HOLE:
              border->setParent(borderPrime);
              break;

            default:
              break;
          }
        } else {
          //(1) (b)
          nbd++;

          if (fji > 1) {
            lnbd = fji;
          }

          borderPrime = borderMap[lnbd];
          from.set_j(from.get_j() + 1);
          border->m_contourType = vp::CONTOUR_HOLE;

          //Table 1
          switch (borderPrime->m_contourType) {
            case vp::CONTOUR_OUTER:
              border->setParent(borderPrime);
              break;

            case vp::CONTOUR_HOLE:
              border->setParent(borderPrime->m_parent);
              break;

            default:
              break;
          }
        }

        vpImagePoint ij(i, j);
        followBorder(I, ij, from, border, nbd);

        //(3) (1) ; single pixel contour
        if (border->m_points.empty()) {
          border->m_points.push_back(ij);
          I[i][j] = -nbd;
        }

        //Compute contour polygon
        border->m_contourPolygon.buildFrom(border->m_points);

        if (retrievalMode == CONTOUR_RETR_LIST || retrievalMode == CONTOUR_RETR_TREE) {
          //Add contour points
          contourPts.push_back(border->m_points);
        }

        borderMap[nbd] = border;
      }

      //(4)
      if (fji != 0 && fji != 1) {
       lnbd = std::abs(fji);
      }
    }
  }

  if (retrievalMode == CONTOUR_RETR_EXTERNAL || retrievalMode == CONTOUR_RETR_LIST) {
    //Delete contours content
    contours.m_parent = NULL;

    for (std::vector<vpContour *>::iterator it = contours.m_children.begin(); it != contours.m_children.end(); ++it) {
      (*it)->m_parent = NULL;
      if (*it != NULL) {
        delete *it;
        *it = NULL;
      }
    }

    contours.m_children.clear();
  }

  if (retrievalMode == CONTOUR_RETR_EXTERNAL) {
    //Add only external contours
    for (std::vector<vpContour*>::const_iterator it = root->m_children.begin(); it != root->m_children.end(); ++it) {
      contours.m_children.push_back(new vpContour(**it));
      contourPts.push_back((*it)->m_points);
    }
  } else if (retrievalMode == CONTOUR_RETR_LIST) {
    getContoursList(*root, 0, contours);

    //Set parent to root
    for (std::vector<vpContour*>::iterator it = contours.m_children.begin(); it != contours.m_children.end(); ++it) {
      (*it)->m_parent = &contours;
    }
  } else {
    //CONTOUR_RETR_TREE
    contours = *root;
  }

  delete root;
  root = NULL;
}
Example #8
0
void MSRCR(vpImage<vpRGBa> &I, const int _scale, const int scaleDiv,
    const int level, const double dynamic, const int _kernelSize) {
  //Calculate the scales of filtering according to the number of filter and their distribution.
  std::vector<double> retinexScales = retinexScalesDistribution(scaleDiv, level, _scale);

  //Filtering according to the various scales.
  //Summarize the results of the various filters according to a specific weight(here equivalent for all).
  double weight = 1.0 / (double) scaleDiv;

  std::vector<vpImage<double> > doubleRGB(3);
  std::vector<vpImage<double> > doubleResRGB(3);
  unsigned int size = I.getSize();

  int kernelSize = _kernelSize;
  if(kernelSize == -1) {
    //Compute the kernel size from the input image size
    kernelSize = (int) (std::min(I.getWidth(), I.getHeight()) / 2.0);
    kernelSize = (kernelSize - kernelSize%2) + 1;
  }

  for(int channel = 0; channel < 3; channel++) {
    doubleRGB[(size_t) channel] = vpImage<double>(I.getHeight(), I.getWidth());
    doubleResRGB[(size_t) channel] = vpImage<double>(I.getHeight(), I.getWidth());

    for(unsigned int cpt = 0; cpt < size; cpt++) {
      //Shift the pixel values by 1 to avoid problem with log(0)
      switch(channel) {
      case 0:
        doubleRGB[(size_t) channel].bitmap[cpt] = I.bitmap[cpt].R + 1.0;
        break;

      case 1:
        doubleRGB[(size_t) channel].bitmap[cpt] = I.bitmap[cpt].G + 1.0;
        break;

      case 2:
        doubleRGB[(size_t) channel].bitmap[cpt] = I.bitmap[cpt].B + 1.0;
        break;

      default:
        break;
      }
    }

    for (int sc = 0; sc < scaleDiv; sc++) {
      vpImage<double> blurImage;
      double sigma = retinexScales[(size_t) sc];
      vpImageFilter::gaussianBlur(doubleRGB[(size_t) channel], blurImage, (unsigned int) kernelSize, sigma);

      for(unsigned int cpt = 0; cpt < size; cpt++) {
        //Summarize the filtered values.
        //In fact one calculates a ratio between the original values and the filtered values.
        doubleResRGB[(size_t) channel].bitmap[cpt] += weight * (std::log(doubleRGB[(size_t) channel].bitmap[cpt])
          - std::log(blurImage.bitmap[cpt]));
      }
    }
  }

  std::vector<double> dest(size*3);
  const double gain = 1.0, alpha = 128.0, offset = 0.0;

  for(unsigned int cpt = 0; cpt < size; cpt++) {
    double logl = std::log( (double) (I.bitmap[cpt].R + I.bitmap[cpt].G + I.bitmap[cpt].B + 3.0) );

    dest[cpt*3] = gain * (std::log(alpha * doubleRGB[0].bitmap[cpt]) - logl) * doubleResRGB[0].bitmap[cpt] + offset;
    dest[cpt*3 + 1] = gain * (std::log(alpha * doubleRGB[1].bitmap[cpt]) - logl) * doubleResRGB[1].bitmap[cpt] + offset;
    dest[cpt*3 + 2] = gain * (std::log(alpha * doubleRGB[2].bitmap[cpt]) - logl) * doubleResRGB[2].bitmap[cpt] + offset;
  }

  double sum = std::accumulate(dest.begin(), dest.end(), 0.0);
  double mean = sum / dest.size();

  std::vector<double> diff(dest.size());
  std::transform(dest.begin(), dest.end(), diff.begin(), std::bind2nd(std::minus<double>(), mean));
  double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
  double stdev = std::sqrt(sq_sum / dest.size());

  double mini = mean - dynamic*stdev;
  double maxi = mean + dynamic*stdev;
  double range = maxi - mini;

  if(vpMath::nul(range)) {
    range = 1.0;
  }

  for(unsigned int cpt = 0; cpt < size; cpt++) {
    I.bitmap[cpt].R = vpMath::saturate<unsigned char>((255.0 * (dest[cpt*3 + 0] - mini) / range));
    I.bitmap[cpt].G = vpMath::saturate<unsigned char>((255.0 * (dest[cpt*3 + 1] - mini) / range));
    I.bitmap[cpt].B = vpMath::saturate<unsigned char>((255.0 * (dest[cpt*3 + 2] - mini) / range));
  }
}