In opencv2.4.10 which I used before, conversion from CvMat* to cv::Mat can be done as below.
CvMat *src = ...;
cv::Mat dst;
dst = cv::Mat(src);
However, in opencv3.0 rc1 cannot convert like this.
In certain website, this conversion can be done as below.
CvMat* src = ...;
cv::Mat dst;
dst = cv::Mat(src->rows, src->cols, src->type, src->data.*);
If type of src is 'float', the last argument is 'src->data.fl'.
Why constructor of cv::Mat is decreased?
Or are there some methods about conversion from CvMat* to cv::Mat?
CvMat* matrix;
Mat M0 = cvarrToMat(matrix);
OpenCV provided this function instead of Mat(matrix).
Note: In OpenCV 3.0 they wrapped up all the constructors which convert old-style structures (cvmat, IPLImage) to the new-style Mat into this function.
In order to convert CvMat* to Mat you have to do like this:
cv::Mat dst(src->rows, src->cols, CV_64FC1, src->data.fl);
Related
I am traying to convert a cv::Mat to IplImage in pc with this caracteristcs:
opencv: 3.4.14
OS: Win 10
code: c++
An example of the differents options:
cv::Mat MBin = cv::Mat::zeros(cv::Size(64, 64), CV_32FC1);
IplImage* image0= new IplImage(MBin);
IplImage image1 = MBin;
IplImage* image2 = cvCloneImage(&(IplImage)MBin);
IplImage* image3;
image3 = cvCreateImage(cvSize(MBin.cols, MBin.rows), 8, 3);
IplImage image4 = MBin;
cvCopy(&image4, image3);
Where imageX appears produces the title error.
This is the only solution, which doesn't generate compiler error:
#include <opencv2/core/types_c.h>
Mat Img = imread("1.jpg");
IplImage IBin_2 = cvIplImage(MBin);
IplImage* IBin = &IBin_2;
Before opencv3.x, Mat has a constructor Mat(const IplImage* img, bool copyData=false);. But in opencv3.x, Mat(const IplImage* img, bool copyData=false); constructor is canceled.
So, you could refer to the following example to convert Mat to IplImage.
//Mat—>IplImage
//EXAMPLE:
//shallow copy:
Mat Img=imread("1.jpg");
IplImage* pBinary = &IplImage(Img);
//For a deep copy, just add another copy of the data:
IplImage *input = cvCloneImage(pBinary)
Also, you could refer to this link for more information.
//opencv 4.5.2
IplImage* IplImage_img = cvCreateImage(cvSize(img.cols, img.rows), 8, 1);
cv::Mat MatImg(img.rows, img.cols, CV_8U, cv::Scalar(0));
MatImg = cv::cvarrToMat(IplImage_img);
img.copyTo(MatImg);
I have to transform QImage to cv::Mat, if I use technique described in similar topics, I receive different numbers of contours (7--8) and strange result matrix, but if I do
QImage im;
im.save ("tmp.bmp");
cv::Mat rImage;
rImage = cv::imread ("tmp.bmp", CV_LOAD_IMAGE_GRAYSCALE);
function findContours works fine and properly. What is the difference between these techniques and which way I can archive equal results between these approaches ?
Your code works for me.
int main(int argc, char *argv[]){
QImage img(QString("lena.bmp"));
QImage img2 = img.convertToFormat(QImage::Format_RGB32);
cv::Mat imageMat = qimage_to_cvmat_copy(img2, CV_8UC4);
cv::namedWindow("lena");
cv::imshow("lena", imageMat);
cv::waitKey(0);
}
cv::Mat qimage_to_cvmat_copy(const QImage &img, int format)
{
uchar* b = const_cast<uchar*> (img.bits ());
int c = img.bytesPerLine();
return cv::Mat(img.height(), img.width(), format, b, c).clone();
}
Make sure your Mat format is CV_8UC4 if your QImage format is Format_RGB32. You don't have to do a cvtColor or mixChannels.
All !
As mentioned above I used conversion QImage to cv::Mat as described here. My source code became something like this
QImage srcIm (argv[1]);
QImage img2 = srcIm.convertToFormat(QImage::Format_ARGB32);
Mat src_gray = QImageToCvMat (img2);
cvtColor (src_gray, src_gray1, CV_RGB2GRAY);
Mat bwimg = src_gray1.clone();// > 127;
vector<vector<Point> > contours;
findContours( bwimg, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE );
All works fine.
i have searched a lot on the internet but i have only found how to convert Qimage to RGB format, i want to convert an Qimage to cv mat format CV_64FC3.
i have really bad results when i work with CV_8UC3
here is my code :
QImage myImage;
myImage.load("C://images//PolarImage300915163358.bmp");
QLabel myLabel;
myLabel.setPixmap(QPixmap::fromImage(myImage));
//myLabel.show();
cv::Mat image1 = QImage2Mat(myImage);
Mat img;
image1.convertTo(img, CV_64FC3, 1.0 / 255.0);
and here is the function that i used :
cv::Mat QImage2Mat(QImage const& src)
{
cv::Mat tmp(src.height(),src.width(),CV_8UC3,(uchar*)src.bits(),src.bytesPerLine());
cv::Mat result; // deep copy just in case (my lack of knowledge with open cv)
cvtColor(tmp, result,CV_BGR2RGB);
return result;
}
please help me i m new to both opencv and Qt
Not sure what you mean with bad results, but you are assuming that QImage also loads the image as OpenCV (BGR). In the documentation it tells you that they use ARGB.
So, knowing this you have 2 options:
Convert to QImage::Format_RGB888 the Qimage using the function convertToFormat and then this line cvtColor(tmp, result,CV_BGR2RGB); is not needed, since it will be already in RGB.
Use CV_8UC4 when creating the cv::Mat and then drop the first channel (channel alpha) using either split and join or mixchannels.
i have found what was going wrong, in fact, Qimage has a fourth channel for alpha so when you read the Qimage data you need to put it in CV_8UC4
here is the code :
Mat QImage2Mat(const QImage& src) {
cv::Mat mat = cv::Mat(src.height(), src.width(), CV_8UC4, (uchar*)src.bits(), src.bytesPerLine());
cv::Mat result = cv::Mat(mat.rows, mat.cols, CV_8UC3 );
int from_to[] = { 0,0, 1,1, 2,2 };
cv::mixChannels( &mat, 1, &result, 1, from_to, 3 );
return result;
}
I have gray Mat (image). I wanna create color image the same size as gray image:
With Visual C++ Express it compiled:
Mat dst = cvCreateImage(gray.size(), 8, 3);
but with GCC compiler is error:
threshold.cpp|462|error: conversion from ‘IplImage* {aka _IplImage*}’ to non-scalar type ‘cv::Mat’ requested|
I change to cvCreateMat
Mat dst = cvCreateMat(gray.rows, gray.cols, CV_8UC3);
but GCC still:
threshold.cpp|462|error: conversion from ‘CvMat*’ to non-scalar type ‘cv::Mat’ requested|
Is method create directly Mat or is any conversion?
cvCreateImage(gray.size(), 8, 3);
is from the old , deprecated c-api. don't use it (it's actually creating an IplImage*).
construct a cv::Mat like this:
Mat dst(gray.size(), CV_8UC3); // 3 uchar channels
note, that you will never have to pre-allocate anything for result images,
so, if i.e. you want to do a threshold operation, it's just:
Mat gray = ....;
Mat thresh; // intentionally left empty!
threshold( gray,thresh, 128,255,0);
// .. go on working with thresh. no need to release it either.
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.