python生成二维码,扫描二维码

首先说生成二维码;需要安装qrcoed

pip install qrcode -i https://pypi.doubanio.com/simple

下来不用说了.直接看程序,业余选手 欢迎吐槽.

r"""
操作系统:win10 64位
python解释器:3.8.8 64位
三方库:qrcode 
    pip install qrcode 
    pip install qrcode -i https://pypi.doubanio.com/simple
编辑器:Notepad++
IDE:IDLE,Thonny
"""
import os,sys,time,qrcode
def p(S):
    print(S)
    return S
def cmd(S="pause"):
    os.system(S)
def CMD(cmd="pause"):
    p=os.popen(cmd)
    return p.read() 
def Wait(S=10):
    time.sleep(S)      
def explorer(start_directory=fr"{os.getcwd()}"):
    temp=start_directory.replace("/","\\")#CMD只认 反斜杠\ 不认正斜杠/
    cmd(f"explorer.exe {temp}");   
def mkdir(path=f"{os.getcwd()}/qr_img"):
    folder = os.path.exists(path)
    if not folder:
        os.makedirs(path)
    else:
        pass       
while True:    
    in_in=input("输入要生成的二维码信息后,按回车:")    
    if in_in !="":   
        QR_content = in_in;print(QR_content)
    else:
        p("None");continue
    mkdir()
    _DATE=time.strftime('%Y-%m-%d'); 
    _TIME=time.strftime('%H_%M_%S');
    SaveFileName=time.strftime('%Y-%m-%d_%H_%M_%S');   
    image = qrcode.make(QR_content)  #生成二维码
    try:
        image.save(f"{os.getcwd()}/qr_img/{SaveFileName}('_{QR_content}_').png")  #保存
        """文件名不合法存不上 "\/:*?<>|" """
        p("done!")#image.show()
    except:
        """"\/:*?<>|"""
        image.save(f"{os.getcwd()}/qr_img/{SaveFileName}'_#%%#_'.png")  #保存
        p("done!_E");#image.show()
    explorer(f"{os.getcwd()}/qr_img")

稍加改动就可以批量生成大量二维码.

比如需要生成[0000-9999].

import os,sys,time,socket,_thread,threading,qrcode
def thread_it(func, *args):
    t = threading.Thread(target=func, args=args)
    t.setDaemon(True);
    t.start();
def p(S):
    print(S)
    return S
def cmd(S="pause"):
    os.system(S)
def CMD(cmd="pause"):
    p=os.popen(cmd)
    return p.read() 
def Wait(S=10):
    time.sleep(S)      
def explorer(start_directory=fr"{os.getcwd()}"):
    temp=start_directory.replace("/","\\")#CMD只认 反斜杠\ 不认正斜杠/
    cmd(f"explorer.exe {temp}");   
def mkdir(path=f"{os.getcwd()}/qr_img"):
    folder = os.path.exists(path)
    if not folder:
        os.makedirs(path)
    else:
        pass       
mkdir(f"{os.getcwd()}/二维码")
def 生成(i):
    SaveFileName=str(i).zfill(4)
    QR_content=SaveFileName
    image = qrcode.make(QR_content)  #生成二维码
    try:
        image.save(f"{os.getcwd()}/二维码/{SaveFileName}.jpg")  #保存
        p(f"done!:>>{SaveFileName}")#image.show()
    except:
        pass    
for i in range(0,9999+1,1):
    thread_it(生成,i)
explorer(f"{os.getcwd()}/二维码")

生成说完了.

2024/09/13 偶然发现把上面那个用来生成qr,发现生成的图像无法转 numpy ,,   .save的二维码图表面上正常但是用别的软件打开会出现 错行;

如图:

后来以为py坑大放弃了,用C# 版的ZXing重做了;

2024/10/5:

直接说:解决办法:

make以后处理或者保存之前需要 .convert  需要注意的是这是pillow的convert:

例如:8位灰度图:

gray_img= qr.make_image(fill_color="black", back_color="white").convert("L");

接下来上完整示例:参数和QR码规格在注释中体现:

import qrcode
from PIL import Image
import numpy as np
import cv2
# 生成二维码
qr = qrcode.QRCode(
    version=1,
    error_correction=qrcode.constants.ERROR_CORRECT_L,
    box_size=10,
    border=4
)
qr.add_data("https://www.example.com")#二维码字符
qr.make(fit=True)#自适应

