分享

python 图片常用操作

 ly88 2024-12-30 发布于山西

2 篇文章0 订阅

一, 图片与base64编码互相转换

  1. import base64
  2. with open('a.jpg','rb') as f:
  3. b6=base64.b64encode(f.read())
  4. print(b6[:50])
  5. # 部分base64编码如下:
  6. # 执行结果:
  7. b'/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQ'
  8. # 2, 将base64编码转换成图片
  9. with open('b.jpg','wb') as f:
  10. f.write(base64.b64decode(b6))

二,字符串生成图片

  1. import os
  2. import math
  3. import random
  4. from uuid import uuid1
  5. from PIL import Image, ImageDraw, ImageFont, ImageFilter
  6. def char_img(zt,str1):
  7. """ 字符串生成图片。zt:字体.ttf文件。str1:字符串。 """
  8. # 实例一个图片对象240 x 60:
  9. width = 40*len(str1) #60 * 4
  10. height = 60
  11. # 图片颜色
  12. r = random.randint(0,200)
  13. g = random.randint(0,200)
  14. b = random.randint(0,200)
  15. clo = (r, g, b)
  16. image = Image.new('RGB', (width, height), clo)
  17. # 创建Font对象:
  18. # 字体文件可以使用操作系统的,也可以网上下载
  19. zt = zt # 'a.ttf'
  20. font = ImageFont.truetype(zt, 36)
  21. # 创建Draw对象:
  22. draw = ImageDraw.Draw(image)
  23. # 输出文字:
  24. # str1 = "我爱世界"
  25. w = 4 #距离图片左边距离
  26. h = 10 #距离图片上边距离
  27. draw.text((w, h), str1, font=font)
  28. # 模糊:
  29. image.filter(ImageFilter.BLUR)
  30. code_name = 'test_code_img.jpg'
  31. save_dir = './{}'.format(code_name)
  32. image.save(save_dir, 'jpeg')
  33. print("已保存图片: {}".format(save_dir))
  34. if __name__ == '__main__':
  35. zt = 'HKSN.ttf'
  36. str1 = '我爱你'
  37. char_img(zt,str1)

执行结果:

三, 方图转换为圆形图片

  1. import os
  2. import math
  3. import random
  4. from uuid import uuid1
  5. from PIL import Image, ImageDraw, ImageFont, ImageFilter
  6. def circle(fn):
  7. """ 把图片变成圆形图片。fn:图片路径 """
  8. ima = Image.open(fn).convert("RGBA")
  9. # ima = ima.resize((600, 600), Image.ANTIALIAS)
  10. size = ima.size
  11. # 因为是要圆形,所以需要正方形的图片
  12. r2 = min(size[0], size[1])
  13. if size[0] != size[1]:
  14. ima = ima.resize((r2, r2), Image.ANTIALIAS)
  15. # 最后生成圆的半径
  16. r3 = 60
  17. imb = Image.new('RGBA', (r3*2, r3*2),(255,255,255,0))
  18. pima = ima.load() # 像素的访问对象
  19. pimb = imb.load()
  20. r = float(r2/2) #圆心横坐标
  21. for i in range(r2):
  22. for j in range(r2):
  23. lx = abs(i-r) #到圆心距离的横坐标
  24. ly = abs(j-r)#到圆心距离的纵坐标
  25. l = (pow(lx,2) + pow(ly,2))** 0.5 # 三角函数 半径
  26. if l < r3:
  27. pimb[i-(r-r3),j-(r-r3)] = pima[i,j]
  28. save_dir = "test_circle.png"
  29. imb.save(save_dir)
  30. print("已保存图片: {}".format(save_dir))
  31. if __name__ == '__main__':
  32. circle('python.jpg')

执行结果:

