Beispiel #1
0
inline cv::Mat opencv_create_mat_with_image2d(const image2d &image,
                                              command_queue &queue = system::default_queue())
{
    BOOST_ASSERT(image.get_context() == queue.get_context());

    cv::Mat mat;
    image_format format = image.get_format();
    const cl_image_format *cl_image_format = format.get_format_ptr();

    if(cl_image_format->image_channel_data_type == CL_UNORM_INT8 &&
            cl_image_format->image_channel_order == CL_BGRA)
    {
        mat = cv::Mat(image.height(), image.width(), CV_8UC4);
    }
    else if(cl_image_format->image_channel_data_type == CL_UNORM_INT16 &&
            cl_image_format->image_channel_order == CL_BGRA)
    {
        mat = cv::Mat(image.height(), image.width(), CV_16UC4);
    }
    else if(cl_image_format->image_channel_data_type == CL_FLOAT &&
            cl_image_format->image_channel_order == CL_INTENSITY)
    {
        mat = cv::Mat(image.height(), image.width(), CV_32FC1);
    }
    else
    {
        mat = cv::Mat(image.height(), image.width(), CV_8UC1);
    }

    opencv_copy_image_to_mat(image, mat, queue);

    return mat;
}
Beispiel #2
0
    /// Enqueues a command to write data from host memory to \p image.
    ///
    /// \see_opencl_ref{clEnqueueWriteImage}
    void enqueue_write_image(const image2d &image,
                             const size_t origin[2],
                             const size_t region[2],
                             size_t input_row_pitch,
                             const void *host_ptr,
                             const wait_list &events = wait_list())
    {
        BOOST_ASSERT(m_queue != 0);
        BOOST_ASSERT(image.get_context() == this->get_context());

        const size_t origin3[3] = { origin[0], origin[1], size_t(0) };
        const size_t region3[3] = { region[0], region[1], size_t(1) };

        cl_int ret = clEnqueueWriteImage(
            m_queue,
            image.get(),
            CL_TRUE,
            origin3,
            region3,
            input_row_pitch,
            0,
            host_ptr,
            events.size(),
            events.get_event_ptr(),
            0
        );

        if(ret != CL_SUCCESS){
            BOOST_THROW_EXCEPTION(opencl_error(ret));
        }
    }
Beispiel #3
0
    /// Enqueues a command to copy data from \p src_image to \p dst_buffer.
    ///
    /// \see_opencl_ref{clEnqueueCopyImageToBuffer}
    event enqueue_copy_image_to_buffer(const image2d &src_image,
                                       const buffer &dst_buffer,
                                       const size_t src_origin[2],
                                       const size_t region[2],
                                       size_t dst_offset,
                                       const wait_list &events = wait_list())
    {
        BOOST_ASSERT(m_queue != 0);
        BOOST_ASSERT(src_image.get_context() == this->get_context());
        BOOST_ASSERT(dst_buffer.get_context() == this->get_context());

        const size_t src_origin3[3] = { src_origin[0], src_origin[1], size_t(0) };
        const size_t region3[3] = { region[0], region[1], size_t(1) };

        event event_;

        cl_int ret = clEnqueueCopyImageToBuffer(
            m_queue,
            src_image.get(),
            dst_buffer.get(),
            src_origin3,
            region3,
            dst_offset,
            events.size(),
            events.get_event_ptr(),
            &event_.get()
        );

        if(ret != CL_SUCCESS){
            BOOST_THROW_EXCEPTION(opencl_error(ret));
        }

        return event_;
    }
