Detection and decoding of curved QR-codes#18003
Conversation
Co-authored-by: Nesterov Alexander <nesoldr@gmail.com>
bb90559 to
79a37c5
Compare
89e1815 to
f67ef55
Compare
f67ef55 to
a243657
Compare
| } | ||
| num_points_at_side += it->second.size(); | ||
| } | ||
| mean_step /= num_points_at_side; |
There was a problem hiding this comment.
please add test for check zero divided
modules/objdetect/src/qrcode.cpp
Outdated
| int count = -1; | ||
| for(size_t j = 0; j < it->second.size() - 1; j++) | ||
| { | ||
| count++; |
modules/objdetect/src/qrcode.cpp
Outdated
| for (it=complete_curved_sides.begin(); it!=complete_curved_sides.end(); ++it) | ||
| { | ||
| int count = -1; | ||
| for(size_t j = 0; j < it->second.size() - 1; j++) |
There was a problem hiding this comment.
please replace all constants outside cycles because cycle call size() function every iteration
modules/objdetect/src/qrcode.cpp
Outdated
| return true; | ||
| } | ||
|
|
||
| vector<vector<float> > QRDecode::computeSpline(vector<int> &x_arr, vector<int> &y_arr) |
There was a problem hiding this comment.
| vector<vector<float> > QRDecode::computeSpline(vector<int> &x_arr, vector<int> &y_arr) | |
| vector<vector<float> > QRDecode::computeSpline(const vector<int> &x_arr, const vector<int> &y_arr) |
modules/objdetect/src/qrcode.cpp
Outdated
|
|
||
| vector<vector<float> > QRDecode::computeSpline(vector<int> &x_arr, vector<int> &y_arr) | ||
| { | ||
| int n = (int)y_arr.size(); |
There was a problem hiding this comment.
| int n = (int)y_arr.size(); | |
| const int n = (int)y_arr.size(); |
modules/objdetect/src/qrcode.cpp
Outdated
| { | ||
| if ((x > x_arr[i]) && (x <= x_arr[i + 1])) | ||
| { | ||
| float y = S[i][0] + S[i][1] * (x - x_arr[i]) + S[i][2] * pow((x - x_arr[i]), 2) |
There was a problem hiding this comment.
please use multiplication instead pow
modules/objdetect/src/qrcode.cpp
Outdated
| x_arr.push_back(cvRound(spline_points[j].x)); | ||
| y_arr.push_back(cvRound(spline_points[j].y)); | ||
| } | ||
| if (abs(x_arr.front() - x_arr.back()) > abs(y_arr.front() - y_arr.back())) |
There was a problem hiding this comment.
please use swap between x and y for calculate only one condition branch
|
|
||
| bool QRDecode::divideIntoEvenSegments(vector<vector<Point2f> > &segments_points) | ||
| { | ||
| vector<vector<Point2f> > spline_lines(NUM_SIDES); |
modules/objdetect/src/qrcode.cpp
Outdated
| mean_num_points_in_line += spline_lines[i].size(); | ||
| } | ||
| mean_num_points_in_line /= NUM_SIDES; | ||
| int min_num_points = 1, max_num_points = cvRound(mean_num_points_in_line / 2.0); |
There was a problem hiding this comment.
| int min_num_points = 1, max_num_points = cvRound(mean_num_points_in_line / 2.0); | |
| const int min_num_points = 1, max_num_points = cvRound(mean_num_points_in_line / 2.0); |
modules/objdetect/src/qrcode.cpp
Outdated
| mean_of_two_sides += mean_dist_in_segment; | ||
| } | ||
| mean_of_two_sides /= NUM_SIDES; | ||
| if (mean_of_two_sides < 0.5) |
modules/objdetect/src/qrcode.cpp
Outdated
| if (abs(temp_point_start.x - temp_point_end.x) > | ||
| abs(temp_point_start.y - temp_point_end.y)) | ||
| { | ||
| if(segments_points[i].front().y > segments_points[(i+1)%2].front().y) | ||
| { | ||
| current_curved_side = segments_points[i]; | ||
| opposite_curved_side = segments_points[(i+1)%2]; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| if(segments_points[i].front().x < segments_points[(i+1)%2].front().x) | ||
| { | ||
| current_curved_side = segments_points[i]; | ||
| opposite_curved_side = segments_points[(i+1)%2]; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
please revise conditions (maybe you can do it simpler)
modules/objdetect/src/qrcode.cpp
Outdated
| if (complete_curved_sides.size() < 2) | ||
| { | ||
| for (size_t i = 0; i < NUM_SIDES; i++) | ||
| { | ||
| if(complete_curved_sides.count(curved_indexes[i]) == 0) | ||
| { | ||
| int idx_second_cur_side = curved_indexes[i]; | ||
| complete_curved_sides.insert(std::pair<int,vector<Point> >(idx_second_cur_side, sides_points[idx_second_cur_side])); | ||
| } | ||
| } | ||
| } | ||
| std::map<int,vector<Point> >::iterator it; | ||
| for (it = complete_curved_sides.begin(); it != complete_curved_sides.end(); ++it) | ||
| { | ||
| Point p1 = it->second.front(); | ||
| Point p2 = it->second.back(); | ||
| if (abs(p1.x - p2.x) > abs(p1.y - p2.y)) | ||
| { | ||
| sort(it->second.begin(), it->second.end(), sortPointsByX()); | ||
| } | ||
| else | ||
| { | ||
| sort(it->second.begin(), it->second.end(), sortPointsByY()); | ||
| } | ||
| } |
There was a problem hiding this comment.
please add it into new method
modules/objdetect/src/qrcode.cpp
Outdated
| CV_TRACE_FUNCTION(); | ||
| const double multiplyingFactor = (version < 3) ? 1 : | ||
| (version == 3) ? 1.5 : | ||
| version * (5 + version - 4); |
There was a problem hiding this comment.
| version * (5 + version - 4); | |
| version * (version + 1); |
872654c to
5d3f886
Compare
5d3f886 to
7380ea4
Compare
modules/objdetect/src/qrcode.cpp
Outdated
| ((a1.x * a2.y - a1.y * a2.x) * (b1.x - b2.x) - | ||
| (b1.x * b2.y - b1.y * b2.x) * (a1.x - a2.x)) / | ||
| ((a1.x - a2.x) * (b1.y - b2.y) - | ||
| (a1.y - a2.y) * (b1.x - b2.x)), |
There was a problem hiding this comment.
divisor should be pre-calculated and checked for 0 (eps tolerance) or NaNs.
Or ensure that caller works well with Inf/NaN values and filter them out later.
modules/objdetect/src/qrcode.cpp
Outdated
| if (sqrt(A*A + B*B) == 0) return 0; | ||
| result = abs((A * a.x - B * a.y + C)) / sqrt(A*A + B*B); |
There was a problem hiding this comment.
Avoid calculation of sqrt() expression twice.
modules/objdetect/src/qrcode.cpp
Outdated
| } | ||
| num_points_at_side += num_points_at_pattern; | ||
| } | ||
| if (num_points_at_side == 0) { return false; } |
There was a problem hiding this comment.
Please use separate line for if body, even for simple cases.
It is important to see the real code coverage.
a06167d to
064142a
Compare
064142a to
8d05d93
Compare
|
Hi! Last year, I defended my PhD in Engineering and Applied Science, regarding a thesis which involved huge use of QR Codes, at the time we didn't realize OpenCV had included a curved QR Code decoder, it is amazing the work the community has been done in recent years. In the thesis, we tackled the recovery of QR Codes from curved surfaces using Thin Plate Splines (Chapter 3 of https://diposit.ub.edu/dspace/bitstream/2445/185845/1/IBA_PhD_THESIS.pdf). Is there any paper regarding the implementation here presented of the use of splines to extract the QR Code? If we understand correctly, the above presented method uses the splines to fit the outer contour of the QR Code? We would like to be able to compare our method and the one presented here, and if able to present the research of the comparison and later attempt to make a pull request. TL;DR: Looking for a paper related with this method. |
These changes add detection and decoding of curved QR-codes