OpenCV fillConvexPoly function in C++ throws exception - c++

I'm trying to fill a triangle in a mask using the fillConvexPoly function.
But I get the following error.
OpenCV Error: Assertion failed (points.checkVector(2, CV_32S) >= 0) in fillConvexPoly, file /home/iris/Downloads/opencv-3.1.0/modules/imgproc/src/drawing.cpp, line 2256
terminate called after throwing an instance of 'cv::Exception'
what(): /home/iris/Downloads/opencv-3.1.0/modules/imgproc/src/drawing.cpp:2256: error: (-215) points.checkVector(2, CV_32S) >= 0 in function fillConvexPoly
I call the function as like so,
cv::Mat mask = cv::Mat::zeros(r2.size(), CV_32FC3);
cv::fillConvexPoly(mask, trOutCroppedInt, cv::Scalar(1.0, 1.0, 1.0), 16, 0);
where the trOutCroppedInt defined like so,
std::vector<cv::Point> trOutCroppedInt
And I push 3 points in the vector,
[83, 46; 0, 48; 39, 0]
How should I correct this error?

When points.checkVector(2, CV_32S) >= 0) is encountered
This error may occur when the data type is more complex than CV_32S and the dimension is greater than two, for example all data type like vector<Point2f> can create the problem. As the result we can use fillConvexpoly according to the following steps:
1. Reading an Image with
cv::Mat src=cv::imread("what/ever/directory");
2. determine points
You must determine your points like in the following graphic
Thus, our code for this point is:
vector<cv::Point> point;
point.push_back(Point(163,146)); //point1
point.push_back(Point(100,148)); //point2
point.push_back(Point(100,110)); //point3
point.push_back(Point(139,110)); //point4
3.Use cv::fillConvexPoly function
Consider the image src and draw a polygon ((with the points)) on this image then code would be as follows:
cv::fillConvexPoly(src, //Image to be drawn on
point, //C-Style array of points
Scalar(255, 0, 0), //Color , BGR form
CV_AA, // connectedness, 4 or 8
0); // Bits of radius to treat as fraction
(so output image is as follows: before:left side - after:right side)

Related

OpenCV warpPerspective error : Bad number of channels

when using warpPerspective,
OpenCV Error: Bad number of channels (Source image must have 1, 3 or 4
channels) in cvConvertImage, file
/build/opencv-ys8xiq/opencv-2.4.9.1+dfsg/modules/highgui/src/utils.cpp,
line 622 terminate called after throwing an instance of
'cv::Exception' what():
/build/opencv-ys8xiq/opencv-2.4.9.1+dfsg/modules/highgui/src/utils.cpp:622:
error: (-15) Source image must have 1, 3 or 4 channels in function
cvConvertImage
But, the source image being used is 1 channel and has the desired size.
This code is basically to get the birdeye's view of an image.
cv::Mat warped;
std::vector<cv::Point2f> src ;
src.push_back(cv::Point2f(640, 470));
src.push_back(cv::Point2f(0, 470));
src.push_back(cv::Point2f(150, 250));
src.push_back(cv::Point2f(490, 250));
std::vector<cv::Point2f> dst ;
dst.push_back(cv::Point2f(640, 480));
dst.push_back(cv::Point2f(0, 480));
dst.push_back(cv::Point2f(0, 0));
dst.push_back(cv::Point2f(640, 0));
cv::Mat M = cv::getPerspectiveTransform(src,dst);
cv::warpPerspective(src, warped, M, image.size());
It was discussed in topic: https://stackoverflow.com/a/17863381
Short answer:
Use cv::perspectiveTransform or matrix multiplication for points and cv::warpPerspective for images
I hope it will help.

OpenCV: Assertion failed " dst.data == widget->original_image->data.ptr in function 'cvImageWidgetSetImage' "

