opencv: Convert Mat to IplImage Issue - c++

In my program I have to mix the c++ and c api a bit.
I capture an image with the c api and get one frame:
CvCapture* capture = 0;
capture = cvCaptureFromCAM(0);
// some code
IplImage* image = cvQueryFrame(capture);
Then it is converted to Mat to be compatible with the new c++ api and I get a ROI:
Mat captureFrame = cvarrToMat(image);
// some code
Mat roi = captureFrame(roiRect);
At the end I have to convert the Mat back to IplImage* to work with the c api:
IplImage imgCaptureFrame = roi;
when I use this as reference &roi I get a
OpenCV Error: Assertion failed (svec[j].size == dst.size && svec[j].depth() == d
st.depth() && svec[j].channels() == 1 && i < dst.channels()) in unknown function
, file C:\slave\builds\WinInstallerMegaPack\src\opencv\modules\core\src\convert.
cpp, line 1306
in code using c api.
When I just use
IplImage imgCaptureFrame = captureFrame;
instead of
IplImage imgCaptureFrame = roi;
there isn't any error but then I don't have my roi.
What can I do to convert my roi to use it in c api?

To convert an IplImage* to cv::Mat and make an independent copy, do:
cv::Mat captureFrame = cv::Mat(image, true);
To create a ROI for captureFrame you could do something like:
cv::Rect roi;
roi.x = 165;
roi.y = 50;
roi.width = 440;
roi.height = 80;
cv::Mat cropped = new cv::Mat(captureFrame, roi);
and finally, to do the conversion the other way:
IplImage imgCaptureFrame = cropped;

Related

No suitable user-defined conversion from "cv::Mat" to "IplImage" exists

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

Image is not retrieved correctly

I want to capture an image and use it as a gray level image.
I have the following code:
CvCapture *p = cvCreateCameraCapture(0);
cvSetCaptureProperty(p, CV_CAP_PROP_FRAME_WIDTH, 1024);
cvSetCaptureProperty(p, CV_CAP_PROP_FRAME_HEIGHT, 1024);
IplImage* frame;
for (int i = 0; i < 25; i++)
{
frame = cvQueryFrame(p);
}
cvSaveImage("test.jpg", frame);
Mat r = imread("test.jpg", 1);
Mat inputImage;
cvtColor(r, inputImage, COLOR_RGB2GRAY);
In my code frame is an RGB image (three dimensions). when I read the saved image with r it has two channels.
I have two questions:
why this happens?
how can I have one dimensional image which is gray level?
For your first question: You should check which camera/hardware you are using? Also, confirm if frame has 2 channels by running:
cout << img->nChannels << endl;
For second part:
To read image as gray channel, change:
Mat r = imread("test.jpg", 1);
to
Mat r = imread("test.jpg", 0);
See this: docs

my application crashes at KNearest::find_nearest

I want to implement a OCR feature.
I have collected some samples and i want to use K-Nearest to implement it.
So, i use the below code to load data and initialize KNearest
KNearest knn = new KNearest;
Mat mData, mClass;
for (int i = 0; i <= 9; ++i)
{
Mat mImage = imread( FILENAME ); // the filename format is '%d.bmp', presenting a 15x15 image
Mat mFloat;
if (mImage.empty()) break; // if the file doesn't exist
mImage.convertTo(mFloat, CV_32FC1);
mData.push_back(mFloat.reshape(1, 1));
mClass.push_back( '0' + i );
}
knn->train(mData, mClass);
Then, i call the code to find best result
for (vector<Mat>::iterator it = charset.begin(); it != charset.end(); ++it)
{
Mat mFloat;
it->convertTo(mFloat, CV_32FC1); // 'it' presents a 15x15 gray image
float result = knn->find_nearest(mFloat.reshape(1, 1), knn->get_max_k());
}
But, my application crashes at find_nearest.
Anyone could help me?
I seemed to find the problem...
My sample image is a converted gray image by cvtColor, but my input image isn't.
After i add
cvtColor(mImage, mImage, COLOR_BGR2GRAY);
between
if (mImage.empty()) break;
mImage.convertTo(mFloat, CV_32FC1);
find_nearest() return a value and my application is fine.

OpenCV: Error when using function cvGoodFeaturesToTrack

