Unsupported depth in Opencv - c++

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

Related

How to copy a rectangular area of a Mat a new Mat of the same size?

How can I save an area of one image in a new image with the same size as the first image?
For example if I had an image like this:
I want to create another image like this:
This is what I tried:
#include <opencv2/opencv.hpp>
#include "iostream"
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("1.png");
Mat dst;
src(Rect(85, 45, 100, 100)).copyTo(dst);
imshow("tmask", dst);
waitKey(0);
return 0;
}
But the result will be like this:
which is not what I wanted.
It is necessary for the program to not initialize the size of Mat dst for reasons that are too long to write here.
How can I generate the second image above (dst) without initializing the size of it?
create a new image and copy the subimage to roi
cv:: Mat img = cv::imread(...);
cv::Rect roi(x,y,w,h);
cv::Mat subimage= img(roi); // embedded
cv::Mat subimageCopied = subimage.clone(); // copied
cv::Mat newImage=cv::Mat::zeros(img.size(), img.type);
img(roi).copyTo(newImage(roi)); // this line is what you want.
If you have access to the original image, but are not allowed to use its siute information, you can use .copyTo with a mask, but then you have to use the size information to create the mask...

c++, opencv: Is it safe to use the same Mat for both source and destination images in filtering operation?

Filtering operations involve convolutions and the filtered value at position (x,y) will also depend on the intensities of pixels (x-a,y-b) with a,b >0.
So using directly as destination the same image will lead to unexpected behaviors because during calculation I'm taking some already-filtered data instead of original ones.
Question
Does opencv manage this issue internally in functions like cv::GaussianBlur(.) , cv::blur, etc? Is it safe to give a reference to the same Mat to both src and dst parameters?
thanks
Yes, there would not be any problem if you do so. I have done such thing several time. openCV will automatically take care of it.
I tested the following code and it works perfect:
int main(int argc, char* argv[])
{
Mat src;
src = imread("myImage.jpeg", 1);
imshow("src", src); //Original src
cv::blur( src, src, Size(25,25) , Point(-1,-1), BORDER_DEFAULT );
imshow("dst", src); //src after blurring
waitKey(0);
}

how to convert from a two dimensional array to a graylevel image in opencv?

I am using openCV in my c++ image processing project.
I have this two dimensional array I[800][600] filled with values between 0 and 255, and i want to put this array in a graylevel "IplImage" so i can view it and process it using openCV functions.
Any help will be appreciated.
Thanks in advance.
It's easy in Opencv C++ interface, all you need to do is to init a matrice, see the line below
cv::Mat img = cv::Mat(800, 600, CV_8UC1, I) // I[800][600]
Now you can do whatever you want, Opencv treats img as an 8-bit grayscale image.
CvSize image_size;
image_size.height = 800;
image_size.width = 600;
int channels = 1;
IplImage *image = cvCreateImageHeader(image_size, IPL_DEPTH_8U, channels);
cvSetData(image, I, image->widthStep)
this is untested, but the most important thing likely to require fixing is the second parameter to cvSetData(). This needs to be a pointer to unsigned character data, and if you're just using a 2D array that isn't part of a Mat, then you'll have to do something a bit different, (possibly a loop? although you should avoid loops in openCV as much as possible).
see this post for a highly relevant question

(Adaptive) thresholding in opencv error (Bad argument (Unknown array type) in cvarrToMat)