四, 生成随机图形验证码

  1. import os
  2. import math
  3. import random
  4. from uuid import uuid1
  5. from PIL import Image, ImageDraw, ImageFont, ImageFilter
  6. class Yzm:
  7. """ 生成字符验证码图片 """
  8. def __init__(self,ttf):
  9. self.ttf = ttf
  10. def rnd_char(self):
  11. '''
  12. 随机一个字母或者数字
  13. :return:
  14. '''
  15. # 随机一个字母或者数字
  16. i = random.randint(1, 3)
  17. if i == 1:
  18. # 随机个数字的十进制ASCII码
  19. an = random.randint(97, 122)
  20. elif i == 2:
  21. # 随机个小写字母的十进制ASCII码
  22. an = random.randint(65, 90)
  23. else:
  24. # 随机个大写字母的十进制ASCII码
  25. an = random.randint(48, 57)
  26. # 根据Ascii码转成字符,return回去
  27. return chr(an)
  28. #  干扰
  29. def rnd_dis(self):
  30. '''
  31. 随机一个干扰字
  32. :return:
  33. '''
  34. d = ['^', '-', '~', '_', '.']
  35. i = random.randint(0, len(d) - 1)
  36. return d[i]
  37. # 两个随机颜色都规定不同的区域,防止干扰字符和验证码字符颜色一样
  38. # 随机颜色1:
  39. def rnd_color(self):
  40. '''
  41. 随机颜色,规定一定范围
  42. :return:
  43. '''
  44. return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
  45. # 随机颜色2:
  46. def rnd_color2(self):
  47. '''
  48. 随机颜色,规定一定范围
  49. :return:
  50. '''
  51. return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
  52. def create_code(self):
  53. # 240 x 60:
  54. width = 60 * 4
  55. height = 60
  56. image = Image.new('RGB', (width, height), (192, 192, 192))
  57. # 创建Font对象:
  58. font = ImageFont.truetype(self.ttf, 36)
  59. # 创建Draw对象:
  60. draw = ImageDraw.Draw(image)
  61. # 填充每个像素:
  62. for x in range(0, width, 20):
  63. for y in range(0, height, 10):
  64. draw.point((x, y), fill=self.rnd_color())
  65. # 填充字符
  66. _str = ""
  67. # 填入4个随机的数字或字母作为验证码
  68. for t in range(4):
  69. c = self.rnd_char()
  70. _str = "{}{}".format(_str, c)
  71. # 随机距离图片上边高度,但至少距离30像素
  72. h = random.randint(1, height - 30)
  73. # 宽度的化,每个字符占图片宽度1/4,在加上10个像素空隙
  74. w = width / 4 * t + 10
  75. draw.text((w, h), c, font=font, fill=self.rnd_color2())
  76. # 实际项目中,会将验证码 保存在数据库,并加上时间字段
  77. print("保存验证码 {} 到数据库".format(_str))
  78. # 给图片加上字符干扰,密集度由 w, h控制
  79. for j in range(0, width, 30):
  80. dis = self.rnd_dis()
  81. w = t * 15 + j
  82. # 随机距离图片上边高度,但至少距离30像素
  83. h = random.randint(1, height - 30)
  84. draw.text((w, h), dis, font=font, fill=self.rnd_color())
  85. # 模糊:
  86. image.filter(ImageFilter.BLUR)
  87. # uuid1 生成唯一的字符串作为验证码图片名称
  88. code_name = '{}.jpg'.format(uuid1())
  89. save_dir = './{}'.format(code_name)
  90. image.save(save_dir, 'jpeg')
  91. print("已保存图片: {}".format(save_dir))
  92. if __name__ == "__main__":
  93. yzm = Yzm('华康少女体\\HKSN.ttf')
  94. yzm.create_code()

执行结果:

五, 修改图片尺寸

  1. def img_size(fileName,width,height):
  2. """ fileName: 图片路径,width:修改宽度,height:修改高度 """
  3. from PIL import Image # 导入相应模块
  4. image = Image.open(fileName)
  5. w, h = image.size # 原图尺寸
  6. new_img = image.resize((width,height),Image.ANTIALIAS)
  7. _new = 'new_'+fileName
  8. new_img.save(_new)
  9. new_img.close()
  10. print('原图: %s, 尺寸为: %d,%d'%(fileName,w,h))
  11. print('修改后的图片: %s 尺寸为: %d,%d'%(_new,width,height))
  12. img_size('a.jpg',80,90)