IMPORTANT: I fixed the problem. Solution at the end.
What do I try to achieve?
Display an image with OpenCV cv::imshow method. (imshow Documentation)
The image which is a 3x3 matrix is created like such:
Mat mask(3, 3, CV_32F, new float[9]{0, 1, 0, 1, -4, 1, 0, 1, 0});
To display the image I call imshow("mask", mask);
What is my problem?
Like I mentioned in the title there is an exception thrown while trying to display the image. Complete Error Message:
terminate called after throwing an instance of 'cv::Exception' what():
OpenCV(4.0.0-pre) /home/mrlab/Libraries/opencv_source/modules/highgui
/src/window_gtk.cpp:146: error: (-215:Assertion failed)
dst.data == widget->original_image->data.ptr in function 'cvImageWidgetSetImage'
Link to window_gtk.cpp
What did I already try?
Looking for the error on the internet. Maybe someone else already encountered the same problem. nope. nothing
Changed the matrix to only contain positive floating point values (0 to 1) in case it has problems with negative input. Initialization: Mat mask(3, 3, CV_32F, new float[9]{0, 1, 0, 1, 0, 1, 0, 1, 0}); same error
Calling the two methods in different locations in case there are changes made during my other code. same error
Writing small OpenCV program to just run these two lines. same error
Various combinations of the above mentioned ideas. same error
Displaying other images I read from memory instead of creating them myself. worked perfectly fine
Saving the image via imwrite("mask.png", mask) Looks like
this. Pretty small I know. I scaled the values to be in range of 0 to 255 since that what png needs. works perfectly fine
Complete code around my corrupted lines:
void high_pass(){
Mat src_f;
// Fourier transform src_bw
src_f = fourier(src_bw);
// Create Laplace High Pass Kernel
Mat mask(3, 3, CV_32F, new float[9]{0, 1, 0, 1, -4, 1, 0, 1, 0});
// In case of using fp values (0 to 1) initialize like this:
// Mat mask(3, 3, CV_32F, new float[9]{0, 1, 0, 1, 0, 1, 0, 1, 0});
imshow("mask", mask);
// Fourier transform kernel
Mat mask_f = fourier_kernel(mask, src_f.size());
Mat hp_filtered;
// Apply filter
mulSpectrums(src_f, mask_f, hp_filtered, DFT_ROWS);
// Transform it back
dst = fourier_inv(hp_filtered);
// Swap quadrants after applying filter
dst = swap_quadrants(dst);
// Show result
//imshow(WINDOW_NAME + "high pass", dst);
}
FYI: The last line threw the same exception which is why it is commented out. I ask the question with "mask" because it is easier.
After writing the question I had another idea.
Solution: I converted the CV_32F type matrix to a CV_8U matrix and scaled all values to be in range of 0 to 255. This solved the problem.
This is something I should have thought of first. For some reason it took me one hour to realize. Just in case someone else is encountering the same error or mental block I still post this here.
Solution: I converted the CV_32F type matrix to a CV_8U matrix and scaled all values to be in range of 0 to 255. This solved the problem.
Edit: As stated by Nikolaj Fogh it is also possible to revert to OpenCV Version 3.4.3. I did not test it myself.
For completeness, this is how to implement Philipp's solution (using his program's variables):
cv::Mat dist_8U; // to store the scaled image with appropriate type
double Min,Max;
cv::minMaxLoc(rgb,&Min,&Max);
dist -= Min;
dist.convertTo(dist_8U,CV_8U,255.0/(Max-Min));
Then dist_8U can be shown with imshow in opencv 4.0.0.
Tested on a raspberry pi.

Why does attempt in calculating a histogram and back projection not work?

I am attempting to calculate a histogram of a ROI in order to find that ROI in an image using back projection. My code is
cvtColor(frame, hsvFrame, CV_BGR2HSV);
cvtColor(ROI, hsvROI, CV_BGR2HSV);
float hRanges[] = {0, 180};
float sRanges[] = {0, 256};
float vRanges[] = {0, 256};
const float* ranges[] = { hRanges, sRanges, vRanges};
int histSize = 256;
int channels[] = {0,1,2};
calcHist(&hsvROI, 1, channels, Mat(), ROIhist, 3, &histSize, ranges);
calcBackProject(&hsvFrame, 1, channels, ROIhist, backProj, ranges, true);
imshow("display", backProj);
Firstly, please assume all Mats have already been declared (this is only a snippet). In my understanding, the more dimensions/channels I use the more accurate the back projection should be...so i have decided to include all 3 channels of an HSV row, and therefore of course an HSV image (is this necessary? is there a better way?). In this example above, i get the error:
OpenCV Error: Assertion failed (s >= 0) in setSize, file opencv/modules/core/src/matrix.cpp, line 293
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: opencv/modules/core/src/matrix.cpp:293: error: (-215) s >= 0 in function setSize
which gets triggered on the CalcHist line. My solution was to make sure ROIhist is of the same size as hsvROI, so I then put this line just before I declare the ranges:
Mat ROIhist(hsvROI.rows,hsvROI.cols, CV_8UC3, Scalar(0,0,0));
I think it worked, as on the next run, i got a different error that was triggered on the CalcBackProject line:
OpenCV Error: Assertion failed (dims > 0 && !hist.empty()) in calcBackProject, file /opencv/modules/imgproc/src/histogram.cpp, line 1887
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: opencv/modules/imgproc/src/histogram.cpp:1887: error: (-215) dims > 0 && !hist.empty() in function calcBackProject
Which i really do not understand. In fact I also feel like my previous fix by adding the Mat constructor shouldn't be necessary anyway...?
I essentially need to be able to calculate this back projection as accurately as possible while using both functions in ideally a rather simple and standard way. My attempt clearly has some logic flaw somewhere and I would appreciate an explanation or suggestion to how i should go about this properly to get the best results. Thanks in advance !
histSize in your case should be the number of bins in your 3D histogram (so an int array, not just an int). And I'd use lower numbers for them, so that more pixels would manage to fall into one bin, and would make your backprojection more meaningful:
int histSize[] = {32, 32, 32};
...
calcHist(&hsvROI, 1, channels, Mat(), ROIhist, 3, histSize, ranges);