r"""
fit=True 是一个可选参数,当设置为True时,
它会指示make方法自动调整二维码的版本(尺寸),
以适应所提供的数据,同时尽量使用最小的尺寸。
如果不设置fit=True或者设置为False,
那么二维码的版本将根据你在创建QRCode对象时指定的version参数来确定。
如果指定的版本太小,无法容纳所有数据,那么make方法将会抛出一个异常。
"""
img = qr.make_image(fill_color="black", back_color="white").convert("RGB")
img_G = qr.make_image(fill_color="black", back_color="white").convert("L");img_G_np = np.array(img_G)
cv2.imwrite("qrcode_8_opencv.png",img_G_np)#保存8位灰度图
r"""
# 这里一定要加上 .convert("RGBA")/*32*/ .convert("RGB")/*24*/  .convert("L")/*8*/  .convert("1")/*1*/
# 我曾经在这里上过当;
# 否则 可以正常保存 但不能成功转换为numpy ; 且保存的图不能被其他图像程序正确识别 
# 比如  海康VisionMaster(图片发生形变);  halcon 有时正常打开(.png正常) 有时不正常( .bmp打不开报错)  
"""
img.save("qrcode.png")# (pillow)保存二维码图片
img_np = np.array(img)# pillow 转numpy #这时候 python 版 halcon 可以正常识别
cv2.imshow("QR Code", img_np)# 使用OpenCV显示图像
cv2.imwrite("qrcode_opencv.png", cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR))# 保存图像 
# opencv python 因为 opencv是BGR >> cv2.COLOR_RGB2BGR


r"""
关于 QR 创建的参数:
    version, error_correction,box_size,    border;
    
version:
表示二维码的尺寸。版本号从1到40,版本1是最小的(21x21模块),每增加一个版本号,尺寸增加4个模块(例如,版本2是25x25模块)。版本越高,可以编码的数据量就越大。
默认值通常是根据数据量自动选择最小的版本,但你也可以手动指定。
error_correction:

表示二维码的错误校正级别。它决定了二维码中用于纠错的模块数量,从而影响二维码的容错能力。
可接受的参数值:
qrcode.constants.ERROR_CORRECT_L:约可纠错7%的错误。
qrcode.constants.ERROR_CORRECT_M:约可纠错15%的错误(默认值)。
qrcode.constants.ERROR_CORRECT_Q:约可纠错25%的错误。
qrcode.constants.ERROR_CORRECT_H:约可纠错30%的错误。
box_size:
表示每个二维码模块(黑色或白色方块)的像素尺寸。增加这个值可以使生成的二维码更大,但同时也会占用更多的空间。
默认值通常是10,但你可以设置为任何正整数。
border:

表示二维码周围边框的宽度。边框是二维码周围一圈空白区域,用于帮助扫描设备识别二维码的边界。
默认值通常是4,但你可以设置为任何正整数。
      
************

关于:pillow .convert("") 可以写哪些参数 
"L":灰度模式。每个像素用8位表示,范围从0(黑色)到255(白色)。
"RGB":真彩色模式。每个像素用24位表示,红色、绿色和蓝色各占8位。
"RGBA":带透明度的真彩色模式。每个像素用32位表示,红色、绿色、蓝色各占8位,另外8位用于透明度(Alpha通道)。
"CMYK":印刷色彩模式。每个像素用32位表示,青色、洋红色、黄色和黑色各占8位。
"1":二值模式。每个像素用1位表示,黑白二值。
"P":调色板模式。每个像素用8位表示,并且有一个调色板定义了可用的颜色。
"LA":灰度加透明度模式。每个像素用16位表示,8位用于灰度值,8位用于透明度。
"I":整型模式。每个像素用32位表示,用于存储整数值。
"F":浮点模式。每个像素用32位浮点数表示,用于存储浮点数值。
"RGBX":带填充的真彩色模式。每个像素用32位表示,红色、绿色和蓝色各占8位,另外8位用于填充(通常用于图像处理中的某些操作)。
"YCbCr":YCbCr颜色空间模式。用于视频压缩和广播。
"LAB":CIELAB颜色空间模式。用于色彩管理。
"HSV":HSV颜色空间模式。用于颜色处理。
"HSL":HSL颜色空间模式。用于颜色处理。
"I16":16位整型模式。每个像素用16位表示。
"""
cv2.waitKey(0)
cv2.destroyAllWindows()

