What is the default (Pixel) storage format used by OpenCV ?
I know it is BGR but is it BGR32 ? BGR16 ?
Is it Packed or Planar ?
Can you suggest me a way to find it out?
Thank you for your help.
[EDIT] Context : Actually I am trying to use OpenCV with another library called MIL (Matrox Imaging Library). I need to grab an Image with MIL and then convert it to an OpenCV Image. That is why I need to know the default pixel format, to configure MIL.
The image format is set by the flag when you create the image eg CV_8UC3 means 8bit pixels, unsigned, 3colour channels. In a colour image the pixel order is BGR, data is stored in row order.
The data isn't packed at the pixel level - it's 3bytes/pixel (BGRA is an option on some of the GPU calls).
Data may be packed at the line level, if the number of pixels in a row * the number of bytes/pixel isn't a multiple of 4 then the data is padded with zero to the next 32bit boundary. The call mat.ptr(n) returns a pointer to the start of the 'n' th row
Note that you can share memory with another comaptible image format by passing the data pointer from the MIL image to the ctor of the cv::Mat
It depends on the way you are managing the image: have you loaded it from a file with imread for example?
Have a look at imread here, with a colour jpeg for example you'll have a 3 channel format, 24 bits overall. Can you be more specific?
I do not know if it's useful, but I had a similar issue when converting an image from Android Bitmap (passed to OpenCV as a byte array RGBA8888) to OpenCV image (BGR888).
Here is how I've solved it.
cv::Mat orig_image1(orig_height, orig_width, CV_8UC4, image_data);
int from_to[] = { 0, 2, 1, 1, 2, 0};
cv::Mat image(orig_height, orig_width, CV_8UC3);
cv::mixChannels(&orig_image1, 1, &image, 1, from_to, 3);
orig_image1.release();
Related
I have a bitmap in RGB format, i.e. 24bit per pixel. How can I create a Mat object so that I can minimize data copying while making sure that the order of the channel is treated correctly, given that default order in OpenCV is BGR
In general you can use RGB order as usual, just remember to convert to correct color space when needed.
You can create a Mat header with no copies using:
int rows = ...
int cols = ...
uchar* rgb_buffer = ...
cv::Mat3b rgb_image(rows, cols, bgr_buffer);
None (or just a few) of the OpenCV functions assume that matrix data should be in BGR or RGB order. You can also operate on your data with your custom processing accounting for RGB order.
The fact that OpenCV images are in BGR order is mostly a matter of input / output (basically imshow, imread, imwrite, and the like).
You can always convert your image with cvtColor(..., RGB2<whatever>) in case you need to switch color space. This won't be a performance issue, since the data would be copied anyway.
RGB buffer:
int rows, int cols, uchar* input_RGB;
Mat buffer declaration:
Mat image(rows, cols, CV_8UC3, input_RGB);
https://docs.opencv.org/master/d6/d6d/tutorial_mat_the_basic_image_container.html
I have an image 16x16 pixel image , how can I put it in a matrix 1x256 pixel and then convert it back to a 16x16 pixel Using opencv ?
I tried reshape but it didn't succeed as when i make cout<< image.cols << image.rows give me the same number which is 16,16 also sometimes the image is not continuous so reshape won't work
Btw I need it in coding a neural network classifier.
// create matrix for the result
Mat image1x256(Size(256,1), image.type());
// use reshape function
Mat image16x16 = image1x256.reshape(image.channels(), 16);
// copy the data from your image to new image
image.copyTo(image16x16);
Since image16x16 and image1x256 are just different pointers to same data, then copying the data to one of them will actually change both.
Note that reshape function creates a new header (i.e. new smart pointer) that may be used instead of old one, but it is not changing properties of the original header that still exist and can be used.
I have a vector of Point2f which have color space CV_8UC4 and need to convert them to CV_64F, is the following code correct?
points1.convertTo(points1, CV_64F);
More details:
I am trying to use this function to calculate the essential matrix (rotation/translation) through the 5-point algorithm, instead of using the findFundamentalMath included in OpenCV, which is based on the 8-point algorithm:
https://github.com/prclibo/relative-pose-estimation/blob/master/five-point-nister/five-point.cpp#L69
As you can see it first converts the image to CV_64F. My input image is a CV_8UC4, BGRA image. When I tested the function, both BGRA and greyscale images produce valid matrices from the mathematical point of view, but if I pass a greyscale image instead of color, it takes way more to calculate. Which makes me think I'm not doing something correctly in one of the two cases.
I read around that when the change in color space is not linear (which I suppose is the case when you go from 4 channels to 1 like in this case), you should normalize the intensity value. Is that correct? Which input should I give to this function?
Another note, the function is called like this in my code:
vector<Point2f>imgpts1, imgpts2;
for (vector<DMatch>::const_iterator it = matches.begin(); it!= matches.end(); ++it)
{
imgpts1.push_back(firstViewFeatures.second[it->queryIdx].pt);
imgpts2.push_back(secondViewFeatures.second[it->trainIdx].pt);
}
Mat mask;
Mat E = findEssentialMat(imgpts1, imgpts2, [camera focal], [camera principal_point], CV_RANSAC, 0.999, 1, mask);
The fact I'm not passing a Mat, but a vector of Point2f instead, seems to create no problems, as it compiles and executes properly.
Is it the case I should store the matches in a Mat?
I am no sure do you mean by vector of Point2f in some color space, but if you want to convert vector of points into vector of points of another type you can use any standard C++/STL function like copy(), assign() or insert(). For example:
copy(floatPoints.begin(), floatPoints.end(), doublePoints.begin());
or
doublePoints.insert(doublePoints.end(), floatPoints.begin(), floatPoints.end());
No, it is not. A std::vector<cv::Pointf2f> cannot make use of the OpenCV convertTo function.
I think you really mean that you have a cv::Mat points1 of type CV_8UC4. Note that those are RxCx4 values (being R and C the number of rows and columns), and that in a CV_64F matrix you will have RxC values only. So, you need to be more clear on how you want to transform those values.
You can do points1.convertTo(points1, CV_64FC4) to get a RxCx4 matrix.
Update:
Some remarks after you updated the question:
Note that a vector<cv::Point2f> is a vector of 2D points that is not associated to any particular color space, they are just coordinates in the image axes. So, they represent the same 2D points in a grey, rgb or hsv image. Then, the execution time of findEssentialMat doesn't depend on the image color space. Getting the points may, though.
That said, I think your input for findEssentialMat is ok (the function takes care of the vectors and convert them into their internal representation). In this cases, it is very useful to draw the points in your image to debug the code.
I am using BGR to HSV conversion of image using OpenCV. Since I am new to this field and software, I may sound incorrect so please let me know if I am wrong.
Now, in my school project i want to work with HSV image, which is easily converted using
cvtColor(src, dst, CV_BGR2HSV);
I suppose, that imread() function reads image in a uchar format which is 8bit unsigned image (i suppose). In that case imshow() is also uchar.
But to work with HSV image, I am not sure but I feel i need to convert use Mat3b perhaps for the distinctive H, S and V channels of the image.
Incase if I am wrong, that I want to work with H channel of the HSV image only so how can i print, or modify this channel information.
Many thanks
Perhaps you can use cv::split to devide the HSV to 3 one-channel Mat. I think this topic OpenCV:split HSV image and scan through H channel may solve your problem.
I'm loading a 24 Bit RGB image from a PNG file into my OpenCV application.
However loading the image as grayscale directly using imread gives a very poor result.
Mat src1 = imread(inputImageFilename1.c_str(), 0);
Loading the RGB image as RGB and converting it to Grayscale gives a much better looking result.
Mat src1 = imread(inputImageFilename1.c_str(), 1);
cvtColor(src1, src1Gray, CV_RGB2GRAY);
I'm wondering if I'm using imread for my image type correctly. Has anyone experienced similar behavior?
The image converted to grayscale using imread is shown here:
The image converted to grayscale using cvtColor is shown here:
I was having the same issue today. Ultimately, I compared three methods:
//method 1
cv::Mat gs = cv::imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
//method 2
cv::Mat color = cv::imread(filename, 1); //loads color if it is available
cv::Mat gs_rgb(color.size(), CV_8UC1);
cv::cvtColor(color, gs_rgb, CV_RGB2GRAY);
//method 3
cv::Mat gs_bgr(color.size(), CV_8UC1);
cv::cvtColor(color, gs_bgr, CV_BGR2GRAY);
Methods 1 (loading grayscale) and 3 (CV_BGR2GRAY) produce identical results, while method 2 produces a different result. For my own ends, I've started using CV_BGR2GRAY.
My input files are jpgs, so there might be issues related to your particular image format.
The simple answer is, that openCV functions uses the BGR format. If you read in a image with imread or VideoCapture, it'll be always BGR. If you use RGB2GRAY, you interchange the blue channel with the green. The formula to get the brightness is
y = 0.587*green + 0.299*red + 0.114*blue
so if you change green and blue, this will cause an huge calculation error.
Greets
I have had a similar problem once, working with OpenGL shaders. It seems that the first container that OpenCV reads your image with does not support all the ranges of color and hence you see that the image is a poor grayscale transformation. However once you convert the original image into grayscale using cvtColor the container is different from the first one and supports all ranges. In my opinion the first one uses less than 8 bits for grayscale or changing to the grayscale uses a bad method. But the second one gives smooth image because of more bits in gray channel.