opencv - image stitch use of vector<vector<Rect> > rois - c++

I'm having trouble specifying the "region of interests" to perform feature finding in image stitching method (Stitcher::stitch). I get the following 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 /Users/Aziz/Documents/Projects/opencv_sources/trunk/modules/core/src/matrix.cpp, line 308
terminate called throwing an exception"
but when I checked the regions and the image cols and rows, it seems to be fine. Any help of suggestion would be appreciated.

OpenCV 2.4.0 have bug in Stitcher::Status Stitcher::matchImages() method (stiicher.cpp):
the algo scales the input image but the input roi remain unchanged.

Related

How to fix error with cv::boundingRect in OpenCV

I am using OpenCV version 4.0.0. I am trying to stitch some images together and trim the resulting image and while I am able to stitch the images, I am not able to trim the resulting image.
My program keeps aborting with the following error:
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: OpenCV(4.0.0) /Users/RAR/opencv/modules/core/src/umatrix.cpp:545: error: (-215: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 function 'UMat'
Abort trap: 6
The error occurs at the line stitched = stitched(cv::boundingRect(c)); in the code below.
while (cv::countNonZero(sub) > 0) {
cv::erode(minRect, minRect, cv::Mat()); // Erode the minimum rectangular mask
cv::subtract(minRect, thresh, sub); // Subtract the thresholded image from the minmum rectangular mask (count if there are any non-zero pixels left)
std::vector<std::vector<cv::Point>> cnts4;
cv::findContours(minRect.clone(), cnts4, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
c = cnts4[0];
for (auto iter = cnts4.begin(); iter != cnts4.end(); ++iter) {
if (cv::contourArea(*iter) > cv::contourArea(c)) { // Finds the largest contour (the contour/outline of the stitched image)
c = *iter;
}
}
stitched = stitched(cv::boundingRect(c)); // Extract the bounding box and use the bounding box coordinates to extract the final stitched images
}
Why am I getting this error?
From OP's comments:
stitched: cols: 4295 rows: 2867 bounding rect[4274 x 2845 from (11, 12)]
stitched: cols: 4274 rows: 2845 bounding rect[4272 x 2843 from (12, 13)]
In the first case, the rectangle is trying to extract a size of (4274, 2845) from (11, 12) in the stitched image. This means that it is taking pixels from (11, 12) to (4285, 2857), which is within the bounds of the stitched image since the stitched image has a size of (4295, 2867). No problem.
In the second case, the rectangle is trying to extract a size of (4272, 2843) from (12, 13) in the stitched image. This means that it is taking pixels from (12, 13) to (4284, 2856), which is out of bounds of the stitched image since the stitched image has a size of (4274, 2845). Problem.
The sub-image you are trying to extract is much bigger than the bigger image.
(-215: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
The error message also indicates this. roi in the error message refers to the sub-image you are trying to extract using cv::boundingRect(c) and m is the stitched image. The coordinates of this rectangle are beyond the size of the stitched image.
You can test this by setting the coordinates of the rectangle manually.
You should not get an error with stitched(cv::Rect(11, 12, cv::Size(4274, 2845)
You will get the error with stitched(cv::Rect(12, 13, cv::Size(4272, 2843)
Last iteration is the problem, as it won't find any contours.
Maybe you can try something like so :
int nonZeroCount = 1;
while (nonZeroCount)
{
cv::erode(minRect, minRect, cv::Mat());
cv::subtract(minRect, thresh, sub);
nonZeroCount = cv::countNonZero(sub);
if (nonZeroCount)
{
std::vector< std::vector<cv::Point> > cnts4;
cv::findContours(minRect.clone(), cnts4, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
c = cnts4[0];
for (auto iter = cnts4.begin(); iter != cnts4.end(); ++iter)
{
if (cv::contourArea(*iter) > cv::contourArea(c))
{
c = *iter;
}
}
stitched = stitched(cv::boundingRect(c));
}
}

Extract sub-image from image using OpenCV and C++

I'm trying to get a sub-image from a RGB image in openCV and C++. I've seen the other threads on this topic but it didn't worked for me.
This is the code that I use:
Mat src = imread("Images/00011_00025.ppm");
Rect crop(1, 1, 64, 67);
Mat rez = src(crop);
The image a 64x67 dimension, so I don't understand why I get the following error in the console:
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)
Any ideas of what is the cause of this error?
Rect crop(1, 1, 64, 67);
The rectangles top left corner is at position (1,1) and its size is set to 64x67.
Mat rez = src(crop);
When using this rectangle to crop the image you're running out of bounds, since the rectangle has an offset of one pixel but the same size as the image to crop.
You could either manually account for the offset on width and height, or, and this is my preferred solution for cropping, make use of a cv::Range.
With ranges you could define a row and column span to perform cropping:
cv::Range rows(1, 64);
cv::Range cols(1, 67);
Mat rez = src(rows, cols);

2D obstacle collision

Hi I am trying to make 2d collision but I dont get it to work
i am doing :
if (collider.posX + collider.sizeX >= obstacle.posX && obstacle.posX + obstacle.sizeX >= collider.posX && collider.posY + collider.sizeY >= obstacle.posY)
the obstacle cannot move on the y axis so this is why i only check for
collider.posY + 50 >= obstacle.posY
the collision works but they are only start when the obstacle is half in the collider
What about:
if( obstacle.posX >= collider.posX &&
obstacle.posX <= collider.posX + collider.sizeX &&
obstacle.posY >= collider.posY &&
obstacle.posY <= collider.posY + collider.sizeY
)
This code should check if obstacle point intersects collider rectangle.
This is better solution because it detects overlapping between 2 rectangles:
if ( obstacle.posX <= collider.posX + collider.sizeX &&
obstacle.posX + obstacle.sizeX >= collider.posX &&
obstacle.posY <= collider.posY + collider.sizeY &&
obstacle.posY + obstacle.sizeY >= collider.posY )
You're running into logical errors, seen by the following code:
collider.posX + collider.sizeX >= obstacle.posX
Suppose the two colliding objects are circles with their positions being their center points. The first object is moving in the positive X direction while the second is static (stationary). You need to check if the first object's X position plus its radius (not diameter) touches the second object's X position minus its radius.
Example code:
collider.posX + (collider.sizeX / 2) >= obstacle.posX - (obstacle.sizeX / 2)
Note: The above inequality assumes that collider.sizeX represents the diameter of collider.
Presumably later on you'll also need to check if the first object is passed the second object. Since the above inequality only accounts for the first object having an increasing X position and its X position being less than the second object's X position.

OpenCV extract area of an image from a vector of squares

I have an image that contains a square, and I need to extract the area contained in that square.
After applying the squares.c script (available in the samples of every OpenCV distribution) I obtain a vector of squares, then I need to save an image for each of them.
The user karlphillip suggested this:
for (size_t x = 0; x < squares.size(); x++)
{
Rect roi(squares[x][0].x, squares[x][0].y,
squares[x][1].x - squares[x][0].x,
squares[x][3].y - squares[x][0].y);
Mat subimage(image, roi);
}
in order to generate a new Mat called subimage for all the squares detected in the original image
As karl remembered me, the points detected in the image may not represent a perfect square (as you can see in the image above) but the code I just suggested to you assumes they do.
In fact 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 /usr/include/opencv/cxmat.hpp,
line 187
terminate called after throwing an instance of 'cv::Exception'
what(): /usr/include/opencv/cxmat.hpp:187: 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
Suggestion for make the script accept also non perfect squares?
I feel like I need to clarify a few things about that code.
First, it assumes that the region detected is a perfect square because it ignores some of the points inside squares[x] to create a new Mat.
Second, it also assumes that the points that make the region were detected in the clockwise direction, starting with p0 in the top-left corner of the image:
(p0) 1st----2nd (p1)
| |
| |
(p3) 4th----3rd (p2)
which might not be true for all the regions detected. That means that this code:
Rect roi(squares[x][0].x, squares[x][0].y,
squares[x][1].x - squares[x][0].x,
squares[x][3].y - squares[x][0].y);
probably will generate a ROI with invalid dimensions, such as negative width and height values, and that's why OpenCV throws a cv::Exception at you on Mat subimage(image, roi);.
What you should do, is write a code that will identify the top-left point of the region and call it p0, then it's nearest neightbor on the right side, p1, then find the bottom-right point of the region and call it p2, and then what's left is p3. After this, assembling the ROI is easy:
Rect roi(p0.x, p0.y,
p1.x - p0.x,
p3.y - p0.y);
EDIT:
I found an excellent solution while reading the documentation of the v2.3 of OpenCV. It automates the process I described earlier and it make things so much easier and clean. You can use this trick to order the 4 Points in the vector to a meaningful Rect structure:
// Data returned and filled by findSquares(). Check the example squares.cpp for more info on this function.
vector<vector<Point> > squares;
for (size_t i = 0; i < squares.size(); i++)
{
Rect rectangle = boundingRect(Mat(squares[i]));
cout << "#" << i << " rectangle x:" << rectangle.x << " y:" << rectangle.y << " " << rectangle.width << "x" << rectangle.height << endl;
}

Access element of float cv::Mat

I don't understand why I can't get this code to work:
cv::Mat M(2, 3, CV_32FC1);
cv::Point2f center(20, 20);
M = cv::getRotationMatrix2D(center, 20, 1.0);
float test;
test = M.at<float>(1, 0);
test = M.at<float>(0, 1);
test = M.at<float>(1, 1);
The code fails when accessing the elements with M.at. The following assertion comes up:
OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)si
ze.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channel
s()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3
) - 1))*4) & 15) == elemSize1()) in unknown function, file C:\OpenCV2.2\include\
opencv2/core/mat.hpp, line 517
To quote Good Will Hunting, "It's not your fault!"
M has been overwritten with a CV_64C1 or a double rotation matrix and that's why M.at<float>(i,j) fails.
So, don't bother initializing M ; cv::getRotationMatrix will take care of it and return a CV_64F matrix which can (of course) be accessed with M.at<double>(i,j).
I don't know anything about the cv namespace, but I would put a breakpoint at the first call to M.at() and look at the members of M. One of these members is causing the error:
dims <= 2
data == 0
i0 < size.p[0]
i1*DataType<_Tp>::channels < size.p[1]*channels()
((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 15) == elemSize1() //sure hope it isn't this one