When I call the function cvGoodFeaturesToTrack to find Harris corners I get this error:
OpenCV Error: Assertion failed (src.type() == CV_8UC1 || src.type() == CV_32FC1) in cornerEigenValsVecs, file /build/buildd/opencv-2.1.0/src/cv/cvcorner.cpp,line 254
terminate called after throwing an instance of 'cv::Exception'
what(): /build/buildd/opencv-2.1.0/src/cv/cvcorner.cpp:254: error: (-215) src.type() == CV_8UC1 || src.type() == CV_32FC1 in function cornerEigenValsVecs
Aborted
It compiles correctly but when I try to run it, it gives me that error.
Here is the code:
IplImage* eig_image = 0;
IplImage* temp_image = 0;
IplImage *img1 = 0;
img1 = cvLoadImage("im1.pgm");
if(img1==0) {
printf("oh no!");
}
eig_image = cvCreateImage(cvGetSize(img1),IPL_DEPTH_32F, 1);
temp_image = cvCreateImage(cvGetSize(img1),IPL_DEPTH_32F, 1);
const int MAX_CORNERS = 100;
CvPoint2D32f corners[MAX_CORNERS] = {0};
int corner_count = MAX_CORNERS;
double quality_level = 0.1;
double min_distance = 1;
int eig_block_size = 3;
int use_harris = true;
double k = .4;
cvGoodFeaturesToTrack(img1, eig_image, temp_image,corners,&corner_count,quality_level,min_distance,NULL,eig_block_size,use_harris,k);
Why is this happening and how can I fix it? I appreciate any help!
OpenCV is trying to tell you that one of the images you passed to cvGoodFeaturesToTrack() (the error is actually originating in the helper function cornerEigenValsVecs()) is not of the required type CV_8UC1 or CV_32FC1.
I suspect img1 may not be of the type you need it to be. What is the type of the img1 matrix? If it is color, then it may be of type CV_8UC3. Consider using cvCvtColor to make it a grayscale image.
Or, alternatively you can initially load the image as grayscale like:
cvLoadImage("im1.pgm", CV_LOAD_IMAGE_GRAYSCALE);

OpenCV running kmeans algorithm on an image

I am trying to run kmeans on a 3 channel color image, but every time I try to run the function it seems to crash with the following error:
OpenCV Error: Assertion failed (data.dims <= 2 && type == CV_32F && K > 0) in unknown function, file ..\..\..\OpenCV-2.3.0\modules\core\src\matrix.cpp, line 2271
I've included the code below with some comments to help specify what is being passed in. Any help is greatly appreciated.
// Load in an image
// Depth: 8, Channels: 3
IplImage* iplImage = cvLoadImage("C:/TestImages/rainbox_box.jpg");
// Create a matrix to the image
cv::Mat mImage = cv::Mat(iplImage);
// Create a single channel image to create our labels needed
IplImage* iplLabels = cvCreateImage(cvGetSize(iplImage), iplImage->depth, 1);
// Convert the image to grayscale
cvCvtColor(iplImage, iplLabels, CV_RGB2GRAY);
// Create the matrix for the labels
cv::Mat mLabels = cv::Mat(iplLabels);
// Create the labels
int rows = mLabels.total();
int cols = 1;
cv::Mat list(rows, cols, mLabels .type());
uchar* src;
uchar* dest = list.ptr(0);
for(int i=0; i<mLabels.size().height; i++)
{
src = mLabels.ptr(i);
memcpy(dest, src, mLabels.step);
dest += mLabels.step;
}
list.convertTo(list, CV_32F);
// Run the algorithm
cv::Mat labellist(list.size(), CV_8UC1);
cv::Mat centers(6, 1, mImage.type());
cv::TermCriteria termcrit(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0);
kmeans(mImage, 6, labellist, termcrit, 3, cv::KMEANS_PP_CENTERS, centers);
The error says all: Assertion failed (data.dims <= 2 && type == CV_32F && K > 0)
These are very simple rules to understand, the function will work only if:
mImage.depth() is CV_32F
if mImage.dims is <= 2
and if K > 0. In this case, you define K as 6.
From what you stated on the question, it seems that:
IplImage* iplImage = cvLoadImage("C:/TestImages/rainbox_box.jpg");`
is loading the image as IPL_DEPTH_8U by default and not IPL_DEPTH_32F. This means that mImage is also IPL_DEPTH_8U, which is why your code is not working.