im trying to access to pixel value of depth map, using kinect, openni and opencv. im using this code
Mat depth;
VideoCapture capture1(CV_CAP_OPENNI);
capture1.grab();
capture1.retrieve(depth,CV_CAP_OPENNI_DEPTH_MAP);
imshow("depth",depth);
waitKey(0);
cout << depth.at<unsigned>(20,20);
system("PAUSE");
the program show me the depth map but when i tried to acccess to the value, produce an error. but if y put:
cout << depth;
then show me all the values.
Since you didn't specified the error, I'll give it a shot: the problem seems to be that you are trying to access elements from another Mat: the one you create is named depth, however the one referenced in the cout call is named depthshow.
According to the documentation for CAP_OPENNI_DEPTH_MAP, your Mat should have 16 bits unsigned integer data per pixel, rather than the 32-bits unsigned int you're trying to use. Therefore, use the following instead:
// uint16_t available in C++11
cout << depth.at<uint16_t>(20,20) << " millimetres";
or
// not 100% sure that all compilers produce 16 bits fields
cout << depth.at<unsigned short int>(20,20) << " millimetres";
Related
I am very new to openCV and learning as I go.
I am using openCV 4.3, however the following is from 2.4:
"If you use cvtColor with 8-bit images, the conversion will have some information lost. For many applications, this will not be noticeable but it is recommended to use 32-bit images in applications that need the full range of colors or that convert an image before an operation and then convert back."
I am using a 24bit jpg image and applying some minor color correction to the LAB channels before converting back to BGR (similar to the warning in the 2.4 notes).
I load the image with:
//Ask user for filename and load with IMREAD_COLOR
string filename, finalFilename;
cout << "Which would you like to load? " << "\n";
cin >> filename;
cout << "What would you like to call the final image? " << "\n";
cin >> finalFilename;
Mat img = imread(filename, IMREAD_COLOR);
//Convert to CIEL*a*b* format and split for histogram
Mat imgLab;
cvtColor(img, imgLab, COLOR_BGR2Lab);
//Checking type and depth of image to ensure CV_8U (Note: This may have to be converted as to not lose information)
cout << "IMREAD_COLOR Loaded this image with a depth value of " << img.depth() << " and a type value of " << img.type() << "\n";
cout << "cvtColor has changed this image to one with a type value of " << imgLab.type() << "\n\n";
Then I manipulate the channels later on after assigning them to temp variables:
{
for (int j = 0; j < img.cols; j++)
{
modA.at<uint8_t>(i, j) = (float)tempA.at<uint8_t>(i, j) + (0.7f * ((float)mask.at<uint8_t>(i, j))/255 * (128-((float)aBlur.at<uint8_t>(i, j))));
modB.at<uint8_t>(i, j) = (float)tempB.at<uint8_t>(i, j) + (0.7f * ((float)mask.at<uint8_t>(i, j))/255 * (128-((float)bBlur.at<uint8_t>(i, j))));
}
}
Mask is a 1 channel 8 bit matrix that holds values from 0-255.
aBlur is tempA with a Gaussian blur applied (same applies to tempB/bBLur).
For some reason, after the conversion, the channels seem to still be skewed from 0-255. (though I could be wrong about this, I noticed that they went above 127 and never below about 100, a bit strange.
I have done a few tests and the type before converting to LAB and after remain the same (CV_8UC3). There is a warning due to the (float) code that there could be information loss:
Severity Code Description Project File Line Suppression State
Warning C4244 '=': conversion from 'float' to '_Tp', possible loss of data OpenCvLearning
My question is:
Am I losing information by this process? I noticed my output was not as pleasant as the paper I am attempting to reimplement.
Here is the original, my imp, and their result:
Colours coming out more gray than they should
UPDATE
So I have updated my code to work with float, which now has many more points possible data (2^32). However when polling the data it is still in 8bit (0-255).
I am attempting to use normalize min n max with the old min and max of the 8bit function and scaling to 0-1 for 32 bit. However, I am concerned about scaling back to 8bit without introducing 8bit error (how can I normalize 0-255 in a matrix that doesn't have 0 or 1 in the 32 bit version?)
I've c++ and OpenCV 3.1 and i separated the RGB three channels with these code :
Mat src = imread("original_image.jpg",CV_LOAD_IMAGE_COLOR);
Mat bgr[3] , bluemat ;
split(src,bgr);
bluemat = bgr[0];
std::cout << "bluemat.at<int>(0,1); : " << bluemat.at<int>(0,1) << '\n';
The strange thing is it print out a big number : 1415208581 , why is that ?
Isn't it suppose to be in 0-255 range ? why it is not ?
(expanding comment for search)
A feature of openCV is that the cv::Mat image type is a very simple object based on the original C version of the library.
The cv::Mat contains a field giving the pixel type but the data is stored simply as a block of memory bytes. You can use this block of memory to store and access pixels however you want. It makes it very flexible and easy to link with other libraries, but means you need to manually keep track of what the data is.
So data.at<int>(0,0) will extract the first pixel as if the data was ints (whatever int is on your platform), data.at<uchar> (0,0) will get the first pixel as a byte (which is generally what you want).
The main difference here is casting the memory byte to uchar vs int. What form the data you have depends on how you read it in. CV_LOAD_IMAGE_COLOR read the image as 16-bit/32-bit values. I cannot compile the code you gave me becuase of the memory issues that are created by converting that data to an int.
Now, if you use uchar, that will be solved. The problem however with the cout printing a character, has to do with the overload functions of <<
Mat src = imread("1.jpg", CV_LOAD_IMAGE_COLOR);
Mat bgr[3], bluemat;
split(src, bgr);
bluemat = bgr[0];
std::cout << "bluemat.at<uchar>(0,1); : " << (int)bluemat.at<uchar>(0, 1) << '\n';
What I changed was just to insert the typecast int. This issue is expanded here, but tells the output stream that this is a number, not a character.
I simply can't understand the opencv Mat types:
CV_16UC3 is well known as unsigned 16 bit 3 channel integer. However when I access each channels, I get negative values. According to How should I name my RGB channels, using cv::Mat_ Vec3s is the keyword to access. Here is what I did:
Mat mat_l(img_height,img_width,CV_16UC3);
mat_l = imread("/home/zhao/workspace/rectified_images/l_rectified_fountain.ppm");
cout << vec_mats_l[1].at<Vec3s>(44,500)[0] << " "
<< vec_mats_l[1].at<Vec3s>(44,500)[1] << " "
<< vec_mats_l[1].at<Vec3s>(44,500)[2] << endl;
Output is : 27522 -32382 -32407
why negative values despite type beeing defined unsigned???
try imread(path, -1);
without the flag, the image will be forced into CV_8UC3
(you can check the outcome with cout << mat_l.type();)
also, preallocating mat_l has no effect at all when you use imread, it will be overwritten anyway, so better leave it empty.
"why negative values" - Vec3s is signed. the unsigned version is Vec3w
I have a image buffer stored as a linear array[640*480] of unsigned integer type, and I want to save this array as a bitmap image which can be viewed. I have captured an image from my camera and retrieved its image buffer from a GigE cable using in c++ code. So please tell me how to write an integer array of RGB values to Bitmap in C++ along with the header files required. I have stream buffer as
if (Result.Succeeded())
{
// Grabbing was successful, process image
cout << "Image #" << n << " acquired!" << endl;
cout << "Size: " << Result.GetSizeX() << " x "
<< Result.GetSizeY() << endl;
// Get the pointer to the image buffer
const unsigned int *pImageBuffer = (int *) Result.Buffer();
the pImagebuffer is the image Buffer and please ignore the Functions as they belong to a custom compiler. I just want to convert the RGB values to bitmap image and then save it
also the pImageBuffer is giving me the R=G=B as photo is mono chrome.
Save the pixel data together with a simple BMP-file header, appropriately initialized. See the format description here.
CompVision once again, I'm working with jpeg images in my application. Just because I'm a bit familiar with MFC and ATL, I used CImage to access pixel values.
For my needs I calculate brightness matrix for the image during initialization. Function goes like this (Image is the name of my own class, unimportant, bright is float[][]):
void Image::fillBrightnessMatrix(){
COLORREF val;
for(int i=0;i<width;i++){
for(int j=0; j<height;j++){
val=src.GetPixel(i,j);
bright[i][j]=rgb_to_L(val);
}
}
}
Where src is an instance of CImage class, rgb_to_L - some function that calculates brightness of the color.
Examining the performance of my app, I discovered that GetPixel is the most expensive operation, and it significantly (really, ~700 times slower than any other operation) slows down the whole initializing of image. The question is, which library can you suggest for fast access to single pixel values? I don't need any other operations but loading jpeg image and accessing single pixels. Performance is important, because my application works with set of ~3000 images and I can't wait for hours to get results.
Use CBitmap::GetBits() to get a raw pointer to the pixel data. You can now directly party on the pixels without going through the expensive GetPixel() method. There are a number of things you need to be careful with when you do this:
You have to use CBitmap::GetPitch() to calculate the offset to the start of a line. The pitch is not the same as the width.
Lines in the bitmap are stored upside-down
You have to deal with the pixel format yourself. A 24bpp image stores 3 bytes per pixel. An indexed format like 8bpp requires looking up the color in the color table. 32bpp is the easy one, 4 bytes per pixel and the pitch is always the same as the width.
I always recommend OpenCV.
This is a humble code snippet to get you started:
IplImage* pRGBImg = cvLoadImage("c:\\test.jpg", CV_LOAD_IMAGE_UNCHANGED);
if (!pRGBImg)
{
std::cout << "!!! cvLoadImage failed !!!" << std::endl;
exit(1);
}
int width = pRGBImg->width;
int height = pRGBImg->height;
int bpp = pRGBImg->nChannels;
for (int i=0; i < width*height*bpp; i+=bpp)
{
if (!(i % (width*bpp))) // print empty line for better readability
std::cout << std::endl;
std::cout << std::dec << "R:" << (int) pRGBImg->imageData[i] <<
" G:" << (int) pRGBImg->imageData[i+1] <<
" B:" << (int) pRGBImg->imageData[i+2] << " ";
}
You should probably extract the jpeg to raw data, then access the raw data instead of GetPixel.