Развернуть криволинейную поверхность

У меня есть цилиндрический объект, на который наклеена круглая метка. Я извлекаю контур изображения. введите здесь описание изображения

Я знаю радиус цилиндрического объекта, а также метку. Но не каждый раз полученный эллипс будет точно симметричным. Как я могу развернуть эллипс в круг?

Вот несимметричное изображениевведите здесь описание изображения

ОТРЕДАКТИРОВАНО Я попытался расширить решение @Haris примерно так: введите описание изображения здесь

Вместо всего лишь 4 точек я хочу использовать массив точек, чтобы получить более точный круг. Но getPerspectiveTransform не позволит мне иметь больше 4 баллов. Есть ли лучший способ для этого?


person harsh    schedule 23.04.2014    source источник
comment
Что такое круглая метка на изображениях, которые вы разместили? А также, хотите ли вы развернуть изображение так, чтобы белые пятна превратились в круги или чтобы сероватое пятно превратилось в круг?   -  person BConic    schedule 23.04.2014
comment
На самом деле я обработал изображение, и все, что вы видите, это круглая метка. Изначально и белые пятна, и сероватое пятно — это круги, которые я хочу сохранить после разворота.   -  person harsh    schedule 23.04.2014
comment
Кроме того, можете ли вы сделать какие-либо предположения об относительном положении между камерой и цилиндрическим объектом? Например, можете ли вы предположить, что ось Y изображения выровнена с осью цилиндра? Кроме того, можете ли вы предположить, что оптическая ось камеры пересекается в 3D с осью цилиндра?   -  person BConic    schedule 23.04.2014
comment
Да, ось Y изображения совмещена с осью цилиндра. Кроме того, поверхность цилиндра всегда параллельна плоскости камеры (это то, что вы спросили, я предполагаю)   -  person harsh    schedule 23.04.2014
comment
Перспективное преобразование — не лучший способ. Предполагая, что ось Y и ось цилиндра выровнены, вам нужно найти локальное горизонтальное смещение, которое будет применяться к каждому пикселю, чтобы цилиндрическая поверхность преобразовывалась в плоскость. Я не думаю, что для этого есть функция OpenCV, но если вы получите соответствующее сопоставление, вы можете использовать cv::remap (ссылка), чтобы применить ее к вашему изображению. Получение фактического сопоставления — это математический вопрос, вы должны задать его здесь.   -  person BConic    schedule 23.04.2014


Ответы (1)


Итак, вы хотите преобразовать свой объект в минимальный окружающий круг,

Как на изображении ниже, преобразуйте тростниковый прямоугольник в зеленый круг. Это преобразование ограничивающего прямоугольника в ограничивающий круг.

введите здесь описание изображения

Итак, сделайте следующее,

 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

Здесь вам нужно рассчитать матрицу преобразования из ограничивающей рамки и окружности, как

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

а затем применить перспективное преобразование,

Mat transformed = Mat::zeros(src.rows, src.cols, CV_8UC3);
warpPerspective(src, transformed, transmtx, src.size());
imshow("transformed", transformed);

введите здесь описание изображения

person Haris    schedule 23.04.2014
comment
Превосходно! Но теперь внутренние круги деформированы. Есть ли способ сохранить это? - person harsh; 23.04.2014
comment
Вы не можете выполнить преобразование, исключив некоторую часть внутри координат преобразования. - person Haris; 23.04.2014
comment
Нельзя ли растянуть точки ближе к вертикальной оси немного меньше, чем дальше? - person harsh; 24.04.2014
comment
В опубликованном вами изображении результата, поскольку внутренние белые пятна (которые находятся на вертикальной оси эллипса) также растягиваются, не можем ли мы получить растяжение, пропорциональное расстоянию точки от вертикальной оси? - person harsh; 24.04.2014
comment
Я думаю, что это невозможно с помощью warpPerspective. - person Haris; 24.04.2014