What does Mat::checkVector do in OpenCV?

I tried to use the following function in OpenCV (C++)
calcOpticalFlowPyrLK(prev_frame_gray, frame_gray, points[0], points[1], status, err, winSize, 3, termcrit, 0, 0.001);
and I get this error
OpenCV Error: Assertion failed ((npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0) in calcOpticalFlowPyrLK,
file /home/rohit/OpenCV_src/opencv-2.4.9/modules/video/src/lkpyramid.cpp, line 845
terminate called after throwing an instance of 'cv::Exception'
what(): /home/rohit/OpenCV_src/opencv-2.4.9/modules/video/src/lkpyramid.cpp:845:
error: (-215) (npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0 in function calcOpticalFlowPyrLK
Both of the following return -1
frame_gray.checkVector(2, CV_32F, true)
prev_frame_gray.checkVector(2, CV_32F, true)
I wanted to know what checkVector actually does because it is leading to the assertion error as you can see above.
The official OpenCV's doc says:
cv::Mat::checkVector() returns N if the matrix is 1-channel (N x
ptdim) or ptdim-channel (1 x N) or (N x 1); negative number otherwise
OpenCV considers some data types equivalent in case of some functions i.e. objectPoints of cv::solvePnP() can be:
1xN/Nx1 1-channel cv::Mat
3xN/Nx3 3-channel cv::Mat
std::vector<cv::Point3f>
With checkVector you can make sure that you are passing the correct representation of your data.
I had a similar issue with cv2.projectPoints function (-215:Assertion failed) because openCV was expecting a nx3 matrix and i was passing an 1D array of length 3. Try:
points[0].reshape(-1,3)
As argument to the function. It changes the shape (3,) to shape (1,3).

convert vector of points to Mat (OpenCV )

my question is very similar to this one... I'm trying to extract a sub matrix from a grayscale image wich is a polygon by 5 points , and convert it to a Mat.
This does not work:
std::vector<Point> vert(5);
vert.push_back(pt1);
vert.push_back(pt2);
vert.push_back(pt3);
vert.push_back(pt4);
vert.push_back(pt5);
Mat matROI = Mat(vert);
It shows me the following error message:
OpenCV Error: Bad number of channels (Source image must have 1, 3 or 4 channels) in cvConvertImage, file /home/user/opencv-2.4.6.1/modules/highgui/src/utils.cpp, line 611
terminate called after throwing an instance of 'cv::Exception'
what(): /home/user/opencv-2.4.6.1/modules/highgui/src/utils.cpp:611: error: (-15) Source image must have 1, 3 or 4 channels in function cvConvertImage
I'm using OpenCV 2.4.6.1 and C++.
Thank you
Edit:
I will rephrase my question: my objective is to obtain the right side of the image.
I thought I'd see the image as a polygon because I have the coordinates of the vertices, and then transform the vector that has the vertices in a matrix (cvMat).
My thought is correct or is there a simpler way to get this submatrix?
Your code has two problems:
First:
std::vector<Point> vert(5);
creates a vector initially with 5 points, so after you use push_back() 5 times you have a vector of 10 points, the first 5 of of which are (0, 0).
Second:
Mat matROI = Mat(vert);
creates a 10x1 Mat (from a vector of 10 points) with TWO channels. Check that with:
cout << "matROI.channels()=" << matROI.channels() << endl;
If you have a code like:
imshow("Window", matROI);
it will pass matROI through to cvConvertImage() which has the following code (and this causes the error you are seeing):
if( src_cn != 1 && src_cn != 3 && src_cn != 4 )
CV_ERROR( CV_BadNumChannels, "Source image must have 1, 3 or 4 channels" );
Since matROI is a list of points, it doesn't make sense to pass it to imshow().
Instead, try this:
Mat img(image.rows, image.cols, CV_8UC1);
polylines(img, vert, true, Scalar(255)); // or perhaps 0
imshow("Window", img);
int c = waitKey(0);