关于二维码的识别

前些日子做 二维码识别。二维码识别有一个技巧,就是 二维码定位,

然后使用多次尝试全局二值化,局部二值化,可以提高 低质量的 二维码的识别率。

全局二值化 可以将 OTSU的阈值,进行 上下浮动阶梯二值化。

局部二值化 可以结合多个方法, 比如 wolf,niblack等。

识别库主要是集成 Zbar或者 Zxing库。

我写了个测试工具专门测试 Zbar或者 Zxing.

随便从网上下载了截图了几个 二维码测试:

zbar识别如下:

zxing测试如下:

很多人说,zbar比 zxing快,其实主要是参数配置问题。

zxing 需要配置对应的识别器, zbar默认开启它支持的识别器。

zxing主要代码如下:

COMMON_LIB_DECL vector<zxing_out> zxing_decode(const Mat& img, const string& fmt = "QR_CODE")
{
	zxing::Ref<zxing::LuminanceSource> source = MatSource::create(img);
	zxing::Ref<zxing::Binarizer> binarizer(new zxing::GlobalHistogramBinarizer(source));
	zxing::Ref<zxing::BinaryBitmap> bitmap(new zxing::BinaryBitmap(binarizer));
	zxing::Ref<zxing::Reader> reader;
        vector<zxing_out> res;

	if (fmt == "AZTEC"){
		reader.reset(new AztecReader);
	}else if (fmt == "CODABAR"){
		reader.reset(new CodaBarReader);
	}else if (fmt == "CODE_39"){
		reader.reset(new Code39Reader);
	}else if (fmt == "CODE_93"){
		reader.reset(new Code93Reader);
	}else if (fmt == "CODE_128"){
		reader.reset(new Code128Reader);
	}else if (fmt == "DATA_MATRIX"){
		reader.reset(new DataMatrixReader);
	}else if (fmt == "EAN_8"){
		reader.reset(new EAN8Reader);
	}else if (fmt == "EAN_13"){
		reader.reset(new EAN13Reader);
	}else if (fmt == "ITF"){
		reader.reset(new ITFReader);
	}else if (fmt == "PDF_417"){
		reader.reset(new PDF417Reader);
	}else if (fmt == "QR_CODE"){
		reader.reset(new QRCodeReader);
	}else if (fmt == "UPC_A"){
		reader.reset(new UPCAReader);
	}else if (fmt == "UPC_E"){
		reader.reset(new UPCEReader);
	}else if (fmt == "MULTI_QR_CODE"){
		QRCodeMultiReader mreader;
        try {
			auto results = mreader.decodeMultiple(bitmap, zxing::DecodeHints::QR_CODE_HINT);
			for (auto result : results)
			{
				zxing_out o;
				o.text = result->getText()->getText();
				o.name = zxing::BarcodeFormat::barcodeFormatNames[result->getBarcodeFormat()];
				auto arrPt = result->getResultPoints();
				for (int i = 0; i < arrPt->size(); ++i)
					o.position.push_back(cv::Point(arrPt[i]->getX(), arrPt[i]->getY()));
				res.push_back(o);
			}
			
        }catch (zxing::ReaderException const& re) {
            (void)re;
        }
        return res;

	}else {
		reader.reset(new QRCodeReader);
	}
    
	
	try {
        zxing_out o;
		zxing::Ref<zxing::Result> result(reader->decode(bitmap));
		o.text = result->getText()->getText();
		o.name = zxing::BarcodeFormat::barcodeFormatNames[result->getBarcodeFormat()];
		auto arrPt = result->getResultPoints();
		for (int i = 0; i < arrPt->size(); ++i)
			o.position.push_back(cv::Point(arrPt[i]->getX(), arrPt[i]->getY()));
        res.push_back(o);
	}catch (zxing::ReaderException const& re) {
		(void)re;
		// continue
	}
	return res;
}

zbar代码

COMMON_LIB_DECL vector<zbar_out> zbar_decode(const Mat& img, int zbarSymbolType = 64)
{
	vector<zbar_out> results;
	Mat grayImg;

	if (img.channels() == 1)
		grayImg = img;
	else if (img.channels() == 3)
		cv::cvtColor(img, grayImg, CV_RGB2GRAY);

	ImageScanner scanner;
	scanner.set_config((zbar_symbol_type_t)zbarSymbolType, ZBAR_CFG_ENABLE, 1);
	int w = grayImg.step;
	int h = grayImg.rows;
	Mat qrImg;
	Image image(w, h, "Y800");
	image.set_data(grayImg.data, w*h);
	//扫描
	int n = scanner.scan(image);
	if (n <= 0)
	{
		image.set_data(NULL, 0);
		return results;
	}

	// 提取 results
	auto syms = image.get_symbols();
	for (auto symI = syms.symbol_begin(); symI != syms.symbol_end(); ++symI) {
		zbar_out param;
		param.name = symI->get_type_name();
		param.text = symI->get_data();
		for (int i = 0; i < symI->get_location_size(); ++i)
		{
			int x = symI->get_location_x(i);
			int y = symI->get_location_y(i);
			param.position.push_back(Point(x, y));
		}
		results.push_back(param);
	}	
	// 清理
	image.set_data(NULL, 0);
	return results;
}

二维码识别的重点在 二维码检测,我实现了一个效果不错的二维码检测器,基于多特征融合,可以在诸多干扰中提取二维码。

不过很多二维码是无法识别的,质量太低

猜你喜欢

转载自blog.csdn.net/laoki/article/details/82391990
今日推荐