二維碼的生成與解析


商品條形碼是二維碼嗎?

實際上條形碼包括【一維條形碼】和【二維條形碼】。

我們常說的條形碼就是【一維條形碼】,而我們說的二維碼則是【二維條形碼】。我們最常見的二維碼是QR Code,全稱是 Quick Response

我們仔細觀察下面的二維碼可以發現,二維碼實際上是由一系列黑白(或彩色的)方塊表示,就像計算機只認識“0”和“1”一樣。也正是這些方塊的不同組合,表示了各種含義的數據信息

 對比來講【二維碼】相比傳統的【一維碼】存儲數據的效率更高,糾錯能力也更強,所以目前二維碼的應用也更加廣泛。

現在你是不是對二維碼多了一些了解?那接下來,我們來快速生成一個二維碼吧!

二維碼的生成

在Python中生成一個二維碼非常簡單,我們只需要安裝幾個模塊,就可以用幾行代碼生成一個二維碼。
首先,我們需要安裝qrcode模塊,用pip安裝的語句如下:

pip install qrcode

緊接着,因為qrcode模塊本身使用到了PIL模塊,所以我們還需要安裝PIL模塊。  

在Python3中的安裝語句如下:

pip install pillow

安裝完成后,我們就可以開始寫代碼了。想要生成二維碼,我們只需要幾句代碼:  

# 導入模塊
import qrcode
# 填入數據,並創建二維碼圖片
qr_im = qrcode.make(data='你好啊')
# 顯示二維碼圖片
qr_im.show()

上面代碼關鍵的操作是--make函數的使用。最簡單的使用就是傳入一個data參數,也就是二維碼中包含的數據信息。make函數會返回一個圖片對象,有了這個圖片,我們就可以調用show方法顯示它了。

除了顯示,我們還可以調用save方法將圖片保存到本地,代碼如下:  

qr_im.save('qrcode.png')

調用save方法后,我們就可以在當前目錄找到qrcode.png圖片了。  

我們發現外面的白色邊框比較粗,而且每個小正方形也比較大。

那有什么方法自己設置嗎?哈哈,想知道的話就繼續往下學習吧!

make函數解析

在上一關我們學習了調用make函數需要傳入一個data參數,而且make函數會返回一個圖片對象,那你有想過make函數里面做了些什么操作嗎?

我們先來看看make函數里面的代碼:

def make(data=None, **kwargs):
    qr = QRCode(**kwargs)
    qr.add_data(data)
    return qr.make_image()

為了方便看,我把代碼改成下面幾句  

# 創建二維碼對象
qr = QRCode()
# 在二維碼中添加數據
qr.add_data(data)
# 創建二維碼圖片
qr_im = qr.make_image()

由此可以看出,make函數做了三件事:  

  • 創建二維碼對象;

  • 在二維碼中添加數據;

  • 創建二維碼圖片,並返回。

因此,我們還可以通過創建QRCode對象的方式來創建二維碼。

我們只需要實現上面三個操作即可,具體代碼如下:

from qrcode import QRCode
# 創建QRCode對象
qr = QRCode()
# 在二維碼中添加數據
qr.add_data('https://www.baidu.com/')
# 創建二維碼圖片
qr_im = qr.make_image()
# 保存二維碼圖片
qr_im.save('qrcode.png')

上面代碼都非常好理解。在添加數據時,調用了add_data方法,這次傳入的是一個網址。 

之前我們掃碼會以【文本】的方式顯示添加的數據,這次直接進入了百度的網站。

因此我們可以知道,當我們添加的數據是一個網址時,掃碼會直接進入網站。

精確生成一個二維碼

了解了make函數具體做的事情后,我們就可以來看看怎樣精確地生成一個二維碼了。

在創建QRCode對象時,我們可以傳入幾個參數:

import qrcode
qr = qrcode.QRCode(
    version=1,
    box_size=5,
    error_correction=qrcode.ERROR_CORRECT_H,
    border=1
)

我們來看看這四個參數的含義:  

前面兩個參數都非常好理解,我們具體看看后兩個參數。

首先,你可能就會問,糾錯能力是什么?

請思考:在你掃碼時,是不是有些損壞了的二維碼有時候也能掃出內容?但是,有些二維碼破損了一點,就掃不出內容,而有的二維碼破損了很多都還能掃出內容。

這種差異就是【糾錯能力】不同而導致的。所以,【糾錯能力】其實就是容許二維碼損壞(錯誤)的百分比。

