Created
March 24, 2017 14:09
-
-
Save StevenPuttemans/2649eea4c6ff5a90cc27d47767e9b739 to your computer and use it in GitHub Desktop.
[OPENCV3.2] Warping rotated rects back to a horizontal position
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Considering you have a contour available after segmentation | |
/// Considering you have an image where the contour is found | |
vector<Point> contour; | |
Mat image; | |
/// Get the RotatedRect associated with the contour | |
RotatedRect rect = minAreaRect(contour); | |
/// Also select the corner points for rotating back | |
Point2f pts[4]; rect.points(pts); | |
/// Define the angle of rotation and rotate the selection to an upright position | |
/// This will work for slight rotations, once going over 45 degrees this might result in wrong transformations | |
double angle = 0.0; | |
if((int)rect.angle < -45){ | |
angle = fmod((rect.angle + 90), 90); | |
}else{ | |
angle = (int)rect.angle; | |
} | |
/// Generate a larger canvas to not loose pixel information while rotating | |
int largest = std::max(image.cols, image.rows); largest = largest * 1.2; | |
Mat canvas = Mat::zeros(Size(largest,largest), image.type()); | |
int offsetx = canvas.cols/2 - image.cols/2; | |
int offsety = canvas.rows/2 - image.rows/2; | |
/// First apply a transformation of the image into the canvas | |
Mat translation_matrix = (Mat_<double>(2,3) << 1, 0, offsetx, 0 , 1, offsety); | |
warpAffine(image, canvas, translation_matrix, canvas.size()); | |
/// Then apply a rotation matrix to the larger canvas, to correct for the angle | |
Mat r = getRotationMatrix2D(Point2f(canvas_final.cols/2, canvas_final.rows/2), angle, 1.0); | |
warpAffine(canvas_final.clone(), canvas_final, r, cv::Size(canvas_final.cols, canvas_final.rows)); | |
/// Finally warp the corner points from the original image using same matrix to obtain the mask to be cut out | |
/// ATTENTION: Keep in mind the offset of the larger canvas | |
Mat coordinates = (Mat_<double>(3,4) << pts[0].x + offsetx, pts[1].x + offsetx, pts[2].x + offsetx, pts[3].x + offsetx,\ | |
pts[0].y + offsety, pts[1].y + offsety, pts[2].y + offsety, pts[3].y + offsety,\ | |
1 , 1 , 1 , 1 ); | |
Mat result = r * coordinates; | |
Point p1_back, p2_back, p3_back, p4_back; | |
vector<Point> collection; | |
p1_back.x=(int)result.at<double>(0,0); p1_back.y=(int)result.at<double>(1,0); collection.push_back(p1_back); | |
p2_back.x=(int)result.at<double>(0,1); p2_back.y=(int)result.at<double>(1,1); collection.push_back(p2_back); | |
p3_back.x=(int)result.at<double>(0,2); p3_back.y=(int)result.at<double>(1,2); collection.push_back(p3_back); | |
p4_back.x=(int)result.at<double>(0,3); p4_back.y=(int)result.at<double>(1,3); collection.push_back(p4_back); | |
/// Cut out the desired region | |
Rect ROI = boundingRect(collection); | |
Mat cropped = canvas(ROI).clone(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An example of how your initial contour can look like is seen below
Grabbed from: http://answers.opencv.org/question/135486/the-cropped-roi-image-is-just-tiltedi-wanted-it-to-be-tilted-to-correct-rectangular-axeswhat-method-should-be-used-to-dopls-help-me-with-a-solution/