2021SC@SDUSC-Zxing(九):解码实例流程分解

2021SC@SDUSC

本篇博客将用在博客(三)-(八)中学习到的知识,通过实例更深入的理解解码步骤,并对2021SC@SDUSC-Zxing(二)中提到的问题及新发现的问题进行解答。

解码实例

在这里插入图片描述

1.LuminanceSource

第一步,将图片传入LuminanceSource,获取灰度图片。
测试代码如下:


  @Test
  public void testBufferedImageLuminanceSource() throws IOException {
    InputStream ins=new FileInputStream("D:/ZxingImage/mess2.jpg");
    BufferedImage image = ImageIO.read(ins);
    //获取图像的宽高信息
    System.out.println("width:"+image.getWidth()+",heigth:"+image.getHeight());
    BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
    //这里修改了BufferedImageLuminanceSource原来封装好的属性权限,这样是非常不规范的,仅为更直观的了解输出中间结果使用。
    BufferedImage imageout=source.getImage();
    File file = new File("D://ZxingImage//BufferedImageLuminanceSource_out.jpg");
    if(!file.exists()){
      //文件不存在则创建
      file.createNewFile();
    }
    ImageIO.write(imageout,"JPEG",file);
    System.out.println("二维码生成成功");
  }

通过这一步,我们成功获得了一个灰度图片。
在这里插入图片描述
后台输出,第一行是原图信息,第二行是输出图像信息:
在这里插入图片描述

2.Binarizer

第二步,将灰度图片传入Binarizer,对图像进行去噪处理、获得阈值、像素值(亮度数据)转换为1位数据(二值化处理)。
转为1位数据:
在这里插入图片描述
当前展示的后台输出的部分大概在图像的这个位置,在后台输出中找二维码部分不好找(从上面的图中我们也可以看到图片被放大到了原来的345%),但是这个图片也已经能说明问题了:
在这里插入图片描述
测试代码如下:

  @Test
  public void testBufferedImageLuminanceSource() throws IOException, NotFoundException {
    InputStream ins=new FileInputStream("D:/ZxingImage/mess2.jpg");
    BufferedImage image = ImageIO.read(ins);
    BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
    HybridBinarizer binarizer = new HybridBinarizer(source);       
    System.out.println("BlackMatrix:\n"+binarizer.getBlackMatrix()+"\nWidth:"+binarizer.getWidth()+"\nheight:"+binarizer.getHeight());
  }

后台输出:
在这里插入图片描述
至于输出为什么是“ ”和“X”,BitMatrix的toString是这样的,表示只会有这两种输出:

  @Override
  public String toString() {
    return toString("X ", "  ");
  }

而选择“ ”、“X”的哪一个,逻辑如下:

//为true表示黑色
  public boolean get(int x, int y) {
    int offset = y * rowSize + (x / 32);
    return ((bits[offset] >>> (x & 0x1f)) & 1) != 0;
  }

接着,这个语句给获取请求的位赋值,如果是黑色,就是setString,反之unsetString,然后通过参数的方式将“X”与setString关联,“ ”与unsetString关联。

result.append(get(x, y) ? setString : unsetString);

Zxing中去噪完成后,没有获取图像,因为去噪的图像对我们解码没有什么帮助,去完噪紧接着就转为1位数据图像了。阈值也是,只是一个中间步骤,代码逻辑在2021SC@SDUSC-Zxing(五):解码关键类详解-Binarizer中已讲解。

3.BinaryBitmap

第三步,对上一步获得的位数据进行进一步维护。
可以看出,BinaryBitmap和LuminanceSource的方法在功能上其实有很多重叠(如是否能旋转、是否能裁剪),但是正如2021SC@SDUSC-Zxing(三):解码相关代码中流程图展示的那样,LuminanceSource操作的是图片,BinaryBitmap操作的是1位数据而非图片。要注意的是,在这一步我们还没有进行裁剪和旋转等操作。
测试代码如下:

  @Test
  public void testBufferedImageLuminanceSource() throws IOException, NotFoundException {
    InputStream ins=new FileInputStream("D:/ZxingImage/mess2.jpg");
    BufferedImage image = ImageIO.read(ins);
    BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
    HybridBinarizer binarizer = new HybridBinarizer(source);
    BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
    System.out.println("BlackMatrix:\n"+binaryBitmap.getBlackMatrix()+"Width:"+binaryBitmap.getWidth()+"\nheight:"+binaryBitmap.getHeight());
  }

