Fill a std::vector with cv:Mat's - opencv

I've created a struct:
struct clusters_t {
cv::Mat ids;
cv::Mat means;
vector<cv::mat> covs;
cv::Mat weights;
} clusters;
And I have a problem filling the "covs". I reserve memory like I show below but... how can I copy a Mat inside the vector of mats??
clusters.covs.clear();
clusters.covs.reserve(0);
cv::Mat matrix;
newCovs.copyTo(clusters.covs.at(0)); //<-- DOESN'T WORK... HOW CAN I COPY matrix inside the vector?

Use resize instead of reserve (and be sure to create at least one element).
Alternatively,
newCovs.copyTo(std::back_inserter(clusters.covs));
will work too.
Nope, because it can't work on iterators.

Related

Set cv::Mat type without matrix size

I want to set the type of a cv::Mat object to CV_32F, but I don't care (at declaration time) of the matrix size.
There is any other way to do this:
cv::Mat m (0,0,CV_32F);
Something like:
cv::Mat m;
m.setType(CV_32F);
The simple answer is use cv::Mat1f or e.g. cv::Mat3f (as #Miki suggested).
However, the place where it actually matters is at allocation time, so there's no problem just leaving m as is, and when you actually come to allocate it to the desired size, set it there (e.g. with cv::Mat::create().
If m is just passed it auto allocating functions, then you don't actually need to set it at all.

How to convert a cv::Mat Image to an std::vector if the Image is not continuous?

I tried looking for solutions and came across this link
Converting a row of cv::Mat to std::vector .However, the answer here will only work if the image is continuous i.e length of a row = step size . Am I right or am I missing something? If I'm right, what is the most efficient way of copying a non-continuous image to a std::vector?
I am looking for something more efficient than,
for(int ii=0;ii<no. of image rows;ii++)
{
ptr = pointer to ii'th row
copy from ptr to (ptr+row length) into std::vector
}
Thanks,
Vishy
For a single channel 8-bit image,
std::vector<uchar> dstVec;
dstVec.assign(srcVec.begin(),srcVec.end());

How to show 2 channel Image or chnage it into 3 or one channel in OpenCv

I am new to Open Cv, I want to transform the two images,
here are my images,Left image and right image.
here is my Code
cv::Mat transformMat = cv::estimateRigidTransform(leftImageMat, rightImageMat, true);
transform(leftImageMat, reconMat, transformMat);
but the problem is that reconMat is of 2 channel. so how can I show it in openCv or convert to 1 channel image as shown above right and left images.
You have a fundamental misunderstanding of what cv::transform() does. The documentation
states:
Performs the matrix transformation of every array element.
This means that the numerical value of each element is transformed by the specified matrix.
It looks like you want a geometric transformation. This can be achieved using cv::warpAffine():
cv::Mat transformMat = cv::estimateRigidTransform(leftImageMat, rightImageMat, true);
cv::Mat output;
cv::Size dsize = leftImageMat.size(); //This specifies the output image size--change as needed
cv::warpAffine(leftImageMat, output, transformMat, dsize);

Convert image color space and output separate channels in OpenCV

I'm trying to reduce the runtime of a routine that converts an RGB image to a YCbCr image. My code looks like this:
cv::Mat input(BGR->m_height, BGR->m_width, CV_8UC3, BGR->m_imageData);
cv::Mat output(BGR->m_height, BGR->m_width, CV_8UC3);
cv::cvtColor(input, output, CV_BGR2YCrCb);
cv::Mat outputArr[3];
outputArr[0] = cv::Mat(BGR->m_height, BGR->m_width, CV_8UC1, Y->m_imageData);
outputArr[1] = cv::Mat(BGR->m_height, BGR->m_width, CV_8UC1, Cr->m_imageData);
outputArr[2] = cv::Mat(BGR->m_height, BGR->m_width, CV_8UC1, Cb->m_imageData);
split(output,outputArr);
But, this code is slow because there is a redundant split operation which copies the interleaved RGB image into the separate channel images. Is there a way to make the cvtColor function create an output that is already split into channel images? I tried to use constructors of the _OutputArray class that accepts a vector or array of matrices as an input, but it didn't work.
Are you sure that copying the image data is the limiting step?
How are you producing the Y ? Cr / Cb cv::mats?
Can you just rewrite this function to write the results into the three separate images?
There is no calling option for cv::cvtColor, that gives it result as three seperate cv::Mats (one per channel).
dst – output image of the same size and depth as src.
source: http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor
You have to copy the pixels from the result (as you are already doing) or write such a conversion function yourself.
Use split. This splits the image into 3 different channels or arrays.
Now converting them back to UIImage is where I am having trouble. I get three grayscale images, one in each array. I am convinced they are the proper channels in cvMat format but when I convert them to UIImage they are grayscale but different grayscale values in each image. If you can use imread and imshow then it should display the images for you after the split. My problem is trying to use the ios.h methods and I believe it reassembles the arrays, instead of transferring the single array. Here is my code using a segmented control to choose which layer, or array, you want to display. Like I said, I get 3 grayscale images but with completely different values. I need to keep the one layer and abandon the rest. Still working on that part of it.
UIImageToMat(_img, cvImage);
cv::cvtColor(cvImage, RYB, CV_RGB2BGRA);
split(RYB, layers);
if (_segmentedRGBControl.selectedSegmentIndex == 0) {
// cv::cvtColor(layers[0], RYB, CV_8UC1);
RYB = layers[0];
_imageProcessView.image = MatToUIImage(RYB);
}
if (_segmentedRGBControl.selectedSegmentIndex == 1) {
RYB = (layers[1]);
_imageProcessView.image = MatToUIImage(RYB);
}
if (_segmentedRGBControl.selectedSegmentIndex == 2) {
RYB = (layers[2]);
_imageProcessView.image = MatToUIImage(RYB);
}
}

OPENCV: can IplImage* hold double value???

I have to create an image to hold double value (that is -0.0001 or 0.005).
I've used
IplImage* temp = cvCreateImage(size, IPL_DEPTH_32F, 1)
but it doesn't work well. Have you some good ideas?
It works as it should, though you cannot visualize 32F image, you have to convert it to the 8U. See this page. BTW, the const is called CV_32F now.

Resources