执行结果:

原图: a.jpg, 尺寸为: 518,545
修改后的图片: new_a.jpg 尺寸为: 80,90

六, 图片转换为字符图

  1. from PIL import Image, ImageDraw, ImageFont
  2. import os
  3. import time
  4. class IMG_STR:
  5. def __init__(self, img_name):
  6. self.img_name = img_name
  7. def save(self, img, file_name):
  8. if os.path.isfile(file_name):
  9. file_name=file_name.split('.')
  10. self.save(img, file_name[0] + 'o.' + file_name[1])
  11. else:
  12. img.save(file_name, 'JPEG')
  13. def main(self):
  14. f_size = 16
  15. f_num_x = 100
  16. font_map = [' ', '.', 'i', 'I', 'J', 'C', 'D', 'O', 'S', 'Q', 'G', 'F', 'E', '#', '&', '@']
  17. im = Image.open(self.img_name).convert('L')
  18. im = im.resize((f_num_x, int(f_num_x * im.size[1] / im.size[0])))
  19. level = im.getextrema()[-1] / (len(font_map) - 1)
  20. im = im.point(lambda i: int(i / level))
  21. imn = Image.new('L', (im.size[0] * f_size, im.size[1] * f_size))
  22. f = ImageFont.truetype('arial.ttf', f_size)
  23. d = ImageDraw.Draw(imn)
  24. for y in range(0, im.size[1]):
  25. for x in range(0, im.size[0]):
  26. pp = im.getpixel((x, y))
  27. d.text((x * f_size, y * f_size), font_map[len(font_map) - pp - 1], fill=255, font=f)
  28. self.save(imn, self.img_name)
  29. if __name__ == '__main__':
  30. img = IMG_STR('xn.jpg')
  31. img.main()

执行前后比对:

七, 图片写入字符串

  1. from PIL import Image
  2. import sys
  3. def makeImageEven(image):
  4. '''取得一个PIL图形并且更改所有值为偶数(使最低有效位为0)'''
  5. pixels=list(image.getdata()) # 得到一个列表: [(r,g,b,t)...]
  6. evenPixels=[(r>>1<<1,g>>1<<1,b>>1<<1) for (r,g,b) in pixels] # 更改所有值为偶数
  7. evenImage=Image.new(image.mode, image.size) # 创建一个相同大小的图片
  8. evenImage.putdata(evenPixels) # 把上面的像素放入到图片副本
  9. return evenImage
  10. def constLenBin(ints):
  11. '''返回固定长度的二进制字符串'''
  12. binary='0'*(8-(len(bin(ints))-2))+bin(ints).replace('0b', '') # 去掉0b,并在左边补足'0'直到字符串长度为8
  13. return binary
  14. def encodeDataInImage(image,data):
  15. '''将字符串编码到图片中'''
  16. evenImage=makeImageEven(image) # 获得最低有效位为0的图片副本
  17. binary=''.join(map(constLenBin,bytearray(data,'utf-8'))) # 将需要隐藏的字符串转换成二进制字符串
  18. if len(binary)>len(image.getdata())*3: # 如果不能编码全部数据,抛出异常
  19. raise Exception("Error: Cant encode more than "+len(evenImage.getdata())*3+" bits in this image. ")
  20. # 将 binary 中的二进制字符串信息编码进像素里
  21. encodePixels=[(r+int(binary[index*3+0]),g+int(binary[index*3+1]),b+int(binary[index*3+2])) if index*3<len(binary) else (r,g,b) for index,(r,g,b) in enumerate(list(evenImage.getdata()))]
  22. encodedImage=Image.new(evenImage.mode, evenImage.size) # 创建新图片以存放编码后的像素
  23. encodedImage.putdata(encodePixels) # 添加编码后的数据
  24. return encodedImage
  25. def binaryToString(binary):
  26. '''从二进制字符串转为 utf-8 字符串'''
  27. index=0
  28. string=[]
  29. rec=lambda x,i:x[2:8]+(rec(x[8:],i-1) if i>1 else '') if x else ''
  30. fun=lambda x,i:x[i+1:8]+rec(x[8:], i-1)
  31. while index+1<len(binary):
  32. chartype=binary[index:].index('0') #存放字节所占字节数,一个字节的字符则存为0
  33. length=chartype*8 if chartype else 8
  34. string.append(chr(int(fun(binary[index:index+length],chartype),2)))
  35. index+=length
  36. return ''.join(string)
  37. def decodeImage(image):
  38. '''解码隐藏数据'''
  39. pixels=list(image.getdata()) # 获得像素列表
  40. # 读取图片中所有最低有效位中的数据
  41. binary=''.join([str(int(r>>1<<1!=r))+str(int(g>>1<<1!=g))+str(int(b>>1<<1!=b)) for (r,g,b) in pixels])
  42. ldn=binary.find('0'*16) # 找到数据截止处的索引
  43. endIndex=ldn+(8-(ldn%8)) if ldn%8!=0 else ldn
  44. data=binaryToString(binary[0:endIndex])
  45. return data
  46. if __name__=='__main__':
  47. # 把字符串写入图片 a.jpg
  48. encodeDataInImage(Image.open('a.jpg'), '我爱你').save('encodeImage.png')
  49. # 解码隐藏的字符串
  50. print(decodeImage(Image.open('encodeImage.png')))

执行程序前的图片:

执行结果输出:

我爱你

执行程序后写入字符串的图片:

八、图片背景透明化

'

九、PDF文件转换为图片

我的环境是Windows10、Python3.6

1、先安装所需要的Python库
pip install traits
pip install fitz
pip install PyMuPDF

2、示例代码如下

  1. import fitz
  2. def pdf_to_image(pdf_name, to_imgs, x, y, rotate):
  3. """pdf_name pdf文件名称
  4. to_imgs 图片要保存的目录
  5. x x方向的缩放系数
  6. y y方向的缩放系数
  7. rotate 旋转角度
  8. 注:x和y一般取相同值,值越大,图像分辨率越高。
  9. """
  10. # 打开PDF文件
  11. pdf = fitz.open(pdf_name)
  12. # 逐页读取PDF
  13. for pg in range(0, pdf.pageCount):
  14. page = pdf[pg]
  15. # 设置缩放和旋转系数
  16. trans = fitz.Matrix(x, y).preRotate(rotate)
  17. pm = page.getPixmap(matrix=trans, alpha=False)
  18. # 开始写图像
  19. pm.writePNG(to_imgs+str(pg)+".png")
  20. pdf.close()
  21. pdf_to_image('我的合同.pdf', 'c\\', 5, 5, 0)

十、图片转换为PDF文件

1、安装所需的库

pip install reportlab