Beispiel #4
0
    /// Enqueues a command to fill \p image with \p fill_color.
    ///
    /// \see_opencl_ref{clEnqueueFillImage}
    ///
    /// \opencl_version_warning{1,2}
    event enqueue_fill_image(const image2d &image,
                             const void *fill_color,
                             const size_t origin[2],
                             const size_t region[2],
                             const wait_list &events = wait_list())
    {
        BOOST_ASSERT(m_queue != 0);
        BOOST_ASSERT(image.get_context() == this->get_context());

        const size_t origin3[3] = { origin[0], origin[1], size_t(0) };
        const size_t region3[3] = { region[0], region[1], size_t(1) };

        event event_;

        cl_int ret = clEnqueueFillImage(
            m_queue,
            image.get(),
            fill_color,
            origin3,
            region3,
            events.size(),
            events.get_event_ptr(),
            &event_.get()
        );

        if(ret != CL_SUCCESS){
            BOOST_THROW_EXCEPTION(opencl_error(ret));
        }

        return event_;
    }
    int sad_distance(const image2d<F>& i1, const image2d<F>& i2,
                     vint2 a,
                     vint2 b,
                     const int winsize,
                     const int th)
    {
      int err = 0.f;

      const F* row1 = &i1(a - vint2(winsize/2, winsize / 2));
      const F* row2 = &i2(b - vint2(winsize/2, winsize / 2));

      for (int r = 0; r < winsize and err <= th; r++)
      {
        int err2 = 0;
        #pragma omp simd
        for (int c = 0; c < winsize; c++)
          err2 += std::abs((row1[c]) - (row2[c]));

        err += err2;
        row1 = (const F*)((const char*) row1 + i1.pitch());
        row2 = (const F*)((const char*) row2 + i2.pitch());
      }

      return err;
    }
Beispiel #6
0
inline void opencv_copy_image_to_mat(const image2d &image,
                                     cv::Mat &mat,
                                     command_queue &queue = system::default_queue())
{
    BOOST_ASSERT(mat.isContinuous());
    BOOST_ASSERT(image.get_context() == queue.get_context());

    queue.enqueue_read_image(image, image.origin(), image.size(), mat.data);
}
Beispiel #7
0
inline void opencv_copy_image_to_mat(const image2d &image,
                                     cv::Mat &mat,
                                     command_queue &queue = system::default_queue())
{
    BOOST_ASSERT(mat.isContinuous());
    BOOST_ASSERT(image.get_context() == queue.get_context());

    size_t origin[2] = { 0, 0 };
    size_t region[2] = { image.width(), image.height() };

    queue.enqueue_read_image(image, origin, region, 0, mat.data);
}
Beispiel #8
0
  void lucas_kanade(const image2d<V>& i1,
		    const image2d<V>& i2,
		    OPTS... opts)
  {
    auto options = iod::D(opts...);
    int niterations = options.get(_niterations, 21);
    int winsize = options.get(_winsize, 11);
    int nscales = options.get(_nscales, 3);
    int min_ev = options.get(_min_ev, 0.0001);
    int delta = options.get(_delta, 0.1);
    auto prediction = options.get(_prediction,
				  [] (auto p) { return vfloat2(0.f, 0.f); });
    auto flow = options.flow;

    auto keypoints = options.keypoints;

    typedef std::decay_t<decltype(V() - V())> Gr;
    pyramid2d<V> pyramid_prev(i1, nscales, 2, _border = winsize / 2);
    pyramid2d<vector<Gr, 2>> pyramid_prev_grad(i1.domain(), nscales, 2, _border = winsize / 2);
    pyramid2d<V> pyramid_next(i2, nscales, 2, _border = winsize / 2);

    scharr(pyramid_prev[0], pyramid_prev_grad[0]);
    pyramid_prev_grad.propagate_level0();

    for (int i = 0; i < keypoints.size(); i++)
    {
      auto kp = keypoints[i];

      vfloat2 tr = (prediction(kp)).template cast<float>() / float(std::pow(2, nscales));
      float dist = 0.f;
      for(int S = pyramid_prev.size() - 1; S >= 0; S--)
	{
	  tr *= pyramid_prev.factor();
	  auto match = lk_internals::match(kp.template cast<float>() / int(std::pow(2, S)),
					   tr,
					   pyramid_prev[S],
					   pyramid_next[S],
					   pyramid_prev_grad[S],
					   winsize,
					   min_ev,
					   niterations, delta);

	  tr = match.first;
	  dist = match.second;
	}

      flow(kp, tr, dist);

    }
  }
