3

I am trying to work with each pixel from depth map. (I am implementing image segmentation.) I don't know how to work with pixels from image with depth higher than 1.

This sample code copies depth map to another cv::Mat pixel by pixel. It works fine, if I normalize it (depth of normalized image = 1). But it doesn't work with depth = 3, because .at<uchar> is wrong operation for this depth.

cv::Mat res; 
cv::StereoBM bm(CV_STEREO_BM_NORMALIZED_RESPONSE);
bm(left, right, res);
std::cout<<"type "<<res.type()<<" depth "<<res.depth()<<" channels "<<res.channels()<<"\n";// type 3 depth 3 channels 1
cv::Mat tmp = cv::Mat::zeros(res.rows, res.cols, res.type());
for(int i = 0; i < res.rows; i++)
{
    for(int j = 0; j < res.cols; j++)
        {
                tmp.at<uchar>(i, j) = res.at<uchar>(i, j);
                //std::cout << (int)res.at<uchar>(i, j) << " ";
    }
    //std::cout << std::endl;
}
cv::imshow("tmp", normalize(tmp));
cv::imshow("res", normalize(res));

normilize function

cv::Mat normalize(cv::Mat const &depth_map)
{
    double min;
    double max;
    cv::minMaxIdx(depth_map, &min, &max);
    cv::Mat adjMap;
    cv::convertScaleAbs(depth_map, adjMap, 255 / max);
    return adjMap;
}

screenshot

left image - tmp, right image - res

How can I get the pixel from image with depth equal to 3?

apaderno
  • 28,547
  • 16
  • 75
  • 90
Daiver
  • 1,488
  • 3
  • 18
  • 47

2 Answers2

3

When your images are of depth 3, do this for copying pixel by pixel:

tmp.at<Vec3b>(i,j) = res.at<Vec3b>(i,j);

However, if you are copying the whole image , I do not understand the point of copying each pixel individually, unless you want to do different processing with different pixels.

You can just copy the whole image res to tmp by this:

res.copyTo(tmp);
Barshan Das
  • 3,677
  • 4
  • 32
  • 46
  • Thank you, for answer. My task is not copying, it just sample of problem. My task is work with each pixel individually, for image segmentation. Can i work with pixel through Vect3b as integer, or same primitive type? – Daiver Apr 13 '13 at 18:37
  • https://github.com/Daiver/scripts/blob/master/ocv/cpp/mystereo/main.cpp line 74 - i use pixel here, works fine if image normilized, but failded otherwise – Daiver Apr 13 '13 at 18:44
3

Mat::depth() returns value equal to a constant symbolising bit depth of the image. If You get depth equal to for example CV_32F, to get to the pixels You would need to use float instead of uchar.

CV_8S -> char

CV_8U -> uchar

CV_16U -> unsigned int

CV_16S -> int

CV_32F -> float

CV_64F -> double

Mat::channels() tells You how many values of that type are assigned to a coordinate. These multiple values can be extracted as cv::Vec. So if You have a two channel Mat with depth CV_8U, instead using Mat.at<uchar> You would need to go with Mat.at<Vec2b>, or Mat.at<Vec2f> for CV_32F one.

morynicz
  • 2,322
  • 2
  • 20
  • 34
  • Thank you, i switched to int, and copying works now! But then i do std::cout << res;//where res is depth map. I see another values, if i print values pixel by pixel – Daiver Apr 14 '13 at 11:14
  • What did `Mat::channels()` and `Mat::depth()` return to You? You might also try `short int` instead of `int`. Types in OpenCV are not defined very well. – morynicz Apr 14 '13 at 13:20
  • std::cout<<"type "< – Daiver Apr 14 '13 at 14:59
  • Well, only things I can think of for You is trying `short int`,checking if You should not change the depth/type of `tmp`, or look for something buggy in Your code. – morynicz Apr 14 '13 at 15:15