1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-28 23:03:03 +04:00

Merge pull request #22025 from AleksandrPanov:fix_samplingForVersion_multiplyingFactor

Fix sampling for version multiplying factor

* reduce experimentalFrequencyElem and listFrequencyElem

* fix large resize

* fix tile in postIntermediate

* add getMinSideLen(), add corrected_index

* add test decode_regression_21929 author Kumataro, add test decode_regression_version_25
This commit is contained in:
Alexander Panov
2022-06-04 17:33:08 +03:00
committed by GitHub
parent c26c4a61c6
commit 53eda42da7
3 changed files with 116 additions and 40 deletions
+39 -37
View File
@@ -1070,6 +1070,15 @@ protected:
};
};
float static getMinSideLen(const vector<Point2f> &points) {
CV_Assert(points.size() == 4ull);
double res = norm(points[1]-points[0]);
for (size_t i = 1ull; i < points.size(); i++) {
res = min(res, norm(points[i]-points[(i+1ull) % points.size()]));
}
return static_cast<float>(res);
}
void QRDecode::init(const Mat &src, const vector<Point2f> &points)
{
CV_TRACE_FUNCTION();
@@ -1081,7 +1090,7 @@ void QRDecode::init(const Mat &src, const vector<Point2f> &points)
original_points = bbox;
version = 0;
version_size = 0;
test_perspective_size = 251;
test_perspective_size = max(getMinSideLen(points)+1.f, 251.f);
result_info = "";
}
@@ -2096,7 +2105,7 @@ bool QRDecode::straightenQRCodeInParts()
{
return false;
}
float perspective_curved_size = 251.0;
float perspective_curved_size = max(getMinSideLen(original_points)+1.f, 251.f);;
const Size temporary_size(cvRound(perspective_curved_size), cvRound(perspective_curved_size));
float dist = perspective_curved_size / (number_pnts_to_cut - 1);
@@ -2367,9 +2376,9 @@ bool QRDecode::versionDefinition()
bool QRDecode::samplingForVersion()
{
CV_TRACE_FUNCTION();
const double multiplyingFactor = (version < 3) ? 1 :
(version == 3) ? 1.5 :
version * (version + 1);
const double multiplyingFactor = (version < 3) ? 1. :
(version == 3) ? 2. :
3.;
const Size newFactorSize(
cvRound(no_border_intermediate.size().width * multiplyingFactor),
cvRound(no_border_intermediate.size().height * multiplyingFactor));
@@ -2378,45 +2387,38 @@ bool QRDecode::samplingForVersion()
const int delta_rows = cvRound((postIntermediate.rows * 1.0) / version_size);
const int delta_cols = cvRound((postIntermediate.cols * 1.0) / version_size);
// number of elements in the tail
const int skipped_rows = postIntermediate.rows - delta_rows * version_size;
const int skipped_cols = postIntermediate.cols - delta_cols * version_size;
vector<double> listFrequencyElem;
for (int r = 0; r < postIntermediate.rows; r += delta_rows)
{
for (int c = 0; c < postIntermediate.cols; c += delta_cols)
{
vector<int> deltas_rows(version_size, delta_rows);
vector<int> deltas_cols(version_size, delta_cols);
for (int i = 0; i < abs(skipped_rows); i++) {
// fix deltas_rows at each skip_step
const double skip_step = static_cast<double>(version_size)/abs(skipped_rows);
const int corrected_index = static_cast<int>(i*skip_step + skip_step/2);
deltas_rows[corrected_index] += skipped_rows > 0 ? 1 : -1;
}
for (int i = 0; i < abs(skipped_cols); i++) {
// fix deltas_cols at each skip_step
const double skip_step = static_cast<double>(version_size)/abs(skipped_cols);
const int corrected_index = static_cast<int>(i*skip_step + skip_step/2);
deltas_cols[corrected_index] += skipped_cols > 0 ? 1 : -1;
}
const double totalFrequencyElem = countNonZero(postIntermediate) / static_cast<double>(postIntermediate.total());
straight = Mat(Size(version_size, version_size), CV_8UC1, Scalar(0));
for (int r = 0, i = 0; i < version_size; r += deltas_rows[i], i++) {
for (int c = 0, j = 0; j < version_size; c += deltas_cols[j], j++) {
Mat tile = postIntermediate(
Range(r, min(r + delta_rows, postIntermediate.rows)),
Range(c, min(c + delta_cols, postIntermediate.cols)));
const double frequencyElem = (countNonZero(tile) * 1.0) / tile.total();
listFrequencyElem.push_back(frequencyElem);
straight.ptr<uint8_t>(i)[j] = (frequencyElem < totalFrequencyElem) ? 0 : 255;
}
}
double dispersionEFE = std::numeric_limits<double>::max();
double experimentalFrequencyElem = 0;
for (double expVal = 0; expVal < 1; expVal+=0.001)
{
double testDispersionEFE = 0.0;
for (size_t i = 0; i < listFrequencyElem.size(); i++)
{
testDispersionEFE += (listFrequencyElem[i] - expVal) *
(listFrequencyElem[i] - expVal);
}
testDispersionEFE /= (listFrequencyElem.size() - 1);
if (dispersionEFE > testDispersionEFE)
{
dispersionEFE = testDispersionEFE;
experimentalFrequencyElem = expVal;
}
}
straight = Mat(Size(version_size, version_size), CV_8UC1, Scalar(0));
for (int r = 0; r < version_size * version_size; r++)
{
int i = r / straight.cols;
int j = r % straight.cols;
straight.ptr<uint8_t>(i)[j] = (listFrequencyElem[r] < experimentalFrequencyElem) ? 0 : 255;
}
return true;
}