在qrcode中定義了四個常量,分別如下:

  • ERROR_CORRECT_L:糾正不超過7%的錯誤

  • ERROR_CORRECT_M(默認):糾正不超過15%的錯誤

  • ERROR_CORRECT_Q:糾正不超過25%的錯誤

  • ERROR_CORRECT_H:就在不超過30%的錯誤

說了這么多,現在應該知道【糾錯能力】是什么了吧!

接下來,我們來看看border參數,也就是白色邊框的大小。

在前面我們設置了一個box_size參數,表示最小正方形的邊長,而border表示的是有幾個白色小正方形。所以實際白色邊框的寬度是border*box_size個像素。

知道這些后,下面這段代碼你理解起來應該沒有問題吧:

import qrcode
qr = qrcode.QRCode(
    version=1,
    box_size=5,
    error_correction=qrcode.ERROR_CORRECT_H,
    border=1
)
qr.add_data('https://www.boxuegu.com/')
qr_im = qr.make_image()
qr_im.save('qrcode.png')

有時候,我們還可以不設置version參數,這個時候可以調用一個make方法,讓它自動設置大小:

import qrcode
qr = qrcode.QRCode(
    box_size=5,
    error_correction=qrcode.ERROR_CORRECT_H,
    border=1
)
# 設置為自動設置大小
qr.make(fit=True)
qr.add_data('https://www.boxuegu.com/')
qr_im = qr.make_image()
qr_im.save('im.png')

去掉version參數后,我們調用了make方法,並把fit參數設置為True,這樣程序會自動給我們設置合適的大小,完工~  

生成二維碼的操作我們就學習到這里,接下來,我們再來看看要怎么解析二維碼!  

二維碼的解析

讀取圖片

要解析二維碼我們還需要用到另外兩個模塊,它們分別是opencv和pyzbar模塊。

opencv模塊是用來讀取圖片的,而pyzbar則是解析二維碼的關鍵,安裝opencv的語句如下:

pip install opencv-python

安裝pyzbar的語句如下:  

pip install pyzbar

在解析二維碼之前,我們先看看讀取圖片操作。  

在安裝好opencv模塊后,我們就可以開始讀取圖片了,代碼如下:

# 導入模塊
import cv2
# 讀取二維碼圖片
qrcode = cv2.imread('qrcode.png')

雖然模塊叫opencv,但是導入的時候我們是導入cv2。  

在導入模塊后,我們就可以調用cv2模塊的imread函數讀取圖片,執行后會返回一個特殊的圖片對象,我們把這個對象交給pyzbar模塊處理就能拿到二維碼的數據了。

解析二維碼的操作也非常簡單,具體代碼如下:

import cv2
from pyzbar import pyzbar
# 讀取二維碼圖片
qrcode = cv2.imread('qrcode.png')
# 解析二維碼中的數據
data = pyzbar.decode(qrcode)
# 解析二維碼中的主要數據
text = data[0].data.decode('utf-8')
# 輸出內容
print(text)

前面讀取圖片的操作我們已經講過,那我們來看看解析二維碼的操作。

在解析二維碼時,我們解析了兩次,第一次調用pyzbar.decode函數,傳入我們的二維碼圖片。

這時候解析的結果是一個列表,我們瞄一眼它長什么樣子:  

[Decoded(data=b'https://www.boxuegu.com/', type='QRCODE', rect=Rect(left=51, top=51, width=368, height=368), polygon=[Point(x=51, y=51), Point(x=51, y=418), Point(x=419, y=419), Point(x=418, y=51)])]

雖然不知道是些什么東西,但可以看出來有很多。  

但仔細一看,列表第一個數據不就是二維碼的數據嗎?哈哈,機靈的你看出了端倪。這也就是我們要進行第二次解析的原因。

最后輸出結果如下:

https://www.boxuegu.com/

即我們在創建二維碼時,通過add_data方法添加的數據。

現在解析二維碼你也學會了,是不是能寫個掃碼小工具了啊?

先別急,我們還不知道怎么調用攝像頭呢!所以我們再來學習一下怎么調用攝像頭吧!

調用攝像頭

前面我們用到的opencv模塊,不僅可以讀取圖片,還可以調用攝像頭,所以,我們不需要再額外安裝模塊了。

調用攝像頭的代碼如下:

import cv2
# 調用攝像頭
cap = cv2.VideoCapture(0)
# 釋放攝像頭
cap.release()

代碼中我們調用了cv2.VideoCapture函數,這個函數是用來讀取視頻的。不過當我們傳入0時,它會直接調用我們的攝像頭。在使用完攝像頭后,我們調用release方法釋放攝像頭。  

不過上面的代碼我們什么都沒做,只是調用攝像頭后立馬釋放了。

那要怎么才能【一直調用】攝像頭呢疑問?咱繼續往下學習~

