использование кластерных индексов из облака точек в изображении rgb

Я работаю с картой глубины, полученной из двух изображений (я взял ее из opencv StereoBM), и теперь мне нужно найти в них кластеры. Я решил использовать растущую сегментацию области pcl http://www.pointclouds.org/documentation/tutorials/region_growing_segmentation.php. Я преобразовал cv :: Mat в облако точек после прочтения этой статьи http://blog.martinperis.com/2012/01/3d-reconstruction-with-opencv-and-point.html и теперь у меня есть кластерные индексы. Это для функций здесь https://gist.github.com/Daiver/5586252 Теперь я хочу использовать эти индексы для отображения кластеров по глубине карта из StereoBM (cv :: Mat)

Я пытаюсь это сделать, но результат меня не устраивает

  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud; //cloud from depth map and rgb image
  std::vector <pcl::PointIndices> clusters;// clusters inices, extracted before
  for(int j = 0; j < clusters.size(); j++)
  {
      cv::Mat to_show = cv::Mat::zeros(288, 384, cv::DataType<uchar>::type);//image has size that equal size of rgb image and depth map        
      for(int i = 0; i < clusters[j].indices.size(); i++)
      {
        to_show.data[clusters[j].indices[i]] = 200;// regions in this Mat must be equal with regions from depth map
      }
      cv::imshow("", to_show);
      cv::waitKey();
  }

Результат Какой-то кластер введите описание изображения здесьДругой кластер  введите описание изображения здесь

Визуализированное облако введите описание изображения здесь

Как я могу проецировать кластеры на cv :: Mat? PS извините за мои ошибки в написании. Английский не на моем родном языке

UPD Я пытался "восстановить" карту глубины, используя циклы, такие как циклы в функции mat_to_cloud

int counter = 0;
cv::Mat to_show = cv::Mat::zeros(288, 384, cv::DataType<uchar>::type);
for(int i = 0; i < cloud->height; i++)
{
  for(int j = 0; j < cloud->width; j++)
  {
    to_show.at<uchar>(i, j) = cloud->at(counter).z;
    counter++;
  }
}

введите описание изображения здесь

И еще один порядок циклов int counter = 0; cv :: Mat to_show = cv :: Mat :: zeros (288, 384, cv :: DataType :: type); for (int j = 0; j ‹cloud-> width; j ++) {for (int i = 0; i‹ cloud-> height; i ++) {to_show.at (i, j) = cloud-> at (счетчик) .z; счетчик ++; }}

введите описание изображения здесь

Я не знаю, почему эти изображения похожи


person Dark_Daiver    schedule 15.05.2013    source источник
comment
Что именно в результате не так или вам не нравится? Кроме того, какая картинка на скриншотах что показывает?   -  person Sarien    schedule 15.05.2013
comment
Я хочу видеть отдельные кластеры на карте глубины. Как с одной головкой, одной лампой или одной камерой   -  person Dark_Daiver    schedule 15.05.2013
comment
Это то, что вы хотите, но каков ваш результат и что с ним не так?   -  person Sarien    schedule 15.05.2013
comment
Картинка справа от карты глубины на скриншотах - результат   -  person Dark_Daiver    schedule 15.05.2013
comment
обратите внимание, что правильный тег - point-cloud-library, PCL изначально означает язык команд принтера.   -  person Oszkar    schedule 23.05.2013


Ответы (2)


Раньше я не работал с PCL, но похоже, что эта строка может быть неправильной:

// regions in this Mat must be equal with regions from depth map
to_show.data[clusters[j].indices[i]] = 200;

to_show - это матрица opencv, но вы используете индексы из облака точек. Сначала вам нужно преобразовать индексы в пиксельные координаты.

person Sarien    schedule 15.05.2013
comment
Спасибо за ответ. Думаю, вы правы, но индексы из облака зависят от пикселей из Mat, потому что я добавил точки в облако в этом цикле: for (int i = 0; i ‹img_rgb.rows; i ++) {for (int j = 0; j ‹Img_rgb.cols; j ++) {/ * некоторая работа * / point_cloud_ptr-› push_back (point); // push_back добавил точки в конец вектора точек? Я думал, что порядок точек облачности такой же, как и у точек данных. }} - person Dark_Daiver; 15.05.2013
comment
Возможно, я прав, я предполагаю, что ваш тип данных неверен, или есть проблемы с выравниванием, или данные изображения упорядочены в режиме основного столбца. Попробуйте проверить это. - person Sarien; 15.05.2013
comment
Вы имеете в виду тип данных to_Show? или данные изображения упорядочены в основном режиме столбца Я думал об этом, но я не знаю, как это проверить - person Dark_Daiver; 15.05.2013
comment
Вы можете попробовать использовать тот же цикл, который вы использовали для получения индексов, чтобы записать их обратно в матрицу. Эти кривые линии выглядят так, будто ваш размер шага слишком мал, но они также зигзагообразны. Не знаю, слишком сложно отлаживать по картинкам. ;) - person Sarien; 15.05.2013

Я решил свою проблему, но мое решение немного грязное и глупое. Я сделал свою простую функцию перепроецирования

void straight_reproject_cloud(cv::Mat& img_rgb, cv::Mat& img_disparity, pcl::PointCloud<pcl::PointXYZRGB>::Ptr& point_cloud_ptr)
{
    uchar pr, pg, pb;
    for (int i = 0; i < img_rgb.rows; i++)
    {
        uchar* rgb_ptr = img_rgb.ptr<uchar>(i);
        uchar* disp_ptr = img_disparity.ptr<uchar>(i);
        for (int j = 0; j < img_rgb.cols; j++)
        {
            uchar d = disp_ptr[j];
            if ( d == 0 ) continue; //Discard bad pixels
            pb = rgb_ptr[3*j];
            pg = rgb_ptr[3*j+1];
            pr = rgb_ptr[3*j+2];
            //Insert info into point cloud structure
            pcl::PointXYZRGB point;
            point.x = j;
            point.y = i;
            point.z = d;
            uint32_t rgb = (static_cast<uint32_t>(pr) << 16 |
                  static_cast<uint32_t>(pg) << 8 | static_cast<uint32_t>(pb));
            point.rgb = *reinterpret_cast<float*>(&rgb);
            point_cloud_ptr->push_back (point);
        } 
    }
}

Эта функция добавляет точки в облако прямо из изображений, без изменений. Новое облако не совпадает со старым перепроецированием, но я могу работать с ним.

И теперь координаты точек в облаке сводятся к координатам на изображениях, я могу показать все кластеры из облака на изображении:

for(int k = 0; k < clusters.size(); k++)
{
    cv::Mat res = cv::Mat::zeros(img_rgb.rows, img_rgb.cols, CV_8U);
    //for(int i =0 ; i < point_cloud_ptr->points.size(); i++)
    for(int j =0 ; j < clusters[k].indices.size(); j++)
    {
        int i = clusters[k].indices[j];
        int x = point_cloud_ptr->at(i).x;
        int y = point_cloud_ptr->at(i).y;
        res.at<uchar>(y, x) = (int)(point_cloud_ptr->at(i).z);
    }
    cv::imshow("rec2", res);
    cv::waitKey();
}

введите описание изображения здесь

Новое облако

введите описание изображения здесь

person Dark_Daiver    schedule 18.05.2013
comment
Может мое перепроецирование кому-то поможет - person Dark_Daiver; 18.05.2013