Beispiel #9
0
    /// Enqueues a command to copy data from \p src_image to \p dst_image.
    ///
    /// \see_opencl_ref{clEnqueueCopyImage}
    event enqueue_copy_image(const image3d &src_image,
                             const image2d &dst_image,
                             const size_t src_origin[3],
                             const size_t dst_origin[2],
                             const size_t region[2],
                             const wait_list &events = wait_list())
    {
        BOOST_ASSERT(m_queue != 0);
        BOOST_ASSERT(src_image.get_context() == this->get_context());
        BOOST_ASSERT(dst_image.get_context() == this->get_context());
        BOOST_ASSERT_MSG(src_image.get_format() == dst_image.get_format(),
                         "Source and destination image formats must match.");

        const size_t dst_origin3[3] = { dst_origin[0], dst_origin[1], size_t(0) };
        const size_t region3[3] = { region[0], region[1], size_t(1) };

        event event_;

        cl_int ret = clEnqueueCopyImage(
            m_queue,
            src_image.get(),
            dst_image.get(),
            src_origin,
            dst_origin3,
            region3,
            events.size(),
            events.get_event_ptr(),
            &event_.get()
        );

        if(ret != CL_SUCCESS){
            BOOST_THROW_EXCEPTION(opencl_error(ret));
        }

        return event_;
    }
