Python學習案例之二維碼生成識別

  • 2019 年 12 月 5 日
  • 筆記

前言

在 JavaWeb 開發中,一般使用 Zxing 來生成和識別二維碼,但是,Zxing 的識別有點差強人意,不少相對模糊的二維碼識別率很低。不過就最新版本的測試來說,識別率有了現顯著提高。

對比

在沒接觸 Python 之前,曾使用 Zbar 的客戶端進行識別,測了大概幾百張相對模糊的圖片,Zbar的識別速度要快很多,識別率也比 Zxing 稍微準確那邊一丟丟,但是,稍微模糊一點就無法識別。相比之下,微信和支付寶的識別效果就逆天了。

程式碼案例

# -*- coding:utf-8 -*-  import os  import qrcode  import time  from PIL import Image  from pyzbar import pyzbar    """  # 升級 pip 並安裝第三方庫  pip install -U pip  pip install Pillow  pip install pyzbar  pip install qrcode  """      def make_qr_code_easy(content, save_path=None):      """      Generate QR Code by default      :param content: The content encoded in QR Codeparams      :param save_path: The path where the generated QR Code image will be saved in.                        If the path is not given the image will be opened by default.      """      img = qrcode.make(data=content)      if save_path:          img.save(save_path)      else:          img.show()      def make_qr_code(content, save_path=None):      """      Generate QR Code by given params      :param content: The content encoded in QR Code      :param save_path: The path where the generated QR Code image will be saved in.                        If the path is not given the image will be opened by default.      """      qr_code_maker = qrcode.QRCode(version=2,                                    error_correction=qrcode.constants.ERROR_CORRECT_M,                                    box_size=8,                                    border=1,                                    )      qr_code_maker.add_data(data=content)      qr_code_maker.make(fit=True)      img = qr_code_maker.make_image(fill_color="black", back_color="white")      if save_path:          img.save(save_path)      else:          img.show()      def make_qr_code_with_icon(content, icon_path, save_path=None):      """      Generate QR Code with an icon in the center      :param content: The content encoded in QR Code      :param icon_path: The path of icon image      :param save_path: The path where the generated QR Code image will be saved in.                        If the path is not given the image will be opened by default.      :exception FileExistsError: If the given icon_path is not exist.                                  This error will be raised.      :return:      """      if not os.path.exists(icon_path):          raise FileExistsError(icon_path)        # First, generate an usual QR Code image      qr_code_maker = qrcode.QRCode(version=4,                                    error_correction=qrcode.constants.ERROR_CORRECT_H,                                    box_size=8,                                    border=1,                                    )      qr_code_maker.add_data(data=content)      qr_code_maker.make(fit=True)      qr_code_img = qr_code_maker.make_image(fill_color="black", back_color="white").convert('RGBA')        # Second, load icon image and resize it      icon_img = Image.open(icon_path)      code_width, code_height = qr_code_img.size      icon_img = icon_img.resize((code_width // 4, code_height // 4), Image.ANTIALIAS)        # Last, add the icon to original QR Code      qr_code_img.paste(icon_img, (code_width * 3 // 8, code_width * 3 // 8))        if save_path:          qr_code_img.save(save_path)      else:          qr_code_img.show()      def decode_qr_code(code_img_path):      """      Decode the given QR Code image, and return the content      :param code_img_path: The path of QR Code image.      :exception FileExistsError: If the given code_img_path is not exist.                                  This error will be raised.      :return: The list of decoded objects      """      if not os.path.exists(code_img_path):          raise FileExistsError(code_img_path)        # Here, set only recognize QR Code and ignore other type of code      return pyzbar.decode(Image.open(code_img_path), symbols=[pyzbar.ZBarSymbol.QRCODE], scan_locations=True)      if __name__ == "__main__":        # # 簡易版      # make_qr_code_easy("make_qr_code_easy", "make_qr_code_easy.png")      # results = decode_qr_code("make_qr_code_easy.png")      # if len(results):      #     print(results[0].data.decode("utf-8"))      # else:      #     print("Can not recognize.")      #      # # 參數版      # make_qr_code("make_qr_code", "make_qr_code.png")      # results = decode_qr_code("make_qr_code.png")      # if len(results):      #     print(results[0].data.decode("utf-8"))      # else:      #     print("Can not recognize.")      #      # 帶中間 logo 的      # make_qr_code_with_icon("https://blog.52itstyle.vip", "icon.jpg", "make_qr_code_with_icon.png")      # results = decode_qr_code("make_qr_code_with_icon.png")      # if len(results):      #     print(results[0].data.decode("utf-8"))      # else:      #     print("Can not recognize.")        # 識別答題卡二維碼 16 識別失敗      t1 = time.time()      count = 0      for i in range(1, 33):          results = decode_qr_code(os.getcwd()+"\img\"+str(i)+".png")          if len(results):              print(results[0].data.decode("utf-8"))          else:              print("Can not recognize.")              count += 1      t2 = time.time()      print("識別失敗數量:" + str(count))      print("測試時間:" + str(int(round(t2 * 1000))-int(round(t1 * 1000))))

測試了32張精挑細選的模糊二維碼:

識別失敗數量:1  測試時間:130

使用最新版的 Zxing 識別失敗了三張。

源碼

https://gitee.com/52itstyle/Python/tree/master/Day13