mirror of
https://github.com/opencv/opencv.git
synced 2025-06-18 16:11:50 +08:00
Added bugfix and some tests
This commit is contained in:
parent
93d1785820
commit
82c2aa6e65
@ -74,6 +74,17 @@ PERF_TEST_P_(Perf_Objdetect_Not_QRCode, detect)
|
|||||||
RNG rng;
|
RNG rng;
|
||||||
rng.fill(not_qr_code, RNG::UNIFORM, Scalar(0), Scalar(1));
|
rng.fill(not_qr_code, RNG::UNIFORM, Scalar(0), Scalar(1));
|
||||||
}
|
}
|
||||||
|
if (type_gen == "chessboard")
|
||||||
|
{
|
||||||
|
uint8_t next_pixel = 0;
|
||||||
|
for (int r = 0; r < not_qr_code.rows * not_qr_code.cols; r++)
|
||||||
|
{
|
||||||
|
int i = r / not_qr_code.cols;
|
||||||
|
int j = r % not_qr_code.cols;
|
||||||
|
not_qr_code.ptr<uchar>(i)[j] = next_pixel;
|
||||||
|
next_pixel = 255 - next_pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QRCodeDetector qrcode;
|
QRCodeDetector qrcode;
|
||||||
TEST_CYCLE() ASSERT_FALSE(qrcode.detect(not_qr_code, corners));
|
TEST_CYCLE() ASSERT_FALSE(qrcode.detect(not_qr_code, corners));
|
||||||
@ -96,6 +107,17 @@ PERF_TEST_P_(Perf_Objdetect_Not_QRCode, decode)
|
|||||||
RNG rng;
|
RNG rng;
|
||||||
rng.fill(not_qr_code, RNG::UNIFORM, Scalar(0), Scalar(1));
|
rng.fill(not_qr_code, RNG::UNIFORM, Scalar(0), Scalar(1));
|
||||||
}
|
}
|
||||||
|
if (type_gen == "chessboard")
|
||||||
|
{
|
||||||
|
uint8_t next_pixel = 0;
|
||||||
|
for (int r = 0; r < not_qr_code.rows * not_qr_code.cols; r++)
|
||||||
|
{
|
||||||
|
int i = r / not_qr_code.cols;
|
||||||
|
int j = r % not_qr_code.cols;
|
||||||
|
not_qr_code.ptr<uchar>(i)[j] = next_pixel;
|
||||||
|
next_pixel = 255 - next_pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QRCodeDetector qrcode;
|
QRCodeDetector qrcode;
|
||||||
TEST_CYCLE() ASSERT_TRUE(qrcode.decode(not_qr_code, corners, straight_barcode).empty());
|
TEST_CYCLE() ASSERT_TRUE(qrcode.decode(not_qr_code, corners, straight_barcode).empty());
|
||||||
@ -105,8 +127,9 @@ PERF_TEST_P_(Perf_Objdetect_Not_QRCode, decode)
|
|||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_Not_QRCode,
|
INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_Not_QRCode,
|
||||||
::testing::Combine(
|
::testing::Combine(
|
||||||
::testing::Values("zero", "random"),
|
::testing::Values("zero", "random", "chessboard"),
|
||||||
::testing::Values(Size(640, 480), Size(1280, 720), Size(1920, 1080))
|
::testing::Values(Size(640, 480), Size(1280, 720),
|
||||||
|
Size(1920, 1080), Size(3840, 2160))
|
||||||
));
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ protected:
|
|||||||
|
|
||||||
void QRDetect::init(const Mat& src, double eps_vertical_, double eps_horizontal_)
|
void QRDetect::init(const Mat& src, double eps_vertical_, double eps_horizontal_)
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
CV_Assert(!src.empty());
|
CV_Assert(!src.empty());
|
||||||
const double min_side = std::min(src.size().width, src.size().height);
|
const double min_side = std::min(src.size().width, src.size().height);
|
||||||
if (min_side < 512.0)
|
if (min_side < 512.0)
|
||||||
@ -72,26 +73,26 @@ void QRDetect::init(const Mat& src, double eps_vertical_, double eps_horizontal_
|
|||||||
|
|
||||||
vector<Vec3d> QRDetect::searchHorizontalLines()
|
vector<Vec3d> QRDetect::searchHorizontalLines()
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
vector<Vec3d> result;
|
vector<Vec3d> result;
|
||||||
const int height_bin_barcode = bin_barcode.rows;
|
const int height_bin_barcode = bin_barcode.rows;
|
||||||
const int width_bin_barcode = bin_barcode.cols;
|
const int width_bin_barcode = bin_barcode.cols;
|
||||||
const size_t test_lines_size = 5;
|
const size_t test_lines_size = 5;
|
||||||
double test_lines[test_lines_size];
|
double test_lines[test_lines_size];
|
||||||
const size_t count_pixels_position = 1024;
|
vector<size_t> pixels_position;
|
||||||
size_t pixels_position[count_pixels_position];
|
|
||||||
size_t index = 0;
|
|
||||||
|
|
||||||
for (int y = 0; y < height_bin_barcode; y++)
|
for (int y = 0; y < height_bin_barcode; y++)
|
||||||
{
|
{
|
||||||
|
pixels_position.clear();
|
||||||
const uint8_t *bin_barcode_row = bin_barcode.ptr<uint8_t>(y);
|
const uint8_t *bin_barcode_row = bin_barcode.ptr<uint8_t>(y);
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
for (; pos < width_bin_barcode; pos++) { if (bin_barcode_row[pos] == 0) break; }
|
for (; pos < width_bin_barcode; pos++) { if (bin_barcode_row[pos] == 0) break; }
|
||||||
if (pos == width_bin_barcode) { continue; }
|
if (pos == width_bin_barcode) { continue; }
|
||||||
|
|
||||||
index = 0;
|
pixels_position.push_back(pos);
|
||||||
pixels_position[index] = pixels_position[index + 1] = pixels_position[index + 2] = pos;
|
pixels_position.push_back(pos);
|
||||||
index +=3;
|
pixels_position.push_back(pos);
|
||||||
|
|
||||||
uint8_t future_pixel = 255;
|
uint8_t future_pixel = 255;
|
||||||
for (int x = pos; x < width_bin_barcode; x++)
|
for (int x = pos; x < width_bin_barcode; x++)
|
||||||
@ -99,13 +100,11 @@ vector<Vec3d> QRDetect::searchHorizontalLines()
|
|||||||
if (bin_barcode_row[x] == future_pixel)
|
if (bin_barcode_row[x] == future_pixel)
|
||||||
{
|
{
|
||||||
future_pixel = 255 - future_pixel;
|
future_pixel = 255 - future_pixel;
|
||||||
pixels_position[index] = x;
|
pixels_position.push_back(x);
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pixels_position[index] = width_bin_barcode - 1;
|
pixels_position.push_back(width_bin_barcode - 1);
|
||||||
index++;
|
for (size_t i = 2; i < pixels_position.size() - 4; i+=2)
|
||||||
for (size_t i = 2; i < index - 4; i+=2)
|
|
||||||
{
|
{
|
||||||
test_lines[0] = static_cast<double>(pixels_position[i - 1] - pixels_position[i - 2]);
|
test_lines[0] = static_cast<double>(pixels_position[i - 1] - pixels_position[i - 2]);
|
||||||
test_lines[1] = static_cast<double>(pixels_position[i ] - pixels_position[i - 1]);
|
test_lines[1] = static_cast<double>(pixels_position[i ] - pixels_position[i - 1]);
|
||||||
@ -120,8 +119,8 @@ vector<Vec3d> QRDetect::searchHorizontalLines()
|
|||||||
if (length == 0) { continue; }
|
if (length == 0) { continue; }
|
||||||
for (size_t j = 0; j < test_lines_size; j++)
|
for (size_t j = 0; j < test_lines_size; j++)
|
||||||
{
|
{
|
||||||
if (j == 2) { weight += fabs((test_lines[j] / length) - 3.0/7.0); }
|
if (j != 2) { weight += fabs((test_lines[j] / length) - 1.0/7.0); }
|
||||||
else { weight += fabs((test_lines[j] / length) - 1.0/7.0); }
|
else { weight += fabs((test_lines[j] / length) - 3.0/7.0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (weight < eps_vertical)
|
if (weight < eps_vertical)
|
||||||
@ -139,6 +138,7 @@ vector<Vec3d> QRDetect::searchHorizontalLines()
|
|||||||
|
|
||||||
vector<Point2f> QRDetect::separateVerticalLines(const vector<Vec3d> &list_lines)
|
vector<Point2f> QRDetect::separateVerticalLines(const vector<Vec3d> &list_lines)
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
vector<Vec3d> result;
|
vector<Vec3d> result;
|
||||||
int temp_length = 0;
|
int temp_length = 0;
|
||||||
uint8_t next_pixel;
|
uint8_t next_pixel;
|
||||||
@ -157,7 +157,7 @@ vector<Point2f> QRDetect::separateVerticalLines(const vector<Vec3d> &list_lines)
|
|||||||
|
|
||||||
for (int j = y; j < bin_barcode.rows - 1; j++)
|
for (int j = y; j < bin_barcode.rows - 1; j++)
|
||||||
{
|
{
|
||||||
next_pixel = bin_barcode.at<uint8_t>(j + 1, x);
|
next_pixel = bin_barcode.ptr<uint8_t>(j + 1)[x];
|
||||||
temp_length++;
|
temp_length++;
|
||||||
if (next_pixel == future_pixel_up)
|
if (next_pixel == future_pixel_up)
|
||||||
{
|
{
|
||||||
@ -173,7 +173,7 @@ vector<Point2f> QRDetect::separateVerticalLines(const vector<Vec3d> &list_lines)
|
|||||||
uint8_t future_pixel_down = 255;
|
uint8_t future_pixel_down = 255;
|
||||||
for (int j = y; j >= 1; j--)
|
for (int j = y; j >= 1; j--)
|
||||||
{
|
{
|
||||||
next_pixel = bin_barcode.at<uint8_t>(j - 1, x);
|
next_pixel = bin_barcode.ptr<uint8_t>(j - 1)[x];
|
||||||
temp_length++;
|
temp_length++;
|
||||||
if (next_pixel == future_pixel_down)
|
if (next_pixel == future_pixel_down)
|
||||||
{
|
{
|
||||||
@ -195,8 +195,8 @@ vector<Point2f> QRDetect::separateVerticalLines(const vector<Vec3d> &list_lines)
|
|||||||
CV_Assert(length > 0);
|
CV_Assert(length > 0);
|
||||||
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 += fabs((test_lines[i] / length) - 3.0/14.0); }
|
if (i % 3 != 0) { weight += fabs((test_lines[i] / length) - 1.0/ 7.0); }
|
||||||
else { weight += fabs((test_lines[i] / length) - 1.0/ 7.0); }
|
else { weight += fabs((test_lines[i] / length) - 3.0/14.0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if(weight < eps_horizontal)
|
if(weight < eps_horizontal)
|
||||||
@ -218,7 +218,7 @@ vector<Point2f> QRDetect::separateVerticalLines(const vector<Vec3d> &list_lines)
|
|||||||
|
|
||||||
void QRDetect::fixationPoints(vector<Point2f> &local_point)
|
void QRDetect::fixationPoints(vector<Point2f> &local_point)
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
double cos_angles[3], norm_triangl[3];
|
double cos_angles[3], norm_triangl[3];
|
||||||
|
|
||||||
norm_triangl[0] = norm(local_point[1] - local_point[2]);
|
norm_triangl[0] = norm(local_point[1] - local_point[2]);
|
||||||
@ -311,6 +311,7 @@ void QRDetect::fixationPoints(vector<Point2f> &local_point)
|
|||||||
|
|
||||||
bool QRDetect::localization()
|
bool QRDetect::localization()
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
Point2f begin, end;
|
Point2f begin, end;
|
||||||
vector<Vec3d> list_lines_x = searchHorizontalLines();
|
vector<Vec3d> list_lines_x = searchHorizontalLines();
|
||||||
if( list_lines_x.empty() ) { return false; }
|
if( list_lines_x.empty() ) { return false; }
|
||||||
@ -356,6 +357,7 @@ bool QRDetect::localization()
|
|||||||
|
|
||||||
bool QRDetect::computeTransformationPoints()
|
bool QRDetect::computeTransformationPoints()
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
if (localization_points.size() != 3) { return false; }
|
if (localization_points.size() != 3) { return false; }
|
||||||
|
|
||||||
vector<Point> locations, non_zero_elem[3], newHull;
|
vector<Point> locations, non_zero_elem[3], newHull;
|
||||||
@ -367,8 +369,7 @@ bool QRDetect::computeTransformationPoints()
|
|||||||
int count_test_lines = 0, index = cvRound(localization_points[i].x);
|
int count_test_lines = 0, index = cvRound(localization_points[i].x);
|
||||||
for (; index < bin_barcode.cols - 1; index++)
|
for (; index < bin_barcode.cols - 1; index++)
|
||||||
{
|
{
|
||||||
next_pixel = bin_barcode.at<uint8_t>(
|
next_pixel = bin_barcode.ptr<uint8_t>(cvRound(localization_points[i].y))[index + 1];
|
||||||
cvRound(localization_points[i].y), index + 1);
|
|
||||||
if (next_pixel == future_pixel)
|
if (next_pixel == future_pixel)
|
||||||
{
|
{
|
||||||
future_pixel = 255 - future_pixel;
|
future_pixel = 255 - future_pixel;
|
||||||
@ -495,6 +496,7 @@ Point2f QRDetect::intersectionLines(Point2f a1, Point2f a2, Point2f b1, Point2f
|
|||||||
// test function (if true then ------> else <------ )
|
// test function (if true then ------> else <------ )
|
||||||
bool QRDetect::testBypassRoute(vector<Point2f> hull, int start, int finish)
|
bool QRDetect::testBypassRoute(vector<Point2f> hull, int start, int finish)
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
int index_hull = start, next_index_hull, hull_size = (int)hull.size();
|
int index_hull = start, next_index_hull, hull_size = (int)hull.size();
|
||||||
double test_length[2] = { 0.0, 0.0 };
|
double test_length[2] = { 0.0, 0.0 };
|
||||||
do
|
do
|
||||||
@ -521,6 +523,7 @@ bool QRDetect::testBypassRoute(vector<Point2f> hull, int start, int finish)
|
|||||||
|
|
||||||
vector<Point2f> QRDetect::getQuadrilateral(vector<Point2f> angle_list)
|
vector<Point2f> QRDetect::getQuadrilateral(vector<Point2f> angle_list)
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
size_t angle_size = angle_list.size();
|
size_t angle_size = angle_list.size();
|
||||||
uint8_t value, mask_value;
|
uint8_t value, mask_value;
|
||||||
Mat mask = Mat::zeros(bin_barcode.rows + 2, bin_barcode.cols + 2, CV_8UC1);
|
Mat mask = Mat::zeros(bin_barcode.rows + 2, bin_barcode.cols + 2, CV_8UC1);
|
||||||
@ -828,6 +831,7 @@ protected:
|
|||||||
|
|
||||||
void QRDecode::init(const Mat &src, const vector<Point2f> &points)
|
void QRDecode::init(const Mat &src, const vector<Point2f> &points)
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
original = src.clone();
|
original = src.clone();
|
||||||
intermediate = Mat::zeros(src.size(), CV_8UC1);
|
intermediate = Mat::zeros(src.size(), CV_8UC1);
|
||||||
original_points = points;
|
original_points = points;
|
||||||
@ -839,6 +843,7 @@ void QRDecode::init(const Mat &src, const vector<Point2f> &points)
|
|||||||
|
|
||||||
bool QRDecode::updatePerspective()
|
bool QRDecode::updatePerspective()
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
const Point2f centerPt = QRDetect::intersectionLines(original_points[0], original_points[2],
|
const Point2f centerPt = QRDetect::intersectionLines(original_points[0], original_points[2],
|
||||||
original_points[1], original_points[3]);
|
original_points[1], original_points[3]);
|
||||||
if (cvIsNaN(centerPt.x) || cvIsNaN(centerPt.y))
|
if (cvIsNaN(centerPt.x) || cvIsNaN(centerPt.y))
|
||||||
@ -887,6 +892,7 @@ inline Point computeOffset(const vector<Point>& v)
|
|||||||
|
|
||||||
bool QRDecode::versionDefinition()
|
bool QRDecode::versionDefinition()
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
LineIterator line_iter(intermediate, Point2f(0, 0), Point2f(test_perspective_size, test_perspective_size));
|
LineIterator line_iter(intermediate, Point2f(0, 0), Point2f(test_perspective_size, test_perspective_size));
|
||||||
Point black_point = Point(0, 0);
|
Point black_point = Point(0, 0);
|
||||||
for(int j = 0; j < line_iter.count; j++, ++line_iter)
|
for(int j = 0; j < line_iter.count; j++, ++line_iter)
|
||||||
@ -949,6 +955,7 @@ bool QRDecode::versionDefinition()
|
|||||||
|
|
||||||
bool QRDecode::samplingForVersion()
|
bool QRDecode::samplingForVersion()
|
||||||
{
|
{
|
||||||
|
CV_TRACE_FUNCTION();
|
||||||
const double multiplyingFactor = (version < 3) ? 1 :
|
const double multiplyingFactor = (version < 3) ? 1 :
|
||||||
(version == 3) ? 1.5 :
|
(version == 3) ? 1.5 :
|
||||||
version * (5 + version - 4);
|
version * (5 + version - 4);
|
||||||
@ -958,21 +965,20 @@ bool QRDecode::samplingForVersion()
|
|||||||
Mat postIntermediate(newFactorSize, CV_8UC1);
|
Mat postIntermediate(newFactorSize, CV_8UC1);
|
||||||
resize(no_border_intermediate, postIntermediate, newFactorSize, 0, 0, INTER_AREA);
|
resize(no_border_intermediate, postIntermediate, newFactorSize, 0, 0, INTER_AREA);
|
||||||
|
|
||||||
const int no_inter_rows = postIntermediate.rows;
|
const int delta_rows = cvRound((postIntermediate.rows * 1.0) / version_size);
|
||||||
const int no_inter_cols = postIntermediate.cols;
|
const int delta_cols = cvRound((postIntermediate.cols * 1.0) / version_size);
|
||||||
const int delta_rows = cvRound((no_inter_rows * 1.0) / version_size);
|
|
||||||
const int delta_cols = cvRound((no_inter_cols * 1.0) / version_size);
|
|
||||||
|
|
||||||
vector<double> listFrequencyElem;
|
vector<double> listFrequencyElem(version_size * version_size, 0);
|
||||||
for (int r = 0; r < no_inter_rows; r += delta_rows)
|
int k = 0;
|
||||||
|
for (int r = 0; r < postIntermediate.rows; r += delta_rows)
|
||||||
{
|
{
|
||||||
for (int c = 0; c < no_inter_cols; c += delta_cols)
|
for (int c = 0; c < postIntermediate.cols; c += delta_cols)
|
||||||
{
|
{
|
||||||
Mat tile = postIntermediate(
|
Mat tile = postIntermediate(
|
||||||
Range(r, min(r + delta_rows, no_inter_rows)),
|
Range(r, min(r + delta_rows, postIntermediate.rows)),
|
||||||
Range(c, min(c + delta_cols, no_inter_cols)));
|
Range(c, min(c + delta_cols, postIntermediate.cols)));
|
||||||
const double frequencyElem = (countNonZero(tile) * 1.0) / tile.total();
|
const double frequencyElem = (countNonZero(tile) * 1.0) / tile.total();
|
||||||
listFrequencyElem.push_back(frequencyElem);
|
listFrequencyElem[k] = frequencyElem; k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -995,27 +1001,11 @@ bool QRDecode::samplingForVersion()
|
|||||||
}
|
}
|
||||||
|
|
||||||
straight = Mat(Size(version_size, version_size), CV_8UC1, Scalar(0));
|
straight = Mat(Size(version_size, version_size), CV_8UC1, Scalar(0));
|
||||||
size_t k = 0;
|
for (int r = 0; r < version_size * version_size; r++)
|
||||||
for (int r = 0; r < no_inter_rows &&
|
|
||||||
k < listFrequencyElem.size() &&
|
|
||||||
floor((r * 1.0) / delta_rows) < version_size; r += delta_rows)
|
|
||||||
{
|
{
|
||||||
for (int c = 0; c < no_inter_cols &&
|
int i = r / straight.cols;
|
||||||
k < listFrequencyElem.size() &&
|
int j = r % straight.cols;
|
||||||
floor((c * 1.0) / delta_cols) < version_size; c += delta_cols, k++)
|
straight.ptr<uint8_t>(i)[j] = (listFrequencyElem[r] < experimentalFrequencyElem) ? 0 : 255;
|
||||||
{
|
|
||||||
Mat tile = postIntermediate(
|
|
||||||
Range(r, min(r + delta_rows, no_inter_rows)),
|
|
||||||
Range(c, min(c + delta_cols, no_inter_cols)));
|
|
||||||
|
|
||||||
if (listFrequencyElem[k] < experimentalFrequencyElem) { tile.setTo(0); }
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tile.setTo(255);
|
|
||||||
straight.at<uint8_t>(cvRound(floor((r * 1.0) / delta_rows)),
|
|
||||||
cvRound(floor((c * 1.0) / delta_cols))) = 255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1035,7 +1025,7 @@ bool QRDecode::decodingProcess()
|
|||||||
{
|
{
|
||||||
int position = y * qr_code.size + x;
|
int position = y * qr_code.size + x;
|
||||||
qr_code.cell_bitmap[position >> 3]
|
qr_code.cell_bitmap[position >> 3]
|
||||||
|= straight.at<uint8_t>(y, x) ? 0 : (1 << (position & 7));
|
|= straight.ptr<uint8_t>(y)[x] ? 0 : (1 << (position & 7));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user