Beispiel #10
0
inline void qt_copy_qimage_to_image2d(const QImage &qimage,
                                      image2d &image,
                                      command_queue &queue)
{
    queue.enqueue_write_image(image, image.origin(), image.size(), qimage.constBits());
}
Beispiel #11
0
bool jpeg_write_uint8_t(std::ostream& stream, const image2d<uint8_t>& imag) {
  jpeg_compress_struct 
    jpeg_ptr{};
  jpeg_error_mgr 
    jerr{};

  jpeg_ptr.err = jpeg_std_error(&jerr);
  jerr.error_exit     = jpeg_exit;
  jerr.output_message = jpeg_message;

  jpeg_create_compress(&jpeg_ptr);
  if (!jpeg_ptr.dest) {
    jpeg_ptr.dest = reinterpret_cast<jpeg_destination_mgr*>((*jpeg_ptr.mem->alloc_small)
                   (reinterpret_cast<j_common_ptr>(&jpeg_ptr), JPOOL_PERMANENT, sizeof(jpeg_dst)));
  }

  auto dst = reinterpret_cast<jpeg_dst*>(jpeg_ptr.dest);
  dst->stream = &stream;
  dst->jpeg.empty_output_buffer = &jpeg_writeproc;
  dst->jpeg.init_destination = [](j_compress_ptr compress) {
    auto dst = reinterpret_cast<jpeg_dst*>(compress->dest);
    dst->buffer = reinterpret_cast<JOCTET*>((*compress->mem->alloc_small)
                 (reinterpret_cast<j_common_ptr>(compress), JPOOL_IMAGE, buffer * sizeof(JOCTET)));

    dst->jpeg.next_output_byte = dst->buffer;
    dst->jpeg.free_in_buffer = buffer;
  };

  dst->jpeg.term_destination = [](j_compress_ptr jpeg_ptr) {
    auto dst = reinterpret_cast<jpeg_dst*>(jpeg_ptr->dest);
    auto count = buffer - dst->jpeg.free_in_buffer;

    if (count > 0) {
      dst->stream->write(reinterpret_cast<char*>(dst->buffer), count);
    }
  };

  jpeg_ptr.image_width = imag.get_shape()[0], jpeg_ptr.image_height = imag.get_shape()[1];

  switch (imag.get_features()) {
  case 1:
    jpeg_ptr.in_color_space = JCS_GRAYSCALE;
    jpeg_ptr.input_components = 1;
    break;
  case 3:
    jpeg_ptr.in_color_space = JCS_RGB;
    jpeg_ptr.input_components = 3;
    break;
  default:
    return false;
  }

  jpeg_set_defaults(&jpeg_ptr);
  jpeg_set_quality(&jpeg_ptr, 95, true);

  jpeg_start_compress(&jpeg_ptr, true);

  while (jpeg_ptr.next_scanline < jpeg_ptr.image_height) {
    auto r = imag.buffer() + (imag.get_shape().front() * imag.get_features() * jpeg_ptr.next_scanline);
    jpeg_write_scanlines(&jpeg_ptr, (JSAMPARRAY)&r, 1);
  }

  jpeg_finish_compress(&jpeg_ptr);
  jpeg_destroy_compress(&jpeg_ptr);
  return true;
}
Beispiel #12
0
  inline void
  semi_dense_optical_flow(const K& keypoints,
                          MC match_callback,
                          const image2d<unsigned char>& i1,
                          const image2d<unsigned char>& i2,
                          OPTS... options)
  {
    using Eigen::Matrix3f;
    
    auto opts = D(options...);
    const int winsize = opts.get(_winsize, 7);
    const int nscales = opts.get(_nscales, 4);
    const int min_scale = opts.get(_min_scale, 0);
    const int propagation_niters = opts.get(_propagation, 2);
    const int patchsize = opts.get(_patchsize, 5);
    const bool f_provided = opts.has(_fundamental_matrix);
    const Matrix3f F = opts.get(_fundamental_matrix, Matrix3f::Zero());
    constexpr bool epipolar_flow = opts.has(_epipolar_flow);
    constexpr bool epipolar_filter = opts.has(_epipolar_filter);
    const bool epipolar_filter_th = opts.get(_epipolar_filter, 2);
      
    auto pf_domain = make_box2d(i1.domain().nrows() / patchsize,
                                i1.domain().ncols() / patchsize);
    pyramid2d<vint2> pyr_flow_map(pf_domain, nscales, 2, _border = nscales);
    pyramid2d<unsigned char> pyr_flow_map_mark(pf_domain, nscales, 2, _border = nscales);
    pyramid2d<unsigned char> pyr_i1(i1, nscales, 2, _border = 2 * winsize);
    pyramid2d<unsigned char> pyr_i2(i2, nscales, 2, _border = 2 * winsize);
    pyramid2d<int> distance_map(pf_domain, nscales, 2, _border = nscales);

    assert(pyr_flow_map_mark.size() == nscales);

    // Compute epipole for epipolar flow.
    vfloat2 epipole = epipole_right(F);
    // Scale fundamental matrix.
    std::vector<Matrix3f> Fs(nscales, F);
    for (int scale = nscales - 1; scale >= 0; scale--)
    {
      Matrix3f downscale;
      downscale <<
        2, 2, 1,
        2, 2, 1,
        1, 1, 0.5;
      Fs[scale] = Fs[scale + 1].cwiseProduct(downscale);
    }
    
    for (int scale = nscales - 1; scale >= min_scale; scale--)
    {
      int scale_div= std::pow(2, scale);
      image2d<unsigned char> i1 = pyr_i1[scale];
      image2d<unsigned char> i2 = pyr_i2[scale];

      fill_border_mirror(i1);
      fill_border_mirror(i2);
      
      // Distance function
      auto distance = [&] (vint2 a, vint2 b, int max_distance)
        {
          if (i1.has(a) and i2.has(b))
            return of_internals::sad_distance(i1, i2, a, b, winsize, max_distance);
          else
            return INT_MAX;
        };
      
      image2d<unsigned char>& flow_map_mark = pyr_flow_map_mark[scale];      
      fill_with_border(flow_map_mark, 0);
      
      // Gradient descent
      #pragma omp parallel for
      for (int i = 0; i < keypoints.size(); i++)
      {
        vint2 p = keypoints[i] / scale_div;
        
        // Descent
        if (!pyr_flow_map_mark[scale](p / patchsize))
        {
          vint2 pf = p / patchsize;
          vint2 pfm = p / (2 * patchsize);
          vint2 prediction = p;

          // Multiscale Prediction
          if (scale < (nscales - 1) and pyr_flow_map_mark[scale + 1](pfm))
            prediction = p + pyr_flow_map[scale + 1](pfm) * 2;
          
          pyr_flow_map_mark[scale](p / patchsize) = 1;

          auto m = iod::static_if<epipolar_flow>
            ([&] { return epipolar_match(p, prediction, epipole, Fs[scale], distance); },
             [&] { return gradient_descent_match(p, prediction, distance, 5); });

          // Register match.
          vint2 match = p + m.flow;
          assert(pyr_flow_map_mark[scale].domain_with_border().has(p / patchsize));
          pyr_flow_map[scale](p / patchsize) = match - p;
          distance_map[scale](p / patchsize) = m.distance;
          pyr_flow_map_mark[scale](p / patchsize) = 2;
        }
      }

      // Propagation
      for (int Ki = 0; Ki < propagation_niters; Ki++)
      {

        auto loop_body = [&] (int r, int c)
          {
            auto& flow_map = pyr_flow_map[scale];
            vint2 p(r, c);
            vint2 pf(r / patchsize, c / patchsize);

            if (!pyr_flow_map_mark[scale](pf)) return;

            vint2 prev_flow = flow_map(pf);
            for (int dr = -1; dr <= 1; dr++)
              for (int dc = -1; dc <= 1; dc++)
              {
                if (!dr and !dc) continue;
                vint2 pfn(pf[0] + dr, pf[1] + dc);
                if (flow_map.has(pfn) and pyr_flow_map_mark[scale](pfn) and
                    (flow_map(pf) - flow_map(pfn)).norm() > 2 and
                    (prev_flow - flow_map(pfn)).norm() > 2)
                {
                  // Two neighbors with high divergence.
                  int d1 = distance_map[scale](pf);
                  int d2 = distance(p, p + flow_map(pfn), INT_MAX);

                  if (d2 < d1)
                  {
                    auto m = iod::static_if<epipolar_flow>
                      ([&] { return epipolar_match(p, vint2(p + flow_map(pfn)), epipole, Fs[scale], distance); },
                       [&] { return gradient_descent_match(p, p + flow_map(pfn), distance, 5); });

                    // Register match.
                    vint2 match = p + m.flow;
                    if (m.distance < d1)
                    {
                      pyr_flow_map_mark[scale](pf) = true;
                      pyr_flow_map[scale](pf) = match - p;
                      distance_map[scale](pf) = m.distance;
                    }
                
                  }
                }
              }
          };

        if (Ki % 2)
#pragma omp parallel for
          for (int r = 0; r < i1.nrows(); r+= patchsize)
            for (int c = 0; c < i1.ncols(); c+= patchsize)
              loop_body(r, c);
        else
#pragma omp parallel for
          for (int r = i1.nrows() - 1; r >= 0; r-= patchsize)
            for (int c = i1.ncols() - 1; c >= 0; c-= patchsize)
              loop_body(r, c);
      }
      
    }

    for (int pi = 0; pi < keypoints.size(); pi++)
    {
      vint2 pos = keypoints[pi];
      vint2 pos2 = pos / int(patchsize * std::pow(2, min_scale));
      if (pyr_flow_map_mark[min_scale].has(pos2) and pyr_flow_map_mark[min_scale](pos2))
        match_callback(pi, pos + pyr_flow_map[min_scale](pos2) * int(std::pow(2, min_scale)),
                       distance_map[min_scale](pos2));
    }
    
  }