问题
I have a cylindrical object on which a circular label is pasted. I extract the contour of the image.
I know the radius of the cylindrical object as well as the label. But not every time the ellipse obtained will be exactly symmetrical. How can I unwrap the ellipse into a circle?
Here's an image which is not symmetrical
EDITED I tried to extend @Haris's solution something like this
Instead of just just 4 points, I want to use an array of points to get a more accurate circle. But getPerspectiveTransform
won't allow me to have more than 4 points. Is there a better way to this?
回答1:
So you want to transform your object to minimum enclosing circle,
Like in the below image transform reed rectangle to green circle. That is transform bounding rectangle to bounding circle.
So do the following,
Threshold the image
Find contour and calculate bounding rect and minmum enclosing circle for contour.
Mat src=imread("src.png");
Mat thr;
cvtColor(src,thr,CV_BGR2GRAY);
threshold( thr, thr, 20, 255,CV_THRESH_BINARY_INV );
bitwise_not(thr,thr);
vector< vector <Point> > contours; // Vector for storing contour
vector< Vec4i > hierarchy;
Mat dst(src.rows,src.cols,CV_8UC1,Scalar::all(0)); //create destination image
findContours( thr.clone(), contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
drawContours( dst,contours, 0, Scalar(255,255,255),CV_FILLED, 8, hierarchy );
Rect R=boundingRect(contours[0]);
Point2f center;
float radius;
minEnclosingCircle( (Mat)contours[0], center, radius);`
- Apply warpPerspective
Here you need calculate transformation matrix from bounding box and circle like
std::vector<Point2f> src_pts;
std::vector<Point2f> dst_pts;
src_pts.push_back(Point(R.x,R.y));
src_pts.push_back(Point(R.x+R.width,R.y));
src_pts.push_back(Point(R.x,R.y+R.height));
src_pts.push_back(Point(R.x+R.width,R.y+R.height));
dst_pts.push_back(Point2f(center.x-radius,center.y-radius));
dst_pts.push_back(Point2f(center.x+radius,center.y-radius));
dst_pts.push_back(Point2f(center.x-radius,center.y+radius));
dst_pts.push_back(Point2f(center.x+radius,center.y+radius));
Mat transmtx = getPerspectiveTransform(src_pts,dst_pts);
and then apply perspective transform,
Mat transformed = Mat::zeros(src.rows, src.cols, CV_8UC3);
warpPerspective(src, transformed, transmtx, src.size());
imshow("transformed", transformed);
来源:https://stackoverflow.com/questions/23240141/unwarp-curved-surface