I am trying to convert this c api to c++
IplImage* hbm0 = cvCreateImage(cvSize(hbmp->width,hbmp->height),hbmp->depth, hbmp->nChannels );
I tried doing like this,
cv::Mat hbm0 = cv::Mat(hbmp.cols,hbmp.rows,hbmp.depth(), hbmp.channels() )
since mat constuctor doesnot seem to have parameters for depth and channels
Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
what could be the best way to convert,as i am not directly using channels they are in a Mat object itself.
Thanks
Related
I am taking in RGB data from my Kinect and trying to put it into an OpenCV matrix. The data is held in "src":
Mat matrixImageRGBA(w, h, CV_8UC4);
memcpy(matrixImageRGBA.data, src, sizeof(byte) * w * h * 4);
However, when I use "imshow" to see the image, it is tiled four time horizontally. I am using the following command:
imshow("Window", matrixImageRGBA);
waitKey(500);
Does anyone have any idea of what the problem may be here? It's driving me nuts.
Thanks!
You have w and h backwards. According to the docs the constructor takes the height as the first argument:
Mat (int rows, int cols, int type)
Also, I would recommend using this constructor:
Mat(int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
instead of copying to the data field (since you are using no padding at the end of each row use the default AUTO_STEP for step).
I'm working with a Ximea Camera, programming in c++ and using Ubuntu 14.04. I have a XI_IMG image and with the next conversion I'm creating an OpenCV image, copying data from xiAPI buffer to OpenCV buffer.
stat = xiGetImage(xiH, 5000, &image);
HandleResult(stat,"xiGetImage");
XI_IMG* imagen = ℑ
IplImage * Ima = NULL;
char fname_jpg[MAX_PATH] = "";
Ima = cvCreateImage(cvSize(imagen->width, imagen->height), IPL_DEPTH_8U, 1);
memcpy(Ima->imageData, imagen->bp, imagen->width * imagen->height);
imwrite("image1", Ima);
After doing that I should be able to save or show the image, but the next error is shown:
program.cpp:76:24:error:invalid initialization of reference of type 'cv::InputArray {aka const cv::_InputArray&}' from expression of type 'IplImage* {aka IplImage*}'
Is there any other way to obtain or save the image? What else can I do to save a jpg image?
You are mixing old (and obsolete) C syntax like IplImage*, cv<SomeFunction>(), etc... with current C++ syntax.
To make it work be consistent and use only one style.
Using IplImage
int main()
{
IplImage* img = NULL;
img = cvCreateImage(...);
// Save
cvSaveImage("myimage.png", img);
// Show
cvShowImage("Image", img);
cvWaitKey();
return 0;
}
Or using new syntax (much better):
int main()
{
Mat img(...);
// Save
imwrite("myimage.png", img);
// Show
imshow("Image", img);
waitKey();
return 0;
}
Note that you don't need to memcpy the data after you initialize your Mat, but you can call one of these constructors:
C++: Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
C++: Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
C++: Mat::Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0)
Last trick, you can wrap your IplImage in a Mat and then use imwrite:
Mat mat(Ima);
imwrite("name.ext", mat);
I am trying to learn some basics, but I keep getting errors.
I am trying to resize a cv::Mat
Edit to clarify why I am not loading an image: I am trying to test without having access to external files.
Inside the code, though, I put int x = M.depth(); and it read 0
cv::Mat M(2,2, CV_8UC3, cv::Scalar(0,0,255));
scale = 2;
cv::Size myImageSize;
myImageSize.height = M.rows;
myImageSize.width = M.cols;
cv::Mat ImgCopy = cvCreateImage(myImageSize, M.depth(), M.channels());
..
cv::resize(M, ImgCopy, myImageSize, 0, 0, CV_INTER_LINEAR);
I am getting an error on the line cvCreateImage
Input image depth is not supported by function (Unsupported format) in unknown functio, file... \modules\core\src\array.cpp...
I have tried with other values (CV_32F...) and I get the same error.
Please help !
cvCreateImage() is for use with the C API and returns an IplImage*. To initialize a cv::Mat, use the appropriate constructor.
cv::Mat ImgCopy(M.size(), M.type());
is the most succinct way to create and allocate memory for a new cv::Mat.
However, cv::resize() makes it even easier. You just have to declare your image
cv::Mat ImgCopy
and the arguments to cv::resize() allow automatic calculation of the correct dimensions and type. The last three parameters do not need to be specified because you don't change them from the defaults.
cv::resize(M, ImgCopy, myImageSize);
Try this code :
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
IplImage *src,*dst;
src=cvLoadImage("img.png");
cvNamedWindow("SRC", CV_WINDOW_AUTOSIZE);
cvNamedWindow("DST", CV_WINDOW_AUTOSIZE);
dst = cvCreateImage(cvSize(500,500),src->depth,src->nChannels);
cvResize(src,dst);
cvShowImage("SRC",src);
cvShowImage("DST",dst);
cvWaitKey(0);
cvDestroyWindow("SRC");
cvDestroyWindow("DST");
cvReleaseImage(&dst);
cvReleaseImage(&src);
return 0;
}
I have a C++ function that is to be called from someone else's C# application. As input my function is given an array of signed short integers, the dimensions of the image it represents, and memory allocated for the returning data, namely another array of signed short integers. This would represent my function's header:
my_function (short* input, int height, int width, short* output)
Inside my function I create a cv::Mat from input, like this:
cv::Mat mat_in = cv::Mat (height, width, CV_16S, input);
This mat_in is then converted to CV_32F and processed by OpenCV's cv::bilateralFilter. After it returns cv::Mat mat_out, I convert the data back to CV_16S (bilateralFilter only accepts CV_8U and CV_32F). Now I need to convert this cv::Mat mat_out back to an array of short integers so that it may be returned to the calling function. This is my code:
my_function (short* input, int height, int width, short* output)
{
Mat mat_in_16S = Mat (height, width, CV_16S, input);
Mat mat_in_32F = Mat (height, width, CV_32F);
Mat mat_out_CV_32F = Mat (height, width, CV_32F);
mat_in_16S.convertTo (mat_in_32F, CV_32F);
bilateralFilter (mat_in_32F, mat_out_32F, 5, 160, 2);
Mat mat_out_16S = Mat (mat_in_16S.size(), mat_in_16S.type());
mat_out_32F.convertTo (mat_out_16S, CV_16S);
return 0;
}
Obviously, somewhere there at the end I need to get the data that is in mat_out_16S into output. My first try was to return a reference:
output = &mat_out_16S.at<short>(0,0);
but of course I realised that this was a silly idea, as mat_out_16S goes out of scope as soon as the function returns, leaving output pointing at emptiness. Currently my best attempt is as follows (from this question):
memcpy ((short*)output, (short*)mat_out_16S.data, height*width*sizeof(short));
Now I would like to know, is there a better way? It feels kind of inefficient to copy all this data, but I don't see what else I can do. I can't return a cv::Mat unfortunately. If there is no better way, is my current memcpy method safe at least? My data are all 2-byte signed short integers, so I don't think there should be issues with padding, but I don't want to run into any unpleasant surprises.
You can use this constructor for your mat_out_16S:
Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
So your function will be:
my_function (short* input, int height, int width, short* output)
{
Mat mat_in_16S = Mat (height, width, CV_16S, input);
Mat mat_in_32F = Mat (height, width, CV_32F);
Mat mat_out_CV_32F = Mat (height, width, CV_32F);
mat_in_16S.convertTo (mat_in_32F, CV_32F);
bilateralFilter (mat_in_32F, mat_out_32F, 5, 160, 2);
Mat mat_out_16S = Mat (mat_in_16S.size(), mat_in_16S.type(), output);
mat_out_32F.convertTo (mat_out_16S, CV_16S);
return 0;
}
I know only C language, so I am getting confusion/not understanding the syntax of the openCV data types particularly in cv::Mat, CvMat*, Mat.
My question is How can I convert cv::Mat to const CvMat* or CvMat*, and can any one provide documentation link for difference between CvMat *mat and cv::Mat and Mat in opencv2.4.
and How can I convert my int data to float data in CvMat ?
Thank you
cv::Mat has a operator CvMat() so simple assignment works:
cv::Mat mat = ....;
CvMat cvMat = mat;
This uses the same underlying data so you have to be careful that the cv::Mat doesn't go out of scope before the CvMat.
If you need to use the CvMat in an API that takes a CvMat*, then pass the address of the object:
functionTakingCmMatptr(&cvMat);
As for the difference between cv::Mat and Mat, they are the same. In OpenCV examples, it is often assumed (and I don't think this is a good idea) that using namespace cv is used.
To answer especially surya's second question:
TBH, the documentation on OpenCV is not the best.
Here the link to the newest type: cv::Mat. The newer types are more modern c++ like than c style.
Here is more OpenCV forum answer with a similar topic and here is an archived page.
Especially for the conversion problem (as juanchopanza mentioned):
cv::Mat mat = cv::Mat(10, 10, CV_32FC1); //CV_32FC1 equals float
//(reads 32bit floating-point 1 channel)
CvMat cvMat = mat;
or with
using namespace cv; //this should be in the beginning where you include
Mat mat = Mat(10, 10, CV_32FC1);
CvMat cvMat = mat;
Note: Usually you would probably work with CvMat* - but you should think about switching to the newer types completely. Example (taken from my second link):
CvMat* A = cvCreateMat(10, 10, CV_32F); //guess this works fine with no channels too
Changing int to float:
CvMat* A = cvCreateMat(10, 10, CV_16SC1);
//Feed A with data
CvMat* B = cvCreateMat(10, 10, CV_32FC1);
for( int i=0; i<10; ++i)
for( int i=0; i<10; ++i)
CV_MAT_ELEM(*A, float, i, j) = (float) cvmGet(B, i, j);
//Don't forget this unless you want to produce a memory leak.
cvReleaseMat(&A);
cvReleaseMat(&B);
The first two examples (without the pointer) are fine like that as the CvMat is held on the heap then. cvCreateMat(...) allocates memory you have to free on your own later. Another reason to use cv::Mat.