Vector of rgb values to QImage - c++

Hi the context in which I need help is as follows. I construct a vector of rgb values (one rgb value is an UInt32) and i want to put them as fast as possible in a QImage preferably without setPixel as it is very slow. To take the first rgb value and put it at [0,0] in the image, next value at [0,1] and so on. Can anyone help me with this?

This QImage constructor is what you need. The trick is only in choosing right Format. I guess in your case it would be QImage::Format_RGB32.
So try:
std::vector<int32_t> pixels{/*init or fill-up your data*/};
int width = 42, height = 42; // your valid values here
// what you're interesting in
auto image(Qimage((uchar *)pixels.data(), width, height, QImage::Format_RGB32));
This approach is the fastest possible way - the pixels will not be copied, but original buffer will be used internally by QImage.
If you're going to render your image later with QPainter::drawImage, don't forget to pass Qt::NoFormatConversion as a flag - this will improve your app performance.

Related

Convert cv::MAT image to CVD::Image

I wanted to convert a cv::MAT image to a CVD::Image but i don't know how can I do. The reason is because previously I had a CVD::Image and I transformed it to cv::MAT in order to set a ROI region in the image, and now, I need the picture in CVD.
The code used to perform it, it's the following:
CVD::Image<CVD::byte> Imatge_a_modificar;
Imatge_a_modificar.copy_from(mimFrameBW_workingCopy); //The image is copied from another one
int x = frameWidth/2;
int y = frameHeight/2;
CvRect sROI = cvRect(x,y, frameWidth/2, frameHeight/2);
int xroi = sROI.x;
int yroi = sROI.y;
cv::Mat image(frameWidth,frameHeight,CV_8UC4,Imatge_a_modificar.data());
cv::Mat imageROI(image, sROI);
First of all, use cv::Rect, not CvRect. The latter is the obsolete C type from OpenCV version 1.
Concerning your question, you need to create CVD::Image the same way you created cv::Mat - from a given bitmap buffer, where your actual pixel values are stored. To access bitmap buffer of cv::Mat use ptr() method. To construct CVD::Image from a buffer, use the corresponding CVD::BasicImage constructor, and then convert CVD::BasicImage to CVD::Image using CVD::Image::copy_from method.

how can set a pointer to the content of a Mat variable in OpenCV

A Mat can be CV_8UC3, CV_8UC1, CV_32FC3 and etc. For example, for a Mat which is CV_8UC3, I can set a pointer: Vec3b *p to the Mat. However, If I only know the Mat's datatype which can be obtained using Mat.type(), How can I set a proper pointer?
The sad answer is: you can't. The type of data should be set in compilation time. But in your example actual type will be decided only during run time. You will have to put switch somewhere in your code. i.e. you will need to have different implementations of your algorithm for all possible types. Note however that you can prevent code duplication by using templates.
If you do know type of data, and the only thing you don't know is number of channels, then the problem is a bit simpler. For example if your image contains unsigned char you can write
uchar* p = img.ptr<uchar>();
And it doesn't matter whether your image have one channel or three. Of course when it comes to actually working with the pixels you do need this information.
Use a void pointer. Void pointers can point to any data type.
http://www.learncpp.com/cpp-tutorial/613-void-pointers/
If you know a type, you can set a pointer to the first element of the first row of cv::Mat using ptr (documentation)
cv::Mat matrix = cv::Mat::zeros(3, 3, CV_32F);
float* firstElement = matrix.ptr<float>(0);

How to get values of a Matrix which are non zero

