OPENCV: can IplImage* hold double value??? - opencv

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.

Related

Copy part of image to another image with EmguCV

I want to copy a center part (Rectangle) of my image to a completely white Mat (to the same position).
Code:
Mat src = Image.Mat;
Mat dst = new Mat(src.Height, src.Width, DepthType.Cv8U, 3);
dst.SetTo(new Bgr(255, 255, 255).MCvScalar);
Rectangle roi = new Rectangle((int)(0.1 * src.Width), (int)(0.1 * src.Height), (int)(0.8 * src.Width), (int)(0.8 * src.Height));
Mat srcROI = new Mat(src, roi);
Mat dstROI = new Mat(dst, roi);
srcROI.CopyTo(dstROI);
//I have dstROI filled well. CopyTo method is doing well.
//However I have no changes in my dst file.
However I'm getting only white image as a result - dst. Nothing inside.
What i'm doing wrong?
using EmguCV 3.1
EDIT
I have a dstROI Mat filled well. But there is a problem how to apply changes to original dst Mat now.
Changing CopyTo like this:
srcROI.CopyTo(dst);
causes that dst is filled now with my part of src image but not in the centre like i wanted
EDIT 2
src.Depth = Cv8U
As you suggested I check a value of IsSubmatrix property.
Console.WriteLine(dstROI.IsSubmatrix);
srcROI.CopyTo(dstROI);
Console.WriteLine(dstROI.IsSubmatrix);
gives output:
true
false
What can be wrong then?
Ancient question, I know, but it came up when I searched so an answer here might still be being hit in searches. I had a similar issue and it may be the same problem. If src and dst have different numbers of channels or different depths, then a new Mat is created instead. I see that they both have the same depth, but in my case, I had a single channel going into a 3 channel Mat. If your src is not a 3 channel Mat, then this may be the issue (it might be 1 (gray) or 4 channel (BGRA) for example).
According to the operator precedence rules of C# a type cast has higher priority than multiplication.
Hence (int)0.8 * src.Width is equivalent to 0 * src.Width, and the same applies to the other parameters of the roi rectangle. Therefore the line where you create the roi is basically
Rectangle roi = new Rectangle(0,0,0,0);
Copying a 0-size block does nothing, so you're left with the pristine white image you created earlier.
Solution
Parenthesize your expressions properly.
Rectangle roi = new Rectangle((int)(0.1 * src.Width)
, (int)(0.1 * src.Height)
, (int)(0.8 * src.Width)
, (int)(0.8 * src.Height));

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

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.

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);
}
}

Cannot get the proper stereo from L/R pair

I run the following code with the left and the right images and get the strange result. I'm not exactly sure what I'm doing wrong. First of all, why is it cropped and why is the disparity all one color?
CvStereoBMState *BMState = cvCreateStereoBMState();
assert(BMState != 0);
BMState->preFilterSize=41;
BMState->preFilterCap=31;
BMState->SADWindowSize=41;
BMState->minDisparity=-64;
BMState->numberOfDisparities=128;
BMState->textureThreshold=10;
BMState->uniquenessRatio=5;
CvMat* disp = cvCreateMat(image_pyramid[0][0]->height, image_pyramid[0][0]->width, CV_16S);
CvMat* vdisp = cvCreateMat(image_pyramid[0][0]->height, image_pyramid[0][0]->width, CV_8U);
cvFindStereoCorrespondenceBM(image_pyramid[0][0], image_pyramid[1][0], disp, BMState);
cvNormalize(disp, vdisp, 0, 256, CV_MINMAX);
cvSaveImage("wowicantbelieveitsnotbutter.jpg", vdisp);
I am not sure about the cropped image but I think that you should normalize it to range 0..1 and not to 0..255 since it is not 8 bit image.
Also maybe it looks cropped since the black values are actually negative.
Try changing min disparity to zero this may help in your case(problem due to cropping). I did face the same problem. But I came with a solution of BMTuner. I have seen a video. Here I attach video this may help you with problem of cropping.
http://www.youtube.com/watch?feature=player_embedded&v=FX7AMktf24E

Resources