逐幀讀取畫面

在上面獲取的cap對象中,有一個read方法可以讀取到攝像頭拍攝到的內容。
代碼如下:

import cv2
cap = cv2.VideoCapture(0)
# 讀取一幀畫面
ret, frame = cap.read()
cap.release()

read方法會返回兩個參數,第一個表示是否有下一幀,第二個則是當前幀的圖片對象。  

如果想要一直讀取攝像頭拍攝的圖像,我們就需要循環讀取,直到read方法返回的ret參數為False,完成上述操作的代碼如下:

import cv2
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
# 循環讀取攝像頭內容,直到沒有下一幀
while ret:
    # 顯示當前幀的圖像
    cv2.imshow('frame', frame)
    # 等待10毫秒
    cv2.waitKey(10)
    # 繼續讀取下一幀圖像
    ret, frame = cap.read()
# 銷毀窗口
cv2.destroyAllWindows()
cap.release()

循環讀取攝像頭內容:這里用ret作為循環條件,表示沒有下一幀時結束。但是因為攝像頭是一直在拍攝畫面,所以這里不會結束。

顯示當前幀的圖像:我們可以調用cv2.imshow函數顯示圖像,該函數接收兩個參數,分別是窗口名稱和畫面。但是這個函數只會顯示一瞬間畫面,因此我們還要結合cv2.waitKey函數,等待10毫秒。

繼續讀取下一幀圖像:read方法每次只會讀取一幀畫面,所以我們需要在循環中一直調用read方法。

銷毀窗口:在opencv中我們只要調用了cv2.imshow函數,就需要在最后調用cv2.destroyAllWindows函數,保證窗口真正銷毀。  

掃碼工具的實現

掃碼工具的實現非常簡單,要想實現掃碼功能我們需要有解析二維碼的能力,以及調用攝像頭的能力。

而這兩種操作我們在前幾關我們都講解過了~

那具體流程又是怎樣的呢?請看:

第一步,我們要把解析二維碼的功能封裝成一個函數,方便后面使用。

第二步,我們需要逐幀讀取攝像頭的畫面,對每一幀畫面進行解析。

第三步,我們要判斷是否解析到了內容。如果解析到了,就停止循環,如果沒解析到就繼續循環。

好,理解了上面的流程,我們就可以開始寫代碼了。

首先,我們把解析二維碼的操作編寫成一個函數,代碼如下

def decode_qr(im):
    data = pyzbar.decode(im)
    # 解析的結果默認為None
    text = None
    # 如果檢測到二維碼再解析主要數據
    if data:
        text = data[0].data.decode('utf-8')
    return text

上面的代碼相對於第三關中的代碼做了一些修改,你有注意到么?吐舌頭  

首先,把text設置為None,表示主要數據默認為None。

然后對第一次的解析結果data做判斷,如果有數據才解析主要數據。

這樣上面函數的功能就成了:傳入圖片,如果有二維碼返回二維碼的數據,如果沒有返回None。

然后就是逐幀讀取畫面了:

def scanner():
    cap = cv2.VideoCapture(0)
    ret, frame = cap.read()
    while ret:
        # 對當前幀畫面進行解析
        result = decode_qr(frame)
        # 如果解析到了結果就輸出,沒解析到就繼續
        if result:
            print(result)
            break
        cv2.imshow('decode qrcode', frame)
        cv2.waitKey(10)
        ret, frame = cap.read()
    cap.release()
    cv2.destroyAllWindows()

上面的代碼也在第四關代碼基礎上進行了一些小的修改,我們來看一下。  

在進入循環后,我們對當前讀取到的畫面進行解析。

如果解析到了內容,程序就會輸出結果,然后跳出循環,這樣就完成了我們的掃碼工作。

掃碼工具完整的代碼如下:

import cv2
from pyzbar import pyzbar

def decode_qr(im):
    data = pyzbar.decode(im)
    text = None
    if data:
        text = data[0].data.decode('utf-8')
    return text

def scanner():
    cap = cv2.VideoCapture(0)
    ret, frame = cap.read()
    while ret:
        result = decode_qr(frame)
        if result:
            print(result)
            break
        cv2.imshow('decode qrcode', frame)
        cv2.waitKey(10)
        ret, frame = cap.read()
    cap.release()
    cv2.destroyAllWindows()
scanner()

因為第二步的操作也編寫成了函數,所以需要在下面調用才會執行。怎么樣,是不是挺簡單的?你也趕快動手實踐  

一下吧~

因此你只需要記住那幾個函數即可。為了方便你記憶,老師給你整理了下面這張圖,請收好:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM