程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2023-06(4)

Python+OpenCv制作证件图片生成器

发布于2019-08-07 11:48     阅读(4082)     评论(0)     点赞(1)     收藏(5)


本项目使用Python和OpenCv实现身份证图片生成工具,填入信息,选择一张头像图片(即可生成黑白和彩色身份证图片)。可以选择是否自动抠图,自动抠图目前仅支持蓝色背景,对自动抠图效果不满意可以手动抠图。

在线抠图地址:

https://burner.bonanza.com/

https://www.gaoding.com/koutu

参照标准:

正面

  “姓名”、“性别”、“民族”、“出生年月日”、“住址”、“公民身份号码”为6号黑体字,用蓝色油墨印刷;登记项目中的姓名项用5号黑体字印刷;其他项目则用小5号黑体字印刷;出生年月日 方正黑体简体字符大小:姓名+号码(11点)其他(9点)字符间距(AV):号码(50)字符行距:住址(12点);身份证号码字体 OCR-B 10 BT 文字 华文细黑。

背面

  左上角为国徽,用红色油墨印刷;其右侧为证件名称“中华人民共和国居民身份证”,分上下两排排列,其中上排的“中华人民共和国”为4号宋体字,下排的“居民身份证”为2号宋体字;“签发机关”、“有效期限”为6号加粗黑体字;签发机关登记项采用,“xx市公安局”;有效期限采用“xxxx.xx-xxxx.xx.xx”格式,使用5号黑体字印刷,全部用黑色油墨印刷。

这里我用周杰伦的图像制作简单的身份证图片,效果图如下:

 

 

实现Demo如下:

  1. # coding:utf-8
  2. import os
  3. import PIL.Image as PImage
  4. from PIL import ImageFont, ImageDraw
  5. import cv2
  6. import numpy as np
  7. try:
  8. from Tkinter import *
  9. from ttk import *
  10. from tkFileDialog import *
  11. from tkMessageBox import *
  12. except ImportError:
  13. from tkinter import *
  14. from tkinter.ttk import *
  15. from tkinter.filedialog import *
  16. from tkinter.messagebox import *
  17. if getattr(sys, 'frozen', None):
  18. base_dir = os.path.join(sys._MEIPASS, 'usedres')
  19. else:
  20. base_dir = os.path.join(os.path.dirname(__file__), 'usedres')
  21. def changeBackground(img, img_back, zoom_size, center):
  22. # 缩放
  23. img = cv2.resize(img, zoom_size)
  24. rows, cols, channels = img.shape
  25. # 转换hsv
  26. hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
  27. # 获取mask
  28. lower_blue = np.array([78, 43, 46])
  29. upper_blue = np.array([110, 255, 255])
  30. mask = cv2.inRange(hsv, lower_blue, upper_blue)
  31. # cv2.imshow('Mask', mask)
  32. # 腐蚀膨胀
  33. erode = cv2.erode(mask, None, iterations=1)
  34. dilate = cv2.dilate(erode, None, iterations=1)
  35. # 粘贴
  36. for i in range(rows):
  37. for j in range(cols):
  38. if dilate[i, j] == 0: # 0代表黑色的点
  39. img_back[center[0] + i, center[1] + j] = img[i, j] # 此处替换颜色,为BGR通道
  40. return img_back
  41. def paste(avatar, bg, zoom_size, center):
  42. avatar = cv2.resize(avatar, zoom_size)
  43. rows, cols, channels = avatar.shape
  44. for i in range(rows):
  45. for j in range(cols):
  46. bg[center[0] + i, center[1] + j] = avatar[i, j]
  47. return bg
  48. def generator():
  49. global ename, esex, enation, eyear, emon, eday, eaddr, eidn, eorg, elife, ebgvar
  50. name = ename.get()
  51. sex = esex.get()
  52. nation = enation.get()
  53. year = eyear.get()
  54. mon = emon.get()
  55. day = eday.get()
  56. org = eorg.get()
  57. life = elife.get()
  58. addr = eaddr.get()
  59. idn = eidn.get()
  60. fname = askopenfilename(parent=root, initialdir=os.getcwd(), title=u'选择头像')
  61. # print fname
  62. im = PImage.open(os.path.join(base_dir, 'empty.png'))
  63. avatar = PImage.open(fname) # 500x670
  64. name_font = ImageFont.truetype(os.path.join(base_dir, 'hei.ttf'), 72)
  65. other_font = ImageFont.truetype(os.path.join(base_dir, 'hei.ttf'), 60)
  66. bdate_font = ImageFont.truetype(os.path.join(base_dir, 'fzhei.ttf'), 60)
  67. id_font = ImageFont.truetype(os.path.join(base_dir, 'ocrb10bt.ttf'), 72)
  68. draw = ImageDraw.Draw(im)
  69. draw.text((630, 690), name, fill=(0, 0, 0), font=name_font)
  70. draw.text((630, 840), sex, fill=(0, 0, 0), font=other_font)
  71. draw.text((1030, 840), nation, fill=(0, 0, 0), font=other_font)
  72. draw.text((630, 980), year, fill=(0, 0, 0), font=bdate_font)
  73. draw.text((950, 980), mon, fill=(0, 0, 0), font=bdate_font)
  74. draw.text((1150, 980), day, fill=(0, 0, 0), font=bdate_font)
  75. start = 0
  76. loc = 1120
  77. while start + 11 < len(addr):
  78. draw.text((630, loc), addr[start:start + 11], fill=(0, 0, 0), font=other_font)
  79. start += 11
  80. loc += 100
  81. draw.text((630, loc), addr[start:], fill=(0, 0, 0), font=other_font)
  82. draw.text((950, 1475), idn, fill=(0, 0, 0), font=id_font)
  83. draw.text((1050, 2750), org, fill=(0, 0, 0), font=other_font)
  84. draw.text((1050, 2895), life, fill=(0, 0, 0), font=other_font)
  85. avatar = cv2.cvtColor(np.asarray(avatar), cv2.COLOR_RGB2BGR)
  86. im = cv2.cvtColor(np.asarray(im), cv2.COLOR_RGB2BGR)
  87. if ebgvar.get():
  88. im = changeBackground(avatar, im, (500, 670), (690, 1500))
  89. else:
  90. #im.paste(avatar, (1500, 690), mask=avatar)
  91. im = paste(avatar, im, (500, 670), (690, 1500))
  92. im = PImage.fromarray(cv2.cvtColor(im, cv2.COLOR_BGR2RGB))
  93. im.save('color.png')
  94. im.convert('L').save('bw.png')
  95. showinfo(u'成功', u'文件已生成到目录下,黑白bw.png和彩色color.png')
  96. if __name__ == '__main__':
  97. global ename, esex, enation, eyear, emon, eday, eaddr, eidn, eorg, elife, ebgvar
  98. root = Tk()
  99. root.title(u'AIRobot身份证图片生成器')
  100. # root.geometry('640x480')
  101. root.resizable(width=False, height=False)
  102. Label(root, text=u'姓名:').grid(row=0, column=0, sticky=W, padx=3, pady=3)
  103. ename = Entry(root, width=8)
  104. ename.grid(row=0, column=1, sticky=W, padx=3, pady=3)
  105. Label(root, text=u'性别:').grid(row=0, column=2, sticky=W, padx=3, pady=3)
  106. esex = Entry(root, width=8)
  107. esex.grid(row=0, column=3, sticky=W, padx=3, pady=3)
  108. Label(root, text=u'民族:').grid(row=0, column=4, sticky=W, padx=3, pady=3)
  109. enation = Entry(root, width=8)
  110. enation.grid(row=0, column=5, sticky=W, padx=3, pady=3)
  111. Label(root, text=u'出生年:').grid(row=1, column=0, sticky=W, padx=3, pady=3)
  112. eyear = Entry(root, width=8)
  113. eyear.grid(row=1, column=1, sticky=W, padx=3, pady=3)
  114. Label(root, text=u'月:').grid(row=1, column=2, sticky=W, padx=3, pady=3)
  115. emon = Entry(root, width=8)
  116. emon.grid(row=1, column=3, sticky=W, padx=3, pady=3)
  117. Label(root, text=u'日:').grid(row=1, column=4, sticky=W, padx=3, pady=3)
  118. eday = Entry(root, width=8)
  119. eday.grid(row=1, column=5, sticky=W, padx=3, pady=3)
  120. Label(root, text=u'住址:').grid(row=2, column=0, sticky=W, padx=3, pady=3)
  121. eaddr = Entry(root, width=32)
  122. eaddr.grid(row=2, column=1, sticky=W, padx=3, pady=3, columnspan=5)
  123. Label(root, text=u'证件号码:').grid(row=3, column=0, sticky=W, padx=3, pady=3)
  124. eidn = Entry(root, width=32)
  125. eidn.grid(row=3, column=1, sticky=W, padx=3, pady=3, columnspan=5)
  126. Label(root, text=u'签发机关:').grid(row=4, column=0, sticky=W, padx=3, pady=3)
  127. eorg = Entry(root, width=32)
  128. eorg.grid(row=4, column=1, sticky=W, padx=3, pady=3, columnspan=5)
  129. Label(root, text=u'有效期限:').grid(row=5, column=0, sticky=W, padx=3, pady=3)
  130. elife = Entry(root, width=32)
  131. elife.grid(row=5, column=1, sticky=W, padx=3, pady=3, columnspan=5)
  132. Label(root, text=u'选项:').grid(row=6, column=0, sticky=W, padx=3, pady=3)
  133. ebgvar = IntVar()
  134. ebg = Checkbutton(root, text=u'自动抠图', variable=ebgvar)
  135. ebg.grid(row=6, column=1, sticky=W, padx=3, pady=3, columnspan=5)
  136. Button(root, text=u'生成', width=32, command=generator).grid(row=7, column=1, sticky=W, padx=3, pady=3, columnspan=4)
  137. # root.iconbitmap(os.path.join(base_dir, 'ico.ico'))
  138. root.mainloop()

 之前上传代码使用项目命名:“Python+OpenCv制作身份证图片生成器代码”,额、但是官方宣布违规禁止上传,所示将项目名称修改的不是那么明显,感兴趣的小伙伴可以下载运行:https://download.csdn.net/download/m0_38106923/11033615

当然为了方便操作,也可以使用pyinstaller模块自己打包成应用程序,首先需要使用命令安装pyinstaller模块:

pip install pyinstaller

Mac打包(打包成Mac app尚有问题未解决)

pyinstaller -i usedres/ico.icns --windowed --clean --noconfirm --onefile --add-data ./usedres:./usedres idcardgenerator.py

Windows打包

pyinstaller -i usedres/ico.ico --windowed --clean --noconfirm --onefile --add-data usedres;usedres idcardgenerator.py

 



所属网站分类: 技术文章 > 博客

作者:大壮

链接:https://www.pythonheidong.com/blog/article/10475/9a845c93be02dc47af9e/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

1 0
收藏该文
已收藏

评论内容:(最多支持255个字符)