Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions modules/barcode/misc/java/src/cpp/barcode_converters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ void Copy_vector_BarcodeType_to_List(JNIEnv* env, std::vector<cv::barcode::Barco
jmethodID m_clear = LIST_CLEAR(env, juArrayList);
env->CallVoidMethod(list, m_clear);

static jclass jInteger = env->FindClass("java/lang/Integer");
static jmethodID m_create_Integer = env->GetMethodID(jInteger, "<init>", "(I)V");
jclass jInteger = env->FindClass("java/lang/Integer");
jmethodID m_create_Integer = CONSTRUCTOR(env, jInteger);

for (size_t i = 0; i < vs.size(); ++i)
{
Expand Down
51 changes: 51 additions & 0 deletions modules/barcode/misc/java/test/BarcodeDetectorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.opencv.test.barcode;

import java.util.List;
import org.opencv.core.Mat;
import org.opencv.barcode.BarcodeDetector;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.test.OpenCVTestCase;
import java.util.ArrayList;
import static org.opencv.barcode.Barcode.EAN_13;

public class BarcodeDetectorTest extends OpenCVTestCase {

private final static String ENV_OPENCV_TEST_DATA_PATH = "OPENCV_TEST_DATA_PATH";
private String testDataPath;

@Override
protected void setUp() throws Exception {
super.setUp();

testDataPath = System.getenv(ENV_OPENCV_TEST_DATA_PATH);
if (testDataPath == null)
throw new Exception(ENV_OPENCV_TEST_DATA_PATH + " has to be defined!");
}

public void testDetectAndDecode() {
Mat img = Imgcodecs.imread(testDataPath + "/cv/barcode/multiple/4_barcodes.jpg");
assertFalse(img.empty());
BarcodeDetector detector = new BarcodeDetector();
assertNotNull(detector);
List < String > infos = new ArrayList< String >();
List < Integer > types = new ArrayList< Integer >();

boolean result = detector.detectAndDecode(img, infos, types);
assertTrue(result);
assertEquals(infos.size(), 4);
assertEquals(types.size(), 4);
final String[] correctResults = {"9787122276124", "9787118081473", "9787564350840", "9783319200064"};
for (int i = 0; i < 4; i++) {
assertEquals(types.get(i).intValue(), EAN_13);
result = false;
for (int j = 0; j < 4; j++) {
if (correctResults[j].equals(infos.get(i))) {
result = true;
break;
}
}
assertTrue(result);
}

}
}
30 changes: 30 additions & 0 deletions modules/barcode/misc/python/test/test_barcode_detector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env python
'''
===============================================================================
Barcode detect and decode pipeline.
===============================================================================
'''
import os
import numpy as np
import cv2 as cv

from tests_common import NewOpenCVTests

class barcode_detector_test(NewOpenCVTests):

def test_detect(self):
img = cv.imread(os.path.join(self.extraTestDataPath, 'cv/barcode/multiple/4_barcodes.jpg'))
self.assertFalse(img is None)
detector = cv.barcode_BarcodeDetector()
retval, corners = detector.detect(img)
self.assertTrue(retval)
self.assertEqual(corners.shape, (4, 4, 2))

def test_detect_and_decode(self):
img = cv.imread(os.path.join(self.extraTestDataPath, 'cv/barcode/single/book.jpg'))
self.assertFalse(img is None)
detector = cv.barcode_BarcodeDetector()
retval, decoded_info, decoded_type, corners = detector.detectAndDecode(img)
self.assertEqual(decoded_info[0], "9787115279460")
self.assertEqual(decoded_type[0], cv.barcode.EAN_13)
self.assertEqual(corners.shape, (1, 4, 2))
33 changes: 15 additions & 18 deletions modules/barcode/src/barcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,30 +130,17 @@ struct BarcodeDetector::Impl

~Impl() = default;

vector<Mat> initDecode(const Mat &src, const vector<Point2f> &points) const;
vector<Mat> initDecode(const Mat &src, const vector<vector<Point2f>> &points) const;

std::shared_ptr<SuperScale> sr;
bool use_nn_sr = false;
};

// return cropped and scaled bar img
vector<Mat> BarcodeDetector::Impl::initDecode(const Mat &src, const vector<Point2f> &points) const
vector<Mat> BarcodeDetector::Impl::initDecode(const Mat &src, const vector<vector<Point2f>> &points) const
{
vector<vector<Point2f>> src_points;
CV_Assert(!points.empty());
CV_Assert((points.size() % 4) == 0);
src_points.clear();
for (int i = 0; (uint) i < points.size(); i += 4)
{
vector<Point2f> tempMat{points.cbegin() + i, points.cbegin() + i + 4};
if (contourArea(tempMat) > 0.0)
{
src_points.push_back(tempMat);
}
}
CV_Assert(!src_points.empty());
vector<Mat> bar_imgs;
for (auto &corners : src_points)
for (auto &corners : points)
{
Mat bar_img;
cropROI(src, bar_img, corners);
Expand Down Expand Up @@ -224,8 +211,18 @@ bool BarcodeDetector::decode(InputArray img, InputArray points, vector<std::stri
}
CV_Assert(points.size().width > 0);
CV_Assert((points.size().width % 4) == 0);
vector<Point2f> src_points;
points.copyTo(src_points);
vector<vector<Point2f>> src_points;
Mat bar_points = points.getMat();
bar_points = bar_points.reshape(2, 1);
for (int i = 0; i < bar_points.size().width; i += 4)
{
vector<Point2f> tempMat = bar_points.colRange(i, i + 4);
if (contourArea(tempMat) > 0.0)
{
src_points.push_back(tempMat);
}
}
CV_Assert(!src_points.empty());
vector<Mat> bar_imgs = p->initDecode(inarr, src_points);
BarDecode bardec;
bardec.init(bar_imgs);
Expand Down
4 changes: 2 additions & 2 deletions modules/barcode/src/decoder/abs_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ patternMatchVariance(const Counter &counter, const std::vector<int> &pattern, ui
// If we don't even have one pixel per unit of bar width, assume this is too small
// to reliably match, so fail:
// and use constexpr functions
return std::numeric_limits<uint>::max();// max
return WHITE;// max
}
// We're going to fake floating-point math in integers. We just need to use more bits.
// Scale up patternLength so that intermediate values below like scaledCounter will have
Expand All @@ -89,7 +89,7 @@ patternMatchVariance(const Counter &counter, const std::vector<int> &pattern, ui
uint variance = std::abs(cnt - scaledPattern);
if (variance > maxIndividualVariance)
{
return std::numeric_limits<uint>::max();
return WHITE;
}
totalVariance += variance;
}
Expand Down
4 changes: 2 additions & 2 deletions modules/barcode/src/decoder/abs_decoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace cv {
namespace barcode {
using std::string;
using std::vector;
constexpr static int BLACK = std::numeric_limits<uchar>::min();
constexpr static uchar BLACK = std::numeric_limits<uchar>::min();
// WHITE elemental area is 0xff
constexpr static int WHITE = std::numeric_limits<uchar>::max();
constexpr static uchar WHITE = std::numeric_limits<uchar>::max();


struct Result
Expand Down
24 changes: 13 additions & 11 deletions modules/barcode/src/decoder/upcean_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,17 @@ std::pair<Result, float> UPCEANDecoder::decodeROI(const Mat &bar_img) const
std::string max_result;
BarcodeType max_type = BarcodeType::NONE;

int step = bar_img.rows / (DIVIDE_PART + BIAS_PART);
const int step = bar_img.rows / (DIVIDE_PART + BIAS_PART);
Result result;
int row_num;
for (int i = 0; i < DIVIDE_PART; ++i)
{
const auto *ptr = bar_img.ptr<uchar>(i * step);
row_num = (i + BIAS_PART / 2) * step;
if (row_num < 0 || row_num > bar_img.rows)
{
continue;
}
const auto *ptr = bar_img.ptr<uchar>(row_num);
vector<uchar> line(ptr, ptr + bar_img.cols);
result = decodeLine(line);
if (result.format != BarcodeType::NONE)
Expand All @@ -159,21 +165,17 @@ std::pair<Result, float> UPCEANDecoder::decodeROI(const Mat &bar_img) const
if (result_vote[result.result] > vote_cnt)
{
vote_cnt = result_vote[result.result];
if ((vote_cnt << 1) > total_vote)
{
max_result = result.result;
max_type = result.format;
}
max_result = result.result;
max_type = result.format;
}
}
}

float confidence = 0;
if (total_vote != 0)
if (total_vote == 0 || (vote_cnt << 2) < total_vote)
{
confidence = (float) vote_cnt / (float) total_vote;
return std::make_pair(Result(string(), BarcodeType::NONE), 0.0f);
}

float confidence = (float) vote_cnt / (float) DIVIDE_PART;
//Check if it is UPC-A format
if (max_type == BarcodeType::EAN_13 && max_result[0] == '0')
{
Expand Down
2 changes: 1 addition & 1 deletion modules/barcode/src/detector/bardetect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ bool Detect::computeTransformationPoints()
void Detect::preprocess()
{
Mat scharr_x, scharr_y, temp;
static constexpr double THRESHOLD_MAGNITUDE = 56.;
static constexpr double THRESHOLD_MAGNITUDE = 64.;
Scharr(resized_barcode, scharr_x, CV_32F, 1, 0);
Scharr(resized_barcode, scharr_y, CV_32F, 0, 1);
// calculate magnitude of gradient and truncate
Expand Down