I am translating some matlab code to c++ using opencv. I want to get the values of a Matrix which satisfies a condition. I created a mask for this and when I apply it to the original Matrix I get the same size of the original matrix but with 0 values which are not there in the mask. But my question is how can I get only the values that are non-zero in the matrix and assign it to a different matrix.
My matlab code is:
for i= 1:size(no,1)
mask= labels==i;
op = orig(mask, :); //op only contains the values from the orig matrix which are in the mask. So orig size and op size is not the same
.....
end
The c++ translation that I have now is:
for (int i=0; i<n.rows; i++)
{
Mat mask;
compare(labels,i,mask,CMP_EQ);
Mat op;
orig.copyTo(op,mask); //Here the orig size and the op size is always same but values which are not in the mask are 0
}
So, how can I create a matrix which only has the values that the mask satisfies???
You might try to make use of cv::SparseMat (http://docs.opencv.org/modules/core/doc/basic_structures.html#sparsemat), which only keeps non-zero values in a hash.
When you assign a regular cv::Mat to a cv::SparseMat, it automatically captures the non-zero values. From that point, you can iterate through the non-zero values and manipulate them as you'd like.
Hope I got question correctly and it helps!
OpenCv does support Matrix Expresions like A > B or A <= Band so on.
This is stated in the Documentation off cv::Mat
If you're simply wanting to store values, the Mat object is probably not the best way, since it has been made for the purpose of containing images.
In that case, use an std::vector object instead of the cv::Mat object, and you can use the .push_back handle whenever you find an element that is non-zero, which will dynamically resize the vector.
If you're trying to create a new image, then you have to be specific about what kind of image you want to see, because if you don't know how many nonzero elements there are, how can you set the width and height? Also you might end up with an odd number of elements.

Accessing pixel values OpenCV 2.3 - C++

How to access individual pixels in OpenCV 2.3 using C++?
For my U8C3 image I tried this:
Scalar col = I.at<Scalar>(i, j);
and
p = I.ptr<uchar>(i);
First is throwing an exception, the second one is returning some unrelated data. Also all examples I was able to find are for old IIPimage(?) for C version of OpenCV.
All I need is to get color of pixel at given coordinates.
The type you call cv::Mat::at with needs to match the type of the individual pixels. Since cv::Scalar is basically a cv::Vec<double,4>, this won't work for a U8C3 image (it would work for a F64C4 image, of course).
In your case you need a cv::Vec3b, which is a typedef for cv::Vec<uchar,3>:
Vec3b col = I.at<Vec3b>(i, j);
You can then convert this into a cv::Scalar if you really need to, but the type of the cv::Mat::at instantiation must match the type of your image, since it just casts the image data without any conversions.
Your second code snippet returns a pointer to the ith row of the image. It is no unrelated data, but just a pointer to single uchar values. So in case of a U8C3 image, every consecutive 3 elements in the data returned to p should represent one pixel. Again, to get every pixel as a single element use
Vec3b *p = I.ptr<Vec3b>(i);
which again does nothing more than an appropriate cast of the row pointer before returning it.
EDIT: If you want to do many pixel accesses on the image, you can also use the cv::Mat_ convenience type. This is nothing more than a typed thin wrapper around the image data, so that all accesses to image pixels are appropriately typed:
Mat_<Vec3b> &U = reinterpret_cast<Mat_<Vec3b>&>(I);
You can then freely use U(i, j) and always get a 3-tuple of unsigned chars and therefore pixels, again without any copying, just type casts (and therefore at the same performance as I.at<Vec3b>(i, j)).

Need to keep track of types of opencv Mats

So I'm using the class Mat from opencv in a program I'm writing. Mat looks something like this:
class Mat {
public:
Mat(int width, int height, int type);
template <typename T> T getElt(int x, int y);
int depth();
...
}
The type in the constructor specifies whether elements in the Mat are floats, ints, etc as well as the number of channels in the image. depth() returns the data type used to store image elements.
Unfortunately I have to call getElt() in my code. Whenever I do that I use a switch statement to check the depth of the Mat so I can call getElt() with the appropriate template parameter. Doing it that way is pretty verbose, so I was wondering if there was a better way to do it. Could I create a container for a Mat and use template magic create a method that returns a type as opposed to a value? Or could I use macros to make things more efficient and logical?
I'd rather not have to subclass Mat since there are several methods besides getElt() for which I have this same issue.
Edit: made the description more accurate.
You're probably looking for Mat_<T> instead. An black&white image really isn't the same as a greyscale image, and neither is equal to a color image. Those should be separate at compile time.
IIRC the 'type' in openCV MAT corresponds to the image type (ie number of channels) not the data type float/int/char etc.
If you want a templated image class that can transparently work with char/int/bool/double etc - take a look at CImg