mirror of
https://github.com/opencv/opencv.git
synced 2025-06-19 17:20:52 +08:00
Merge pull request #11968 from allnes:detect_qr_code
This commit is contained in:
commit
40b8ca2eed
@ -35,13 +35,13 @@ protected:
|
|||||||
Point2f intersectionLines(Point2f a1, Point2f a2, Point2f b1, Point2f b2);
|
Point2f intersectionLines(Point2f a1, Point2f a2, Point2f b1, Point2f b2);
|
||||||
vector<Point2f> getQuadrilateral(vector<Point2f> angle_list);
|
vector<Point2f> getQuadrilateral(vector<Point2f> angle_list);
|
||||||
bool testBypassRoute(vector<Point2f> hull, int start, int finish);
|
bool testBypassRoute(vector<Point2f> hull, int start, int finish);
|
||||||
double getQuadrilateralArea(Point2f a, Point2f b, Point2f c, Point2f d);
|
|
||||||
double getTriangleArea(Point2f a, Point2f b, Point2f c);
|
double getTriangleArea(Point2f a, Point2f b, Point2f c);
|
||||||
|
double getPolygonArea(vector<Point2f> points);
|
||||||
double getCosVectors(Point2f a, Point2f b, Point2f c);
|
double getCosVectors(Point2f a, Point2f b, Point2f c);
|
||||||
|
|
||||||
Mat barcode, bin_barcode, straight_barcode;
|
Mat barcode, bin_barcode, straight_barcode;
|
||||||
vector<Point2f> localization_points, transformation_points;
|
vector<Point2f> localization_points, transformation_points;
|
||||||
double experimental_area, eps_vertical, eps_horizontal, coeff_expansion;
|
double eps_vertical, eps_horizontal, coeff_expansion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -113,8 +113,8 @@ vector<Vec3d> QRDecode::searchVerticalLines()
|
|||||||
|
|
||||||
for (size_t i = 0; i < test_lines.size(); i++)
|
for (size_t i = 0; i < test_lines.size(); i++)
|
||||||
{
|
{
|
||||||
if (i == 2) { weight += abs((test_lines[i] / length) - 3.0/7.0); }
|
if (i == 2) { weight += fabs((test_lines[i] / length) - 3.0/7.0); }
|
||||||
else { weight += abs((test_lines[i] / length) - 1.0/7.0); }
|
else { weight += fabs((test_lines[i] / length) - 1.0/7.0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (weight < eps_vertical)
|
if (weight < eps_vertical)
|
||||||
@ -184,8 +184,8 @@ vector<Point2f> QRDecode::separateHorizontalLines(vector<Vec3d> list_lines)
|
|||||||
|
|
||||||
for (size_t i = 0; i < test_lines.size(); i++)
|
for (size_t i = 0; i < test_lines.size(); i++)
|
||||||
{
|
{
|
||||||
if (i % 3 == 0) { weight += abs((test_lines[i] / length) - 3.0/14.0); }
|
if (i % 3 == 0) { weight += fabs((test_lines[i] / length) - 3.0/14.0); }
|
||||||
else { weight += abs((test_lines[i] / length) - 1.0/ 7.0); }
|
else { weight += fabs((test_lines[i] / length) - 1.0/ 7.0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if(weight < eps_horizontal)
|
if(weight < eps_horizontal)
|
||||||
@ -245,6 +245,7 @@ bool QRDecode::localization()
|
|||||||
|
|
||||||
vector<Point2f> centers;
|
vector<Point2f> centers;
|
||||||
Mat labels;
|
Mat labels;
|
||||||
|
if (list_lines_y.size() < 3) { return false; }
|
||||||
kmeans(list_lines_y, 3, labels,
|
kmeans(list_lines_y, 3, labels,
|
||||||
TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 10, 1.0),
|
TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 10, 1.0),
|
||||||
3, KMEANS_PP_CENTERS, localization_points);
|
3, KMEANS_PP_CENTERS, localization_points);
|
||||||
@ -390,13 +391,6 @@ bool QRDecode::computeTransformationPoints()
|
|||||||
intersectionLines(down_left_edge_point, down_max_delta_point,
|
intersectionLines(down_left_edge_point, down_max_delta_point,
|
||||||
up_right_edge_point, up_max_delta_point));
|
up_right_edge_point, up_max_delta_point));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
experimental_area = getQuadrilateralArea(transformation_points[0],
|
|
||||||
transformation_points[1],
|
|
||||||
transformation_points[2],
|
|
||||||
transformation_points[3]);
|
|
||||||
|
|
||||||
vector<Point2f> quadrilateral = getQuadrilateral(transformation_points);
|
vector<Point2f> quadrilateral = getQuadrilateral(transformation_points);
|
||||||
transformation_points = quadrilateral;
|
transformation_points = quadrilateral;
|
||||||
|
|
||||||
@ -489,6 +483,8 @@ vector<Point2f> QRDecode::getQuadrilateral(vector<Point2f> angle_list)
|
|||||||
hull[i] = Point2f(x, y);
|
hull[i] = Point2f(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const double experimental_area = getPolygonArea(hull);
|
||||||
|
|
||||||
vector<Point2f> result_hull_point(angle_size);
|
vector<Point2f> result_hull_point(angle_size);
|
||||||
double min_norm;
|
double min_norm;
|
||||||
for (size_t i = 0; i < angle_size; i++)
|
for (size_t i = 0; i < angle_size; i++)
|
||||||
@ -600,8 +596,11 @@ vector<Point2f> QRDecode::getQuadrilateral(vector<Point2f> angle_list)
|
|||||||
extra_bypass_orientation = testBypassRoute(hull, finish_line[1], unstable_pnt);
|
extra_bypass_orientation = testBypassRoute(hull, finish_line[1], unstable_pnt);
|
||||||
|
|
||||||
vector<Point2f> result_angle_list(4), test_result_angle_list(4);
|
vector<Point2f> result_angle_list(4), test_result_angle_list(4);
|
||||||
double min_area = std::numeric_limits<double>::max(), test_area;
|
double min_diff_area = std::numeric_limits<double>::max(), test_diff_area;
|
||||||
index_hull = start_line[0];
|
index_hull = start_line[0];
|
||||||
|
double standart_norm = std::max(
|
||||||
|
norm(result_side_begin[0] - result_side_end[0]),
|
||||||
|
norm(result_side_begin[1] - result_side_end[1]));
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (bypass_orientation) { next_index_hull = index_hull + 1; }
|
if (bypass_orientation) { next_index_hull = index_hull + 1; }
|
||||||
@ -610,6 +609,9 @@ vector<Point2f> QRDecode::getQuadrilateral(vector<Point2f> angle_list)
|
|||||||
if (next_index_hull == hull_size) { next_index_hull = 0; }
|
if (next_index_hull == hull_size) { next_index_hull = 0; }
|
||||||
if (next_index_hull == -1) { next_index_hull = hull_size - 1; }
|
if (next_index_hull == -1) { next_index_hull = hull_size - 1; }
|
||||||
|
|
||||||
|
if (norm(hull[index_hull] - hull[next_index_hull]) < standart_norm / 10.0)
|
||||||
|
{ index_hull = next_index_hull; continue; }
|
||||||
|
|
||||||
extra_index_hull = finish_line[1];
|
extra_index_hull = finish_line[1];
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -619,6 +621,9 @@ vector<Point2f> QRDecode::getQuadrilateral(vector<Point2f> angle_list)
|
|||||||
if (extra_next_index_hull == hull_size) { extra_next_index_hull = 0; }
|
if (extra_next_index_hull == hull_size) { extra_next_index_hull = 0; }
|
||||||
if (extra_next_index_hull == -1) { extra_next_index_hull = hull_size - 1; }
|
if (extra_next_index_hull == -1) { extra_next_index_hull = hull_size - 1; }
|
||||||
|
|
||||||
|
if (norm(hull[extra_index_hull] - hull[extra_next_index_hull]) < standart_norm / 10.0)
|
||||||
|
{ extra_index_hull = extra_next_index_hull; continue; }
|
||||||
|
|
||||||
test_result_angle_list[0]
|
test_result_angle_list[0]
|
||||||
= intersectionLines(result_side_begin[0], result_side_end[0],
|
= intersectionLines(result_side_begin[0], result_side_end[0],
|
||||||
result_side_begin[1], result_side_end[1]);
|
result_side_begin[1], result_side_end[1]);
|
||||||
@ -632,13 +637,10 @@ vector<Point2f> QRDecode::getQuadrilateral(vector<Point2f> angle_list)
|
|||||||
= intersectionLines(hull[index_hull], hull[next_index_hull],
|
= intersectionLines(hull[index_hull], hull[next_index_hull],
|
||||||
result_side_begin[0], result_side_end[0]);
|
result_side_begin[0], result_side_end[0]);
|
||||||
|
|
||||||
test_area = getQuadrilateralArea(test_result_angle_list[0],
|
test_diff_area = fabs(getPolygonArea(test_result_angle_list) - experimental_area);
|
||||||
test_result_angle_list[1],
|
if (min_diff_area > test_diff_area)
|
||||||
test_result_angle_list[2],
|
|
||||||
test_result_angle_list[3]);
|
|
||||||
if (min_area > test_area)
|
|
||||||
{
|
{
|
||||||
min_area = test_area;
|
min_diff_area = test_diff_area;
|
||||||
for (size_t i = 0; i < test_result_angle_list.size(); i++)
|
for (size_t i = 0; i < test_result_angle_list.size(); i++)
|
||||||
{
|
{
|
||||||
result_angle_list[i] = test_result_angle_list[i];
|
result_angle_list[i] = test_result_angle_list[i];
|
||||||
@ -652,48 +654,9 @@ vector<Point2f> QRDecode::getQuadrilateral(vector<Point2f> angle_list)
|
|||||||
index_hull = next_index_hull;
|
index_hull = next_index_hull;
|
||||||
}
|
}
|
||||||
while(index_hull != unstable_pnt);
|
while(index_hull != unstable_pnt);
|
||||||
|
|
||||||
if (norm(result_angle_list[0] - angle_list[2]) >
|
|
||||||
norm(angle_list[2] - angle_list[1]) / 3) { result_angle_list[0] = angle_list[2]; }
|
|
||||||
|
|
||||||
if (norm(result_angle_list[1] - angle_list[1]) >
|
|
||||||
norm(angle_list[1] - angle_list[0]) / 3) { result_angle_list[1] = angle_list[1]; }
|
|
||||||
|
|
||||||
if (norm(result_angle_list[2] - angle_list[0]) >
|
|
||||||
norm(angle_list[0] - angle_list[3]) / 3) { result_angle_list[2] = angle_list[0]; }
|
|
||||||
|
|
||||||
if (norm(result_angle_list[3] - angle_list[3]) >
|
|
||||||
norm(angle_list[3] - angle_list[2]) / 3) { result_angle_list[3] = angle_list[3]; }
|
|
||||||
|
|
||||||
return result_angle_list;
|
return result_angle_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
// b __________ c
|
|
||||||
// / |
|
|
||||||
// / |
|
|
||||||
// / S |
|
|
||||||
// / |
|
|
||||||
// a --------------- d
|
|
||||||
|
|
||||||
double QRDecode::getQuadrilateralArea(Point2f a, Point2f b, Point2f c, Point2f d)
|
|
||||||
{
|
|
||||||
double length_sides[4], perimeter = 0.0, result_area = 1.0;
|
|
||||||
length_sides[0] = norm(a - b); length_sides[1] = norm(b - c);
|
|
||||||
length_sides[2] = norm(c - d); length_sides[3] = norm(d - a);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 4; i++) { perimeter += length_sides[i]; }
|
|
||||||
perimeter /= 2;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
result_area *= (perimeter - length_sides[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
result_area = sqrt(result_area);
|
|
||||||
|
|
||||||
return result_area;
|
|
||||||
}
|
|
||||||
|
|
||||||
// b
|
// b
|
||||||
// / |
|
// / |
|
||||||
// / |
|
// / |
|
||||||
@ -704,21 +667,31 @@ double QRDecode::getQuadrilateralArea(Point2f a, Point2f b, Point2f c, Point2f d
|
|||||||
|
|
||||||
double QRDecode::getTriangleArea(Point2f a, Point2f b, Point2f c)
|
double QRDecode::getTriangleArea(Point2f a, Point2f b, Point2f c)
|
||||||
{
|
{
|
||||||
double length_sides[3], perimeter = 0.0, triangle_area = 1.0;
|
double norm_sides[] = { norm(a - b), norm(b - c), norm(c - a) };
|
||||||
length_sides[0] = norm(a - b);
|
double half_perimeter = (norm_sides[0] + norm_sides[1] + norm_sides[2]) / 2.0;
|
||||||
length_sides[1] = norm(b - c);
|
double triangle_area = sqrt(half_perimeter *
|
||||||
length_sides[2] = norm(c - a);
|
(half_perimeter - norm_sides[0]) *
|
||||||
for (size_t i = 0; i < 3; i++) { perimeter += length_sides[i]; }
|
(half_perimeter - norm_sides[1]) *
|
||||||
perimeter /= 2;
|
(half_perimeter - norm_sides[2]));
|
||||||
for (size_t i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
triangle_area *= (perimeter - length_sides[i]);
|
|
||||||
}
|
|
||||||
triangle_area += sqrt(triangle_area);
|
|
||||||
|
|
||||||
return triangle_area;
|
return triangle_area;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double QRDecode::getPolygonArea(vector<Point2f> points)
|
||||||
|
{
|
||||||
|
CV_Assert(points.size() >= 3);
|
||||||
|
if (points.size() == 3)
|
||||||
|
{ return getTriangleArea(points[0], points[1], points[2]); }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double result_area = 0.0;
|
||||||
|
for (size_t i = 1; i < points.size() - 1; i++)
|
||||||
|
{
|
||||||
|
result_area += getTriangleArea(points[0], points[i], points[i + 1]);
|
||||||
|
}
|
||||||
|
return result_area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// / | b
|
// / | b
|
||||||
// / |
|
// / |
|
||||||
// / |
|
// / |
|
||||||
|
Loading…
Reference in New Issue
Block a user