I'm trying to use thresholding on my video stream but it is not working.
My video stream:
Mat *depthImage = new Mat(480, 640, CV_8UC1, Scalar::all(0));
Then i try to do the adaptive thresholding, (also doesn't work with regular thresholding)
for(;;){
if( wrapper->update()){
wrapper->getDisplayDepth(depthImage);
cvAdaptiveThreshold(depthImage, depthImage,255,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,75,10);
imshow("Depth", *depthImage);
}
int k = waitKey(25);
if(k == 27 ) exit(0);
}
I get this error :
OpenCV Error: Bad argument (Unknown array type) in cvarrToMat, file /Users/olivierjanssens/source/OpenCV-2.3.1/modules/core/src/matrix.cpp, line 646
terminate called throwing an exception
What am i doing wrong, i can get display and see the stream perfectly.But when i add this thresholding i get the error previously mentioned. (i'm rather new to opencv btw).
Thx in advance !
Your depthImage is a pointer to a cv::Mat, which to me seems strange...
...but, if you're using the C++ syntax then you'll want to use the C++ version of adaptiveThreshold, which deals with cv::Mat, with the following definition:
void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue,
int adaptiveMethod, int thresholdType, int blockSize, double C);
which will need prefixed by cv:: if you're not using that namespace already.
For example:
Mat *depthImage; // Obtain this using your method
Mat image = *depthImage; // Obtain a regular Mat to use (doesn't copy data, just headers)
adaptiveThreshold(image, image,255,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,75,10);
imshow("Depth Image", *depthImage);
// OR
imshow("Depth Image", image);

Converting cv::Mat to IplImage*

The documentation on this seems incredibly spotty.
I've basically got an empty array of IplImage*s (IplImage** imageArray) and I'm calling a function to import an array of cv::Mats - I want to convert my cv::Mat into an IplImage* so I can copy it into the array.
Currently I'm trying this:
while(loop over cv::Mat array)
{
IplImage* xyz = &(IplImage(array[i]));
cvCopy(iplimagearray[i], xyz);
}
Which generates a segfault.
Also trying:
while(loop over cv::Mat array)
{
IplImage* xyz;
xyz = &array[i];
cvCopy(iplimagearray[i], xyz);
}
Which gives me a compile time error of:
error: cannot convert ‘cv::Mat*’ to ‘IplImage*’ in assignment
Stuck as to how I can go further and would appreciate some advice :)
cv::Mat is the new type introduce in OpenCV2.X while the IplImage* is the "legacy" image structure.
Although, cv::Mat does support the usage of IplImage in the constructor parameters, the default library does not provide function for the other way. You will need to extract the image header information manually. (Do remember that you need to allocate the IplImage structure, which is lack in your example).
Mat image1;
IplImage* image2=cvCloneImage(&(IplImage)image1);
Guess this will do the job.
Edit: If you face compilation errors, try this way:
cv::Mat image1;
IplImage* image2;
image2 = cvCreateImage(cvSize(image1.cols,image1.rows),8,3);
IplImage ipltemp=image1;
cvCopy(&ipltemp,image2);
(you have cv::Mat old)
IplImage copy = old;
IplImage* new_image = ©
you work with new as an originally declared IplImage*.
Here is the recent fix for dlib users link
cv::Mat img = ...
IplImage iplImage = cvIplImage(img);
Personaly I think it's not the problem caused by type casting but a buffer overflow problem; it is this line
cvCopy(iplimagearray[i], xyz);
that I think will cause segment fault, I suggest that you confirm the array iplimagearray[i] have enough size of buffer to receive copyed data
According to OpenCV cheat-sheet this can be done as follows:
IplImage* oldC0 = cvCreateImage(cvSize(320,240),16,1);
Mat newC = cvarrToMat(oldC0);
The cv::cvarrToMat function takes care of the conversion issues.
In case of gray image, I am using this function and it works fine! however you must take care about the function features ;)
CvMat * src= cvCreateMat(300,300,CV_32FC1);
IplImage *dist= cvCreateImage(cvGetSize(dist),IPL_DEPTH_32F,3);
cvConvertScale(src, dist, 1, 0);
One problem might be: when using external ipl and defining HAVE_IPL in your project, the ctor
_IplImage::_IplImage(const cv::Mat& m)
{
CV_Assert( m.dims <= 2 );
cvInitImageHeader(this, m.size(), cvIplDepth(m.flags), m.channels());
cvSetData(this, m.data, (int)m.step[0]);
}
found in ../OpenCV/modules/core/src/matrix.cpp is not used/instanciated and conversion fails.
You may reimplement it in a way similar to :
IplImage& FromMat(IplImage& img, const cv::Mat& m)
{
CV_Assert(m.dims <= 2);
cvInitImageHeader(&img, m.size(), cvIplDepth(m.flags), m.channels());
cvSetData(&img, m.data, (int)m.step[0]);
return img;
}
IplImage img;
FromMat(img,myMat);