2、示例代码如下

  1. from reportlab.pdfgen import canvas
  2. from reportlab.lib.units import inch, cm
  3. from reportlab.lib.pagesizes import letter
  4. from reportlab.platypus import SimpleDocTemplate, Paragraph, Image, PageBreak
  5. from reportlab.lib.pagesizes import A4,A3,A2,A1, legal, landscape
  6. from reportlab.lib.utils import ImageReader
  7. from PIL import Image, ExifTags
  8. from os import listdir
  9. import os, re
  10. import time
  11. from reportlab.lib.units import inch
  12. def img_search(mypath, filenames):
  13. for lists in os.listdir(mypath):
  14. path = os.path.join(mypath,lists)
  15. if os.path.isfile(path):
  16. expression = r'[\w]+\.(jpg|png|jpeg)$'
  17. if re.search(expression, path, re.IGNORECASE):
  18. filenames.append(path)
  19. elif os.path.isdir(path):
  20. img_search(path, filenames)
  21. def rotate_img_to_proper(image):
  22. try:
  23. if hasattr(image, '_getexif'):
  24. for orientation in ExifTags.TAGS.keys():
  25. if ExifTags.TAGS[orientation] == 'Orientation':
  26. break
  27. e = image._getexif()
  28. if e is not None:
  29. exif = dict(e.items())
  30. orientation = exif[orientation]
  31. if orientation == 3:
  32. image = image.transpose(Image.ROTATE_180)
  33. elif orientation == 6:
  34. image = image.transpose(Image.ROTATE_270)
  35. elif orientation == 8:
  36. image = image.rotate(90, expand=True)
  37. except Exception as ex:
  38. print(ex)
  39. return image
  40. def main(imgs, compress=0.5):
  41. """
  42. imgs:图片存储路径
  43. compress:图片缩放比例
  44. """
  45. save_name = 'new.pdf' # 保存文件名
  46. imgDoc = canvas.Canvas(save_name) # pagesize=0.5
  47. imgDoc.setPageSize(A4)
  48. document_width, document_height = A4
  49. filenames=[]
  50. start = time.clock()
  51. img_search(imgs, filenames)
  52. end = time.clock()
  53. print('find file cost time: ', end-start, 'find files: ', len(filenames))
  54. for image in filenames:
  55. try:
  56. image_file = Image.open(image)
  57. w, h = image_file.size # 原图尺寸
  58. image_file = image_file.resize((int(w*compress), int(h*compress)), Image.ANTIALIAS) # 调整图片尺寸
  59. image_file = rotate_img_to_proper(image_file)
  60. image_width, image_height = image_file.size
  61. print('img size:', image_file.size)
  62. if not(image_width>0 and image_height>0):
  63. raise Exception
  64. image_aspect = image_height/float(image_width)
  65. print_width = document_width
  66. print_height = document_width*image_aspect
  67. imgDoc.drawImage(ImageReader(image_file),document_width-print_width,
  68. document_height-print_height,width=print_width,
  69. height=print_height,preserveAspectRatio=True)
  70. imgDoc.showPage()
  71. except Exception as e:
  72. print('error:', e, image)
  73. imgDoc.save()
  74. print(save_name)
  75. main(r'C:\Users\Administrator\Desktop\pimg\images')

十一、图片拼接,拼接多张图片为一张

  1. from PIL import Image, ImageDraw, ImageFont
  2. import cv2
  3. import numpy as np
  4. def jigsaw(imgs, direction=None, gap=0):
  5. """ direction:horizontal,vertical;水平,垂直,为空则根据图片方向选择 """
  6. imgs = [Image.fromarray(img) for img in imgs]
  7. w, h = imgs[0].size
  8. if direction == "horizontal" or (not direction and w <= h):
  9. result = Image.new(imgs[0].mode, ((w+gap)*len(imgs)-gap, h))
  10. for i, img in enumerate(imgs):
  11. result.paste(img, box=((w+gap)*i, 0))
  12. elif direction == "vertical" or (not direction and w > h):
  13. result = Image.new(imgs[0].mode, (w, (h+gap)*len(imgs)-gap))
  14. for i, img in enumerate(imgs):
  15. result.paste(img, box=(0, (h+gap)*i))
  16. else:
  17. result = {}
  18. print("请选择拼接方向,水平或者垂直拼接!")
  19. return np.array(result)
  20. def main():
  21. img1 = cv2.imread("a1.jpg")
  22. img2 = cv2.imread("a2.jpg")
  23. img3 = cv2.imread("a3.jpg")
  24. img = jigsaw([img1, img2, img3])
  25. # cv2.imwrite("new_img.png", img)
  26. cv2.imwrite("new_img.jpg", img)
  27. main()

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多