2

I have a cylindrical object on which a circular label is pasted. I extract the contour of the image.enter image description here

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 symmetricalenter image description here

EDITED I tried to extend @Haris's solution something like this enter image description here

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?

harsh
  • 905
  • 1
  • 10
  • 21
  • What exactly is the "circular label" in the images you posted? And also, do you want to unwarp the image so that _the white spots_ become circles or so that _the greyish blob_ becomes a circle? – BConic Apr 23 '14 at 12:25
  • Actually I have processed the image, and all you see is the "circular label". Originally, both the white spots and the grayish blob are circles, which I want to retain after the unwarp. – harsh Apr 23 '14 at 12:30
  • Also, can you make any assumptions about the relative pose between the camera and the cylindrical object? For instance, can you assume that the y-axis of the image is aligned with the axis of the cylinder? Also, can you assume that the optical axis of the camera intersects in 3D the axis of the cylinder? – BConic Apr 23 '14 at 12:36
  • Yes, the y-axis of image is aligned with axis of cylinder. Also, the surface of the cylinder is always parallel to the camera's plane (this is what you asked I assume) – harsh Apr 23 '14 at 12:42
  • A perspective transform is not the good way to go. Assuming the y-axis and cylinder axis are aligned, what you want is finding the local horizontal offset to be applied to each pixel, so that the cylindrical surface is transformed into a plane. I don't think there is an OpenCV function for that, but if you derive the appropriate mapping, you can use `cv::remap` ([link](http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html?highlight=remap#remap)) to apply it to your image. Deriving the actual mapping is a math question, you should ask [there](http://math.stackexchange.com/). – BConic Apr 23 '14 at 13:18

1 Answers1

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.

enter image description here

So do the following,

 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);`

enter image description here

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);

enter image description here

Haris
  • 13,645
  • 12
  • 90
  • 121
  • Excellent! But now the interior circles are deformed. Is there any way to maintain that as well? – harsh Apr 23 '14 at 10:47
  • You cant do transformation by excluding some part inside the transformation co-ordinates. – Haris Apr 23 '14 at 10:56
  • Can't we stretch points nearer to vertical axis a little less than those farther away? – harsh Apr 24 '14 at 07:14
  • 1
    In the result image you posted, since the inner white blobs (which are on the vertical axis of the ellipse) are also getting stretched, can't we have a stretch proportional to the distance of the point from the vertical axis? – harsh Apr 24 '14 at 07:32
  • I think it's not possible using warpPerspective. – Haris Apr 24 '14 at 07:48