后台输出:
在这里插入图片描述

4.Reader

第四步,通过Reader开始解码。
前几步的操作都是为了这一步做准备,这一步是解码的重中之重。
测试代码:

  @Test
  public void testBufferedImageLuminanceSource() throws IOException, NotFoundException, ChecksumException, FormatException {
    InputStream ins=new FileInputStream("D:/ZxingImage/mess2.jpg");
    BufferedImage image = ImageIO.read(ins);
    BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
    HybridBinarizer binarizer = new HybridBinarizer(source);
    BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
    QRCodeReader reader = new QRCodeReader();
    //这里为了演示也是把QRCodeReader的private方法extractPureBits设置成public了
    BitMatrix bt= reader.extractPureBits(binaryBitmap.getBlackMatrix());
    System.out.println("reader:"+bt+"\nw:"+bt.getWidth()+"\nh:"+bt.getHeight());
    System.out.println("解码结果:"+reader.decode(binaryBitmap));
  }

这里我们没有用2021SC@SDUSC-Zxing(二):Zxing运行(Springboot)解码demo中提到的MultiFormatReader,因为这个类它尝试解码库支持的所有条形码格式,而我们现在知道解码的是QR码,因此就直接用QR码的解码器了。具体介绍可以看2021SC@SDUSC-Zxing(七):解码关键类详解-Reader

后台输出,显然这个宽高是被裁剪过的,但也不是生成demo中设置的300 * 300。通过查看“X”、“ ”阵列图片,也可以发现图片被旋转了。为什么大小不是 300 * 300?因为这个宽高已经可以满足Zxing的裁剪需求了,因此没有继续裁剪。
在这里插入图片描述
通过这个555*555的输出可以容易的找到二维码:
在这里插入图片描述
2021SC@SDUSC-Zxing(二):Zxing运行(Springboot)生成二维码时设置的大小
在这里插入图片描述
下图为未经放缩的原图像素点位置,红点是二维码四个顶点,绿点是输出的四个定位点。可以看出原图中的大小依旧是300 * 300(手动标注存在误差)。
在这里插入图片描述

5.Result

第五步,输出解码结果。
这一步在第四步的输出中已经体现,在代码中的实现为:

Result result = reader.decode(binaryBitmap, hints);
String content = result.getText();

Result中会存放定位点的信息,这个信息会传给安卓端,这也是为什么最开始的扫码图像会在对应位置有绿色的方块

欢迎提出宝贵意见,感谢观看!
参考: ZxingAPI

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要将C++版ZXing库中`zxing::Ref<zxing::String>`类型的解码结果转换为UTF-8编码的字符串,您可以使用C++标准库中的字符串转换功能。 以下是一个示例代码,演示了如何将`zxing::Ref<zxing::String>`类型的解码结果转换为UTF-8编码的字符串: ```cpp #include <iostream> #include <string> #include <locale> #include <codecvt> #include <zxing/common/Str.h> std::string convertToUTF8(const zxing::Ref<zxing::String>& input) { std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; std::wstring wide = converter.from_bytes(input->getText()); return converter.to_bytes(wide); } int main() { // 假设通过解码获得一个zxing::Ref<zxing::String>类型的解码结果 zxing::Ref<zxing::String> decodedResult = zxing::String::valueOf("Hello, 世界!"); // 将解码结果转换为UTF-8编码 std::string utf8Result = convertToUTF8(decodedResult); // 输出转换后的结果 std::cout << "UTF-8 Result: " << utf8Result << std::endl; return 0; } ``` 在上面的示例中,我们定义了一个名为`convertToUTF8`的函数,它接受一个`zxing::Ref<zxing::String>`类型的输入参数,并将其转换为UTF-8编码的字符串。该函数使用了C++标准库中的`std::wstring_convert`和`std::codecvt_utf8`来进行字符串转换。 请注意,上述示例代码中假设您已经通过解码获得了一个`zxing::Ref<zxing::String>`类型的解码结果,并将其赋值给了`decodedResult`变量。 希望这个示例能够解决您的问题!如果您还有其他疑问,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值