I'm currently trying to correct the perspective of a random taken image showing a rectangle.
The perspective correction is working fine, but i want to crop the image to the target, too. Si I've tried to transform the given contour of my target by the perspective matrix (cv::Mat) and crop it with the results.
My method is currently crashing at the marked line with the following error.
OpenCV Error: Assertion failed (mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0)) in create, file /Volumes/build-storage/build/master_iOS-mac/opencv/modules/core/src/matrix.cpp, line 2430
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /Volumes/build-storage/build/master_iOS-mac/opencv/modules/core/src/matrix.cpp:2430: error: (-215) mtype == type0 || (CV_MAT_CN(mtype) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) in function create
Code
cv::Mat correctMat(cv::Mat mat, std::vector<cv::Point> contour) {
double minObjectSize = 100.0;
if (contour.size() == 4) {
cv::Rect rect = cv::boundingRect(contour);
if (rect.height < minObjectSize || rect.width < minObjectSize) {
NSLog(#"Objects size was too small: %d * %d", rect.width, rect.height);
}
else {
std::vector<Point2f> quad_pts;
std::vector<Point2f> squre_pts;
quad_pts.push_back(Point2f(contour[0].x, contour[0].y));
quad_pts.push_back(Point2f(contour[1].x, contour[1].y));
quad_pts.push_back(Point2f(contour[3].x, contour[3].y));
quad_pts.push_back(Point2f(contour[2].x, contour[2].y));
squre_pts.push_back(Point2f(rect.x, rect.y));
squre_pts.push_back(Point2f(rect.x, rect.y + rect.height));
squre_pts.push_back(Point2f(rect.x + rect.width, rect.y));
squre_pts.push_back(Point2f(rect.x + rect.width, rect.y + rect.height));
Mat transmtx = getPerspectiveTransform(quad_pts, squre_pts);
Mat transformed = Mat::zeros(mat.rows, mat.cols, CV_8UC3);
cv::line(mat, quad_pts[0], quad_pts[1], Scalar(0,0,255), 5, CV_AA, 0);
cv::line(mat, quad_pts[1], quad_pts[2], Scalar(0,0,255), 5, CV_AA, 0);
cv::line(mat, quad_pts[2], quad_pts[3], Scalar(0,0,255), 5, CV_AA, 0);
cv::line(mat, quad_pts[3], quad_pts[0], Scalar(0,0,255), 5, CV_AA, 0);
warpPerspective(mat, transformed, transmtx, mat.size());
std::vector<cv::Point2f> transformedPoints;
cv::Matx23f matrix = *transmtx.clone().ptr();
cv::transform(quad_pts, transformedPoints, matrix);
cv::Mat cropped = transformed(cv::boundingRect(transformedPoints));
fixColorOfMat(cropped);
return cropped;
}
}
return mat;
}
I do not really know what the error message is telling me so i hope somebody here could help me solving this crash.
Next Problem
I've changed the code a bit, the transform action on the point vector works now, but i'm unabled to crop the Mat by these transformed points.
std::vector<cv::Point2f> transformedPoints;
cv::Matx23f matrix = *transmtx.clone().ptr();
cv::transform(quad_pts, transformedPoints, matrix);
// Crash
cv::Mat cropped = transformed(cv::boundingRect(transformedPoints));
The error message says
OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in Mat, file /Volumes/build-storage/build/master_iOS-mac/opencv/modules/core/src/matrix.cpp, line 522
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /Volumes/build-storage/build/master_iOS-mac/opencv/modules/core/src/matrix.cpp:522: error: (-215) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows in function Mat
Hmm, I used memcpy() convert vector to Mat directly. Maybe you can try that on the transform part.
memcpy(Mat.data, vector.data(), vector.size()*sizeof(Point));
As long as you got the mask matrix of contour, I think you can use bitwise() to corp your target result.
Btw, I cannot explain opencv's error statement, as I have never understood it.
Related
I am trying to create an ROI above the face detected to place a hat like shown in the image: Plz click here : ROI created above face to place a hat
I have made sure that the ROI created is withing the bounds of the image. It looks like this:
// Create an ROI
// where face is the detected face ROI
if (0<=face.x && 0<=face.x-face.width*0.08<=image.cols && 0<=face.x+face.width+face.width*0.08<=image.cols
&& 0<=face.y && 0<=face.y-face.height*0.28<=image.rows)
{
Mat ROI_hat = image(Rect(abs(face.x-face.width*0.08),abs(face.y-face.height*0.28),abs(face.x+face.width+face.width*0.08),abs(face.y)));
rectangle(image,Point(abs(face.x-face.width*0.08),abs(face.y-face.height*0.28)),Point(abs(face.x+face.width+face.width*0.08),abs(face.y)),Scalar(255, 0, 0), 1, 4);
cout<<"Within the bounds of Image"<<endl;
}
else{
cout<<" Out of bounds of Image "<<endl;
}
There are no negative values and for every frame it says ROI is withing the bounds. But I still get assertion error:
OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in Mat, file /home/user/OpenCV_Installed/opencv-3.2.0/modules/core/src/matrix.cpp, line 522 terminate called after throwing an instance of 'cv::Exception' what(): /home/user/OpenCV_Installed/opencv-3.2.0/modules/core/src/matrix.cpp:522: error: (-215) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows in function Mat Aborted (core dumped)
Can someone please tell me where I'm going wrong?
The error means that your ROI is outside of the image, so your conditions are wrong.
Since it's pretty easy to get confused, I usually apply this small trick that is based on the intersection of the roi with a dummy roi roiImg that contains all the image:
Rect roiImg(0, 0, image.cols, image.rows);
Rect roi = ... // Very complex way of setting up the ROI
if( (roi.area() > 0) && ((roiImg & roi).area() == roi.area()) ) {
// roi is inside the image, and is non-empty
// VALID roi
} else {
// roi is at least partially outside of the image, or it's empty
// INVALID roi
}
I am coding in C++ and am trying to resize image 2 to the same dimensions as image 1, however I don't want to stretch the image. I am trying to copy image2 to the padded matrix (at the point 0,0). Am getting the error:
OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in Mat, file C:\opencv\opencv\modules\core\src\matrix.cpp, line 323
Code is below. Thanks in advance
Mat padded;
padded.setTo(cv::Scalar::all(0));
padded.create(image1.rows,image1.cols, image2.type());
image2.copyTo(padded(Rect(0, 0, image2.rows, image2.cols)));
You can use the OpenCV function copyMakeBorder to pad an image:
To achieve what you want, you can try the following:
cv::Mat padded;
//Assuming that dimensions of image1 are larger than that of image2
//Calculate padding amount so that total size after padding is equal to image1's size
int rowPadding = image1.rows - image2.rows;
int colPadding = image1.cols - image2.cols;
cv::copyMakeBorder(image2, padded, 0, rowPadding, 0, colPadding, cv::BORDER_CONSTANT, cv::Scalar::all(0));
It is almost the same as I asked before. As for you exmple, you just swap cols and rows in function call as berak already mentioned above.
Method copyMakeBorder(...) exists both for Mat and oclMat, so it could be usefull if you will try openCL-extension of openCV for better perfomance.
I don't know the syntax, but here's a pseudo-code
float width1, height1; //size of image1
float width2, height2; //original size of image2
float scale;
bool portrait = width2 < height2;
if(portrait) scale = height1 / height2;
else scale = width1 / width2;
float scaled_width2 = width2 * scale;
float scaled_height2 = height2 * scale;
When the image is portrait, we fill height, otherwise we fill the width.
By doing it this way, the image will get to its maximum size without being stretched
I am working on application for finding face in 2D image and later inside same image I want to find mouth, but I have some problem right now. This is my code so far:
for (int i = 0; i < faces.size(); i++)
{
Point pt1(faces[i].x, faces[i].y);
Point pt2((faces[i].x + faces[i].height), (faces[i].y + faces[i].width));
rectangle(frame, pt1, pt2, Scalar(255,0 , 0), 2, 8, 0);
//I WANT ROI(FOR MOUTH DETECTION) TO BE ONLY HALF OF THE RECTANGLE WITH FACE
Rect mouthROI;
mouthROI.x = (faces[i].x);
mouthROI.y = faces[i].y*(1.5);
mouthROI.width = (faces[i].x + faces[i].height);
mouthROI.height = (faces[i].y + faces[i].width);
//I CHECK IF NEW RECTANGLE IS EXACTLY BOTTOM HALF OF PREVIOUS ONE
Point ptAA(mouthROI.x, mouthROI.y);
Point ptBB(mouthROI.width, mouthROI.height);
rectangle(frame, ptBB, ptAA, Scalar(0,0 , 255), 2, 2, 0);
Mat image_roi = frame(mouthROI);
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist( frame_gray, frame_gray );
// DETECTING MOUTH INSIDE ROI OF EARLIER DETECTED FACE
mouth_cascade.detectMultiScale(image_roi, mouths, 1.1, 2, 0, Size(30, 30));
for(int i = 0; i < mouths.size(); i++)
{
Point pt1(mouths[i].x, mouths[i].y); // Display detected faces on main window - live stream from camera
Point pt2((mouths[i].x + mouths[i].height), (mouths[i].y + mouths[i].width));
rectangle(frame, pt1, pt2, Scalar(0, 255, 0), 2, 8, 0);
}
}
Unfortunately this code does not work. I get error like this:
OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in cv::Mat::Mat(const cv::Mat&, const cv::Rect&), file C:/build/2_4_PackSlave-win32-vc11-shared/opencv/modules/core/src/matrix.cpp, line 323
How can I fix this error. Thank You all for help!
The way you have initialized mouthROI is incorrect. It should be like this instead,
<previous code>
mouthROI.width = (faces[i].height);
mouthROI.height = (faces[i].width);
Point ptAA(mouthROI.x, mouthROI.y);
Point ptBB(mouthROI.x+mouthROI.width, mouthROI.y+mouthROI.height);
Remember that cv::Rect doesn't take the position of the rectangle, it takes the position of the upper left corner and the width and the height.. Refer to the documentation for further details.
HTH
This question is similar, but never was answered: OpenCV filtering part of an image
I'm using opencv2 and c++. I have a Mat, say 300x200, and I want to blur only the area in the rectangle with top-left = 50,50 size=100,50. I've been wading through the example and docs on opencv.org, but I cannot determine how to filter, or perform other operations on only a sub-rect from a Mat.
Code in question is below, where surf is an SDL_Surface and rect is an SDL_Rect (int x,y,w,h). The line with the creation of Mat src_mat from the surface is fine as it works well elsewhere. This compiles, but gives the following error.
{ // Extra scoping used for the surface_lock.
using namespace cv;
surface_lock surf_lock(surf);
//int rows, int cols, int type, void* data, size_t step=AUTO_STEP
Mat src_mat = Mat(surf->h, surf->w, CV_8UC4, src->pixels, Mat::AUTO_STEP);
Mat cropmat(src_mat, Rect(rect.y, rect.y + rect.h, rect.x, rect.x + rect.w));
blur(crop_mat, crop_mat, Size((depth + 1), (depth + 1)), Point(-1,-1));
}
error:
OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in Mat, file /build/opencv/src/opencv-2.4.6.1/modules/core/src/matrix.cpp, line 323
terminate called after throwing an instance of 'cv::Exception'
what(): /build/opencv/src/opencv-2.4.6.1/modules/core/src/matrix.cpp:323: error: (-215) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows in function Mat
a subrect is a Mat, too.
Mat larger;
Mat roi(larger, Rect(50,50,100,50));
// apply whatever algo on 'roi'
blur( roi,roi, cv::Size(5,5) );
I have a Student class and an imagehandler class (which as the opencv image handler)
Student object has a field:
imagehandler img;
and in the imagehandler class there is a function to copy image from one image to another into a certain location.
void imagehandler::copy_paste_image(imagehandler& dst, int xLoc, int yLoc){
cv::Rect roi(xLoc, yLoc, m_image.size().width, m_image.size().height);
cv::Mat imageROI (dst.m_image, roi);
m_image.copyTo(imageROI);
}
and the imagehandler class has a Mat object m_image:
private:
cv::Mat m_image;
Now in the main, I have declared a new image through the imagehandler specified constructor.
the constructor I use to make the image:
imagehandler::imagehandler(int width, int height)
: m_image(width, height, CV_8UC3){
}
in the main, I declare the image like this:
imagehandler CSImg((4*300), (320 * ceil((float)(numOfCSStudents/4))));
Trust me on this one: CSImg is way bigger than all of the images I want to input in it.
Now I want to copy a certain student's picture and input it into CS Img. That's what I do:
studentsVector.at(i)->getImg().copy_paste_image(CSImg, CSWidthCount*300, CSHeightCount*320);
And I get this error:
OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows) in Mat, file /build/buildd/opencv-2.3.1/modules/core/src/matrix.cpp, line 303
terminate called after throwing an instance of 'cv::Exception'
what(): /build/buildd/opencv-2.3.1/modules/core/src/matrix.cpp:303: error: (-215) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows in function Mat
I've noticed that this happens in roi, I have no clue why. I -am- a total beginner at openCV and I am doing this for homework.
Thank you.
If you need any further info please ask.
I'm not sure about C++ API but this is what I did in C API;
CvRect ROI = cvRect(x, y, width, height);
cvSetImageROI(srcImg, ROI);
IplImage* cropImg = cvCreateImage(cvGetSize(srcImg), IPL_DEPTH_8U, 1);//this part very important
cvCopy(srcImg, cropImg);
cvResetImageROI(srcImg);