Closed hduonggithub closed 3 years ago
Is there anyone can help me to write single band 16bit depth image correctly? Thanks
Hi, I use opencv like
frames.depthFrame_ = std::make_shared<cv::Mat> ( Mat(Size(width, height), CV_16UC1, (void*)frame_depth.get_data(), Mat::AUTO_STEP));
and imwrite works fine for me
@hduonggithub, the issue is with the export call:
stbi_write_png(png_depth_file.str().c_str(), vf_depth.get_width(), vf_depth.get_height(), vf_depth.get_bytes_per_pixel(), (uint16_t*)vf_depth.get_data(), vf_depth.get_stride_in_bytes());
It assumes the input buffer being Big-endian according to PNG spec, while Z16
depth format is little-endian. So practically you need to swap the bytes order for each depth pixel (word) in the input buffer before calling stbi_write_png
@ev-mp Can you give me a sample code to swap the bytes? Thanks
@hduonggithub , you can do
std::vector<uint16_t> values(w*h);
memcpy((uint8_t*)values.data(),vf_depth.get_data(),values.size() * sizeof(uint16_t));
std::for_each(values.begin(), values.end(), [](uint16_t& val){ val=((val<<8)|(val>>8)); });
stbi_write_png(... ,values.data,() ... )
@ev-mp I have modified the code as following. The result still looks incorrectly. Any idea?
const int w = vf_depth.get_width();
const int h = vf_depth.get_height();
std::vector<uint16_t> values(w * h);
memcpy((uint8_t*)values.data(), vf_depth.get_data(), values.size() * sizeof(uint16_t));
std::for_each(values.begin(), values.end(), [](uint16_t& val) { val = ((val << 8) | (val >> 8)); });
stbi_write_png(png_depth_file.str().c_str(), w, h, vf_depth.get_bytes_per_pixel(), values.data(), vf_depth.get_stride_in_bytes());
@hduonggithub , the input data is 16bpp. Is the tool you're using for snapshot it capable of handling 16bit data channels? From the picture it is seen as if the render just presents the lower 8 bits of the data, hence the repetitive "wave" structure. Most display/graphic card vendors still render True-color 24bit, or 8bit per channel, So I think it is the limitation of the graphic card/display you're using to present the result. You can still use 16bit PNG with Processing software, such as Matlab. It is just not suitable to be presented with standard displays. For that we have a "colorizer" class in SDK that transfers 16bit single-channel depth data to 24bit RGB color space and makes "human-readable" images.
@ev-mp I did use EVNI/IDL software which is well known software for image processing. Below images are displayed in the same tool.
Test dataset shows correctly info: single band 16 bit image, BSQ format, Uint data type Mine is 2 band image, BIP format and Byte data type.
I am so confused now. The data values look rounded and very small compared to test dataset (see profiles red color). Any help is really welcome. Thanks!
This is test dataset from open3d
This is mine
@hduonggithub , the difference is in the data header -
Mine is 2 band image, BIP format and Byte data type.
The PNG image appears stored incorrectly as 2-channel 8-bit rather than single-channel 16 bit data. I looked up 'stbi' header and it seem to generate 8-bit per channel files only and therefore is not suitable to store 16-bit depth as native PNG.
The functions create an image file defined by the parameters. The image is a rectangle of pixels stored from left-to-right, top-to-bottom. Each pixel contains 'comp' channels of data stored interleaved with 8-bits per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is monochrome color.)
We'll look for alternatives for stbi
to deliver this capability for Z16
, but in the meanwhile I suggest to serialize the raw data directly and handle it as a binary format:
https://github.com/IntelRealSense/librealsense/blob/f7cdf6e8961e1709f6d864bdb33095c00a671ca7/common/model-views.cpp#L346-L360
@ev-mp Thanks. I will look forward to it. I will try your suggestion, I just do not know if open3d library can regconize this format or not. You may know.
I also will try using opencv as suggested by @cdb0y511
@cdb0y511 Do you have any problem to compile when using imwrite? I think there is something missing here in opencv from realsense SDK package, so I cannot compile when using imwrite.
If I comment out the imwrite, the code was compiled successfully. If uncomment out the imwrite, I got this error:
The code:---------------
Mat image16(Size(w, h), CV_16UC1, (void*)depth.get_data(), Mat::AUTO_STEP);
std::vector
The error:-------------------
Error LNK2019 unresolved external symbol "bool __cdecl cv::imwrite(class cv::String const &,class cv::debug_build_guard::_InputArray const &,class std::vector<int,class std::allocator
Any help to fix this, Thanks!
@hduonggithub Hi, I don't meet this problem, try
cv::imwrite("test.png", image16);
It does not relate with the SDK. I think you modified the sample directly. so you may check your include or cmakelist again.
@cdb0y511 I believe the imshow and imwrite should be in the same opencv package, right?
When I make the new project, using my opencv (4.4.0) (not using opencv from C:\Program Files (x86)\Intel RealSense SDK 2.0\third-party\opencv-3.4\include\opencv2), then I am able to compile and write depth image correctly in single band 16 bit format.
Here is my depth image
I use 3.4 from GitHub. The warp from SDK third party may not include the full function of open CV ,I guess.
Hi,
Will you be needing further help with this? If we don’t hear from you in 7 days, this issue will be closed.
Thanks
Before opening a new issue, we wanted to provide you with some useful suggestions (Click "Preview" above for a better view):
All users are welcomed to report bugs, ask questions, suggest or request enhancements and generally feel free to open new issue, even if they haven't followed any of the suggestions above :)
Issue Description
Hi Support Team,
I am trying to write to images for both color and 16-bit depth from L515 camera. The color and depth image must be aligned and the same dimension. The depth should be in 16-bit format.
I have played with rs-capture and rs-save-to-disk, but my depth images did not look right. I did check the format which is shown as below:![image](https://user-images.githubusercontent.com/11492480/89811677-9dae0100-db04-11ea-8408-0f6694dd192a.png)
Please advise, Thanks!
Here is my code which is modified from rs-capture and rs-save-to-disk
Here is result CASE 1: //rs2::align align_to(RS2_STREAM_DEPTH)
![depth66](https://user-images.githubusercontent.com/11492480/89811173-e4e7c200-db03-11ea-8a04-a0a297c6fb31.png)
CASE 2;s2::align align_to(RS2_STREAM_COLOR); /////////////CASE 2
![depth0](https://user-images.githubusercontent.com/11492480/89811264-047eea80-db04-11ea-847b-8e908cd6b19b.png)