Skip to content

Instantly share code, notes, and snippets.

@StevenPuttemans
Created March 24, 2017 14:09
Show Gist options
  • Save StevenPuttemans/2649eea4c6ff5a90cc27d47767e9b739 to your computer and use it in GitHub Desktop.
Save StevenPuttemans/2649eea4c6ff5a90cc27d47767e9b739 to your computer and use it in GitHub Desktop.
[OPENCV3.2] Warping rotated rects back to a horizontal position
/// 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