Skip to content

Commit

Permalink
support detect corners of deltille
Browse files Browse the repository at this point in the history
  • Loading branch information
ftdlyc committed Oct 23, 2018
1 parent 9840478 commit 3c3296a
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 32 deletions.
5 changes: 3 additions & 2 deletions src/libcbdetect/deltilles_from_corners.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ void deltilles_from_corners(const cv::Mat &img, const Corner &corners,
std::default_random_engine e;
auto time = std::chrono::system_clock::now().time_since_epoch();
e.seed(time.count());
int start = e() % corners.p.size();
int start = 47;
e() % corners.p.size();

// for all seed corners do
int n = 0;
Expand All @@ -87,7 +88,7 @@ void deltilles_from_corners(const cv::Mat &img, const Corner &corners,
while (1) {
int num_corners = deltille.num;

for (int j = 0; j < 4; ++j) {
for (int j = 0; j < 6; ++j) {
std::vector<cv::Point2i> proposal;
GrowType grow_type = grow_deltille(corners, used, deltille, proposal, j);
if (grow_type == Failure) { continue; }
Expand Down
11 changes: 9 additions & 2 deletions src/libcbdetect/find_corners.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace cbdetect {

void find_corners_in_image(const cv::Mat &img, Corner &corners, const Params &params) {
// convert to double grayscale image
cv::Mat img_norm, img_show;
cv::Mat img_norm;
if (img.channels() == 3) {
cv::cvtColor(img, img_norm, CV_BGRA2GRAY);
img_norm.convertTo(img_norm, CV_64F, 1 / 255.0, 0);
Expand All @@ -49,6 +49,12 @@ void find_corners_in_image(const cv::Mat &img, Corner &corners, const Params &pa
// normalize image and calculate gradients
cv::Mat img_du, img_dv, img_angle, img_weight;
image_normalization_and_gradients(img_norm, img_du, img_dv, img_angle, img_weight, params);
if (params.show_debug_image && params.norm) {
cv::Mat img_show;
img_norm.convertTo(img_show, CV_8U, 255, 0);
cv::imshow("norm image ", img_show);
cv::waitKey();
}

// get corner's initial locaiton
get_init_location(img_norm, img_du, img_dv, corners, params);
Expand Down Expand Up @@ -98,6 +104,7 @@ void find_corners(const cv::Mat &img, Corner &corners, const Params &params) {
find_corners_in_image(img, corners_1, params);
Params params_resize = params;
params_resize.norm_half_kernel_size = params.norm_half_kernel_size / 2;
params_resize.polynomial_fit_half_kernel_size = std::max(2, params.polynomial_fit_half_kernel_size / 2);
find_corners_in_image(img_resized, corners_2, params_resize);
std::for_each(corners_2.p.begin(), corners_2.p.end(), [](auto &p) { p *= 2; });

Expand All @@ -109,7 +116,7 @@ void find_corners(const cv::Mat &img, Corner &corners, const Params &params) {
corners.v3 = std::move(corners_1.v3);
corners.score = std::move(corners_1.score);
for (int i = 0; i < corners_2.p.size(); ++i) {
double min_dist = 1e10;
double min_dist = DBL_MAX;
cv::Point2d &p2 = corners_2.p[i];
for (int j = 0; j < n_1; ++j) {
cv::Point2d &p1 = corners.p[j];
Expand Down
46 changes: 26 additions & 20 deletions src/libcbdetect/grow_chessboard.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,32 @@ std::vector<cv::Point2d> predict_corners(const Corner &corners,
const std::vector<int> &p1,
const std::vector<int> &p2,
const std::vector<int> &p3) {
std::vector<cv::Point2d> pred(p1.size());
for (int i = 0; i < pred.size(); ++i) {
// compute vectors
cv::Point2d v1 = corners.p[p2[i]] - corners.p[p1[i]];
cv::Point2d v2 = corners.p[p3[i]] - corners.p[p2[i]];

// predict angles
double a1 = std::atan2(v1.y, v1.x);
double a2 = std::atan2(v2.y, v2.x);
double a3 = 2 * a2 - a1;

// predict scales
double s1 = cv::norm(v1);
double s2 = cv::norm(v2);
double s3 = 2 * s2 - s1;

// predict p4 (the factor 0.75 ensures that under extreme
// distortions (omnicam) the closer prediction is selected)
pred[i].x = corners.p[p3[i]].x + 0.75 * s3 * std::cos(a3);
pred[i].y = corners.p[p3[i]].y + 0.75 * s3 * std::sin(a3);
std::vector<cv::Point2d> pred(p3.size());
if (p1.empty()) {
for (int i = 0; i < pred.size(); ++i) {
pred[i] = 2 * corners.p[p3[i]] - corners.p[p2[i]];
}
} else {
for (int i = 0; i < pred.size(); ++i) {
// compute vectors
cv::Point2d v1 = corners.p[p2[i]] - corners.p[p1[i]];
cv::Point2d v2 = corners.p[p3[i]] - corners.p[p2[i]];

// predict angles
double a1 = std::atan2(v1.y, v1.x);
double a2 = std::atan2(v2.y, v2.x);
double a3 = 2 * a2 - a1;

// predict scales
double s1 = cv::norm(v1);
double s2 = cv::norm(v2);
double s3 = 2 * s2 - s1;

// predict p4 (the factor 0.75 ensures that under extreme
// distortions (omnicam) the closer prediction is selected)
pred[i].x = corners.p[p3[i]].x + 0.75 * s3 * std::cos(a3);
pred[i].y = corners.p[p3[i]].y + 0.75 * s3 * std::sin(a3);
}
}
return pred;
}
Expand Down
130 changes: 126 additions & 4 deletions src/libcbdetect/grow_deltille.cc
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ GrowType grow_deltille(const Corner &corners, std::vector<int> &used, Deltille &
int rows = deltille.idx.size();
std::vector<int> idx, p1, p2, p3;

// fill inside corners
#if 0
// fill inside corners top/left/bottom/right/top-left/bottom-right
switch (board_type) {
case 0: {
for (int i = rows - 4; i >= 0; --i) {
Expand Down Expand Up @@ -174,7 +175,7 @@ GrowType grow_deltille(const Corner &corners, std::vector<int> &used, Deltille &
break;
}
case 2: {
for (int i = 3; i <= rows - 1; ++i) {
for (int i = 3; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx1 = deltille.idx[i - 3][j];
Expand All @@ -191,7 +192,7 @@ GrowType grow_deltille(const Corner &corners, std::vector<int> &used, Deltille &
}
case 3: {
for (int i = 0; i < rows; ++i) {
for (int j = 3; j <= cols - 1; ++j) {
for (int j = 3; j < cols; ++j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx1 = deltille.idx[i][j - 3];
int idx2 = deltille.idx[i][j - 2];
Expand All @@ -205,8 +206,129 @@ GrowType grow_deltille(const Corner &corners, std::vector<int> &used, Deltille &
}
break;
}
case 4: {
for (int i = 3; i < rows; ++i) {
for (int j = 3; j < cols; ++j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx1 = deltille.idx[i - 3][j - 3];
int idx2 = deltille.idx[i - 2][j - 2];
int idx3 = deltille.idx[i - 1][j - 1];
if (idx1 < 0 || idx2 < 0 || idx3 < 0) { continue; }
p1.emplace_back(idx1);
p2.emplace_back(idx2);
p3.emplace_back(idx3);
proposal.emplace_back(cv::Point2i(j, i));
}
}
break;
}
case 5: {
for (int i = 0; i < rows - 3; ++i) {
for (int j = 0; j < cols - 3; ++j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx1 = deltille.idx[i + 3][j + 3];
int idx2 = deltille.idx[i + 2][j + 2];
int idx3 = deltille.idx[i + 1][j + 1];
if (idx1 < 0 || idx2 < 0 || idx3 < 0) { continue; }
p1.emplace_back(idx1);
p2.emplace_back(idx2);
p3.emplace_back(idx3);
proposal.emplace_back(cv::Point2i(j, i));
}
}
}
default:break;
}
#else
// fill inside corners top/left/bottom/right/top-left/bottom-right
switch (board_type) {
case 0: {
for (int i = rows - 3; i >= 0; --i) {
for (int j = 0; j < cols; ++j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx2 = deltille.idx[i + 2][j];
int idx3 = deltille.idx[i + 1][j];
if (idx2 < 0 || idx3 < 0) { continue; }
p2.emplace_back(idx2);
p3.emplace_back(idx3);
proposal.emplace_back(cv::Point2i(j, i));
}
}
break;
}
case 1: {
for (int i = 0; i < rows; ++i) {
for (int j = cols - 3; j >= 0; --j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx2 = deltille.idx[i][j + 2];
int idx3 = deltille.idx[i][j + 1];
if (idx2 < 0 || idx3 < 0) { continue; }
p2.emplace_back(idx2);
p3.emplace_back(idx3);
proposal.emplace_back(cv::Point2i(j, i));
}
}
break;
}
case 2: {
for (int i = 2; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx2 = deltille.idx[i - 2][j];
int idx3 = deltille.idx[i - 1][j];
if (idx2 < 0 || idx3 < 0) { continue; }
p2.emplace_back(idx2);
p3.emplace_back(idx3);
proposal.emplace_back(cv::Point2i(j, i));
}
}
break;
}
case 3: {
for (int i = 0; i < rows; ++i) {
for (int j = 2; j < cols; ++j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx2 = deltille.idx[i][j - 2];
int idx3 = deltille.idx[i][j - 1];
if (idx2 < 0 || idx3 < 0) { continue; }
p2.emplace_back(idx2);
p3.emplace_back(idx3);
proposal.emplace_back(cv::Point2i(j, i));
}
}
break;
}
case 4: {
for (int i = 2; i < rows; ++i) {
for (int j = 2; j < cols; ++j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx2 = deltille.idx[i - 2][j - 2];
int idx3 = deltille.idx[i - 1][j - 1];
if (idx2 < 0 || idx3 < 0) { continue; }
p2.emplace_back(idx2);
p3.emplace_back(idx3);
proposal.emplace_back(cv::Point2i(j, i));
}
}
break;
}
case 5: {
for (int i = 0; i < rows - 2; ++i) {
for (int j = 0; j < cols - 2; ++j) {
if (deltille.idx[i][j] != -1) { continue; }
int idx2 = deltille.idx[i + 2][j + 2];
int idx3 = deltille.idx[i + 1][j + 1];
if (idx2 < 0 || idx3 < 0) { continue; }
p2.emplace_back(idx2);
p3.emplace_back(idx3);
proposal.emplace_back(cv::Point2i(j, i));
}
}
break;
}
default:break;
}
#endif

// predict inside corners
std::vector<int> pred = predict_deltille_corner(corners, used, p1, p2, p3);
Expand All @@ -227,7 +349,7 @@ GrowType grow_deltille(const Corner &corners, std::vector<int> &used, Deltille &
cols = deltille.idx[0].size();
rows = deltille.idx.size();

// grow board corners
// grow board corners top/left/bottom/right
switch (board_type) {
case 0: {
for (int i = 0; i < cols; ++i) {
Expand Down
4 changes: 2 additions & 2 deletions src/libcbdetect/polynomial_fit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void polynomial_fit_saddle(const cv::Mat &img, int r, Corner &corners) {
void polynomial_fit_monkey_saddle(const cv::Mat &img, int r, Corner &corners) {
// maximum iterations and precision
int max_iteration = 5;
double eps = 0.01;
double eps = 0.001;
int width = img.cols;
int height = img.rows;

Expand Down Expand Up @@ -181,7 +181,7 @@ void polynomial_fit_monkey_saddle(const cv::Mat &img, int r, Corner &corners) {
cv::Mat tmp_a = (cv::Mat_<double>(3, 2) << 3.0 * k.at<double>(0, 0), k.at<double>(1, 0),
2.0 * k.at<double>(1, 0), 2.0 * k.at<double>(2, 0),
k.at<double>(2, 0), 3.0 * k.at<double>(3, 0));
cv::Mat tmp_b = (cv::Mat_<double>(3, 1) << -k.at<double>(4, 0), -2.0 * k.at<double>(5, 0), -k.at<double>(6, 0));
cv::Mat tmp_b = (cv::Mat_<double>(3, 1) << -k.at<double>(4, 0), -k.at<double>(5, 0), -k.at<double>(6, 0));
cv::Mat tmp_x = (tmp_a.t() * tmp_a).inv() * tmp_a.t() * tmp_b;
double dx = tmp_x.at<double>(0, 0);
double dy = tmp_x.at<double>(1, 0);
Expand Down
4 changes: 2 additions & 2 deletions src/libcbdetect/score_corners.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ void sorce_corners(const cv::Mat &img, const cv::Mat &img_weight, Corner &corner
// for all corners do
for (int i = 0; i < corners.p.size(); ++i) {
// corner location
int u = corners.p[i].x;
int v = corners.p[i].y;
double u = corners.p[i].x;
double v = corners.p[i].y;
int r = corners.r[i];

if (u - r < 0 || u + r >= width || v - r < 0 || v + r >= height) {
Expand Down

0 comments on commit 3c3296a

Please sign in to comment.