好了,这下可以了 ;2024/10/5:

下来说扫描.

先看:zbar.

"""
pyzbar
"""
from __future__ import print_function
import pyzbar.pyzbar as pyzbar
import numpy as np
import cv2
#from win32Selectfile import *
import win32ui
def getfilepath(S=r"C:\Users\Administrator\Desktop"):
    dlg =win32ui.CreateFileDialog(1)
    dlg.SetOFNInitialDir(f"{S}")
    dlg.DoModal()
    filename=dlg.GetPathName()
    #self.lineEtid_InputId_AI.setText(filename)
    print(filename)
    return filename
'''
最大容忍度为 图像清晰情况下 水平旋转30° 垂直旋转30°
尽量保持水平....
https://mh.cli.im/
'''
def decode(im) :
  decodedObjects = pyzbar.decode(im)
  for obj in decodedObjects:
    print('Type : ', obj.type)
    print('Data : ', str(obj.data.decode('UTF-8','strict')),'\n')
  return decodedObjects
def display(im, decodedObjects):
  cv2.imshow("Yuanshi", im);#Show出原始图片..
  for decodedObject in decodedObjects:
    points = decodedObject.polygon   
    if len(points) > 4 :
      hull = cv2.convexHull(np.array([point for point in points], dtype=np.float32))
      hull = list(map(tuple, np.squeeze(hull)))
    else :
      hull = points;
    n = len(hull)
    for j in range(0,n):
      cv2.line(im, hull[j], hull[ (j+1) % n], (255,0,0), 3)
if __name__ == '__main__':
  pppic=getfilepath(r"C:\Users\Administrator\Desktop\MVS_PY\PY\barcode-QRcodeScanner")
  im = cv2.imdecode(np.fromfile(pppic,dtype=np.uint8),1)
  decodedObjects = decode(im)
  display(im, decodedObjects)
  cv2.imshow("Results", im);
  cv2.waitKey(0);

需要安装 pywin32,numpy,pyzbar,

接下来看opencv扩展库微信扫描二维码的版本

需要安装opencv-python 和 opencv-contrib-python ,同时下载依赖文件到程序能找到的地方.

建议放在程序运行目录:

在这里下载"https://github.com/WeChatCV/opencv_3rdparty/tree/wechat_qrcode"

"detect.prototxt","detect.caffemodel","sr.prototxt","sr.caffemodel"这四个文件放在程序运行目录.

好了库安装好,依赖文件下载好,就可以用微信扩展来扫描二维码了,

r"""
操作系统:win10 64位
python解释器:3.8.8 64位
三方库:qrcode 
numpy
win32ui
opencv-python
opencv-contrib-python
pip install opencv-python -i https://pypi.doubanio.com/simple   
编辑器:Notepad++
IDE:IDLE,Thonny
"""
import cv2
import imutils
import win32ui
import os,sys
import numpy as np
#from CV_class import *
def getfilepath(path=f'{os.getcwd()}'):
    dlg =win32ui.CreateFileDialog(1)
    dlg.SetOFNInitialDir(path)
    dlg.DoModal()
    filename=dlg.GetPathName();#
    return filename
def CV_Getimg(picpath,x2=1):
    All_Suffix_Name= (".jpg",".JPG",".bmp",".BMP",".png",".PNG")
    for S in All_Suffix_Name:#检查后缀名
        RRR=os.path.splitext(picpath)[-1] == f"{S}";
        if RRR==True:
            try:#打开一个可以含有中文路径的图片文件.""""""
                return cv2.imdecode(np.fromfile(picpath,dtype=np.uint8),x2)
            except:
                print("不支持打开此图片.")
                return np.zeros((1,1,1),dtype="uint8")
    print("不是有效后缀名.")
    return np.zeros((1,1,1),dtype="uint8") 
t1 ="detect.prototxt"
t2 ="detect.caffemodel"
t3 ="sr.prototxt"
t4 ="sr.caffemodel"
try:
    detector = cv2.wechat_qrcode_WeChatQRCode(t1, t2, t3, t4)
except:#找不到依赖文件
    print("---------------------------------------------------------------")
    print("Failed to initialize WeChatQRCode.")
    print("Please, download 'detector.*' and 'sr.*' from")
    print("https://github.com/WeChatCV/opencv_3rdparty/tree/wechat_qrcode")
    print("and put them into the current directory.")
    print("---------------------------------------------------------------")
   
img = CV_Getimg(getfilepath())    
res, points = detector.detectAndDecode(img)
print(f""">>>{res}<<<|>>>{points}<<<********************""")
Line_w=3
if len(res)>1 :
    print(f""">>>{res[0]}<<<""")
if len(points[0])==4:
    #print(f""">>>
    #{int(points[0][0][0])} {int(points[0][0][1])}\n{int(points[0][1][0])} {int(points[0][1][1])}
    #{int(points[0][2][0])} {int(points[0][2][1])}\n{int(points[0][3][0])} {int(points[0][3][1])}
    #<<<""")
    c=[]  
    c.append(int(points[0][0][0]));c.append(int(points[0][0][1]))
    c.append(int(points[0][1][0]));c.append(int(points[0][1][1]))
    c.append(int(points[0][2][0]));c.append(int(points[0][2][1]))
    c.append(int(points[0][3][0]));c.append(int(points[0][3][1]))
    color=(25,255,0)
    cv2.line(img, (c[0],c[1]), (c[2],c[3]),color,Line_w)#12
    cv2.line(img, (c[4],c[5]), (c[6],c[7]),color,Line_w)#23
    cv2.line(img, (c[0],c[1]), (c[6],c[7]),color,Line_w)#34
    cv2.line(img, (c[2],c[3]), (c[4],c[5]),color,Line_w)#41
""" 
笨办法,画出二维码轮廓 哈哈哈 过于愚蠢
"""    
cv2.namedWindow("vas",flags=cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO | cv2.WINDOW_GUI_EXPANDED)
cv2.moveWindow("vas",0,0);
cv2.resizeWindow("vas",640,480)
cv2.imshow("vas", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

可以了,生成二维码和扫描二维码都能用了.

python大法好啊,不考虑性能的话还是挺实用的. 

2024/07/23:晴

 有人发来两张图说识别不到,(首先给那位老兄[不知道是老哥还是老兄]说一声对不住[实在太忙(懒)了]).

不废话上图.

没啥思路先把图转正吧,.

import cv2,os
import numpy as np
import copy
class Get_Image_Size():
    def X(work):return work.shape[0]
    def Y(work):return work.shape[1]  
def FP(work):
    NW=[0,0];  NE=[Get_Image_Size.X(work),0]
    SW=[0,Get_Image_Size.Y(work)];  SE=[Get_Image_Size.X(work),Get_Image_Size.Y(work)]
    return [NW, NE, SW, SE] 
img = cv2.imread('001.jpg')
#img = cv2.imread('002.jpg')#002
work=copy.deepcopy(img)#
work = cv2.resize(work, (800, 800), interpolation=cv2.INTER_AREA)
cv2.imwrite(f"{os.getcwd()}/work.png",work)  #保存调整的图 
gray = cv2.cvtColor(work,cv2.COLOR_BGR2GRAY) #转灰度
ret, binary = cv2.threshold(gray,120,255,cv2.THRESH_BINARY) #二值化#这2张图120效果最好
cv2.imwrite(f"{os.getcwd()}/binary.png",binary)
#调整大小/转灰度/直接二值化已经可以正常识别了.
#为了说明情况还是透视变换一下吧.
print(FP(work))
# 设置适当变换坐标>> [NW, NE, SW, SE]
#src = np.float32([[139, 83], [733, 125],[45,635],  [697, 703]])#第二张图002
src = np.float32([[31, 134], [591, 143],[107,686],  [720, 662]])
dst = np.float32(FP(work))
M = cv2.getPerspectiveTransform(src, dst)
transform_bin_img = cv2.warpPerspective(binary, M, (800, 800))
cv2.imshow('img', img)
cv2.imshow('transform_bin_img', transform_bin_img)
cv2.imwrite(f"{os.getcwd()}/transform_bin_img.png",transform_bin_img)
#保存转正图
th2 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)#MEAN
cv2.imshow('th2', th2)
cv2.waitKey(0)

看结果. 这样是不是容易识别的多了呢?

第一张Zbar都可以,第二张有些反光(实际第二张反光用adaptiveThreshold的图也是可以的)

Zbar都可以opencv微信扩展肯定也是可以的. 

ps:变换坐标的获取也是个技术活我是手工填进去的,实际应检测二维码角点获取.

ps:扫码不是其他图像处理,可以一直尝试,复杂场景最笨的办法则可以不断变更参数后多次送入decode能很大提高检出率.

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值