타원은 원뿔을 평면으로 잘랐을 때 생기는 곡선 중의 하나로 다음 이차 형식(quadratic form)으로 표현된다.

이차 형식의 계수를 구하기 위해서는 타원 위의 서로 다른 5개의 점이 필요하다 (타원이기 위해서는
이를 만족시키는 해는 다음 행렬식으로 쓰인 방정식의 해와 같다:
또는 간단히
의 형태로 쓰여진다. 6개의 conic-parameters를 결정해야 하므로,
행렬
이어서

// 2024.05.30에 새롭게 작성;
double alg_distance(const CfPt& pts, double conic_param[6]) {
return conic_param[0] * pts.x * pts.x +
conic_param[1] * pts.x * pts.y +
conic_param[2] * pts.y * pts.y +
conic_param[3] * pts.x +
conic_param[4] * pts.y +
conic_param[5];
}
int num_sampling5(double prob_fail, double inlier_ratio) {
return int(log(prob_fail)/log(1-pow(inlier_ratio, 5)));
}
std::vector<int> Ransac_EllipseFit(std::vector<CfPt>& points, double ellipse_param[5]) {
if (points.size() < 5) return std::vector<int> (); //return null_vector;
CfPt center; double inv_scale;
// normalize input points for the sake of numerical stability;
std::vector<CfPt> nor_pts = normalize(points, inv_scale, center);
// RANSAC;
const double prob_fail = 0.01;
int sample_num = 1000; //number of sample
int ransac_count = 0;
const double distance_thresh = sqrt(3.84) * inv_scale;
double best_eparam[5] = {0};
std::vector<int> best_inliers;
while (sample_num > ransac_count) {
// pick random 5 indices:[0,points.size()-1];
int quintet[5];
random_quintet(points.size()-1, quintet);
CfPt selected[5];
for (int i = 0; i < 5; i++)
selected[i] = nor_pts[quintet[i]];
// ellipse parameters with 5 points;
double conic_param[6];
solve_conic(selected, conic_param);
// find inliers;
std::vector<int> inliers;
inliers.reserve(points.size());
for (int i = nor_pts.size(); i-->0;) {
// error measure = algebric distance;
double deviation = alg_distance(nor_pts[i], conic_param);
if (fabs(deviation) < distance_thresh)
inliers.push_back(i);
}
if ((inliers.size() > best_inliers.size()) &&
solve_ellipse(conic_param, ellipse_param)) {
// update sampling_num;
sample_num = num_sampling5(prob_fail, double(inliers.size())/points.size());
// update best_inliers;
best_inliers.swap(inliers);
// update best ellipse param;
for (int i = 0; i < 5; i++)
best_eparam[i] = ellipse_param[i];
}
if (++ransac_count > 1500) {
TRACE("error! ransac_count exceed!\n");
break;
}
}
// recover original scale and coordinate;
denormalize(best_eparam, best_eparam, inv_scale, center);
if (best_eparam[0] > 0 && best_eparam[1] > 0) {
for (int i = 0; i < 5; i++)
ellipse_param[i] = best_eparam[i];
TRACE("ellipse found(%d, %d)\n", sample_num, ransac_count);
} else
best_inliers.clear();
return best_inliers;
}
'Image Recognition' 카테고리의 다른 글
Expectation Maximization Algorithm for Two-Component Gaussian Mixture (0) | 2017.01.02 |
---|---|
Union-Find Connected Component Labeling (0) | 2012.11.01 |
Autofocus Algorithm (0) | 2012.06.03 |
Statistical Region Merging (2) | 2012.03.25 |
Local Histogram Equalization (0) | 2012.03.10 |