2025年2月14日 星期五 甲辰(龙)年 腊月十四 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Python

python 图片常用操作

时间:04-01来源:作者:点击数:46

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

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

二,字符串生成图片

  • import os
  • import math
  • import random
  • from uuid import uuid1
  • from PIL import Image, ImageDraw, ImageFont, ImageFilter
  • def char_img(zt,str1):
  • """ 字符串生成图片。zt:字体.ttf文件。str1:字符串。 """
  • # 实例一个图片对象240 x 60:
  • width = 40*len(str1) #60 * 4
  • height = 60
  • # 图片颜色
  • r = random.randint(0,200)
  • g = random.randint(0,200)
  • b = random.randint(0,200)
  • clo = (r, g, b)
  • image = Image.new('RGB', (width, height), clo)
  • # 创建Font对象:
  • # 字体文件可以使用操作系统的,也可以网上下载
  • zt = zt # 'a.ttf'
  • font = ImageFont.truetype(zt, 36)
  • # 创建Draw对象:
  • draw = ImageDraw.Draw(image)
  • # 输出文字:
  • # str1 = "我爱世界"
  • w = 4 #距离图片左边距离
  • h = 10 #距离图片上边距离
  • draw.text((w, h), str1, font=font)
  • # 模糊:
  • image.filter(ImageFilter.BLUR)
  • code_name = 'test_code_img.jpg'
  • save_dir = './{}'.format(code_name)
  • image.save(save_dir, 'jpeg')
  • print("已保存图片: {}".format(save_dir))
  • if __name__ == '__main__':
  • zt = 'HKSN.ttf'
  • str1 = '我爱你'
  • char_img(zt,str1)

执行结果:

三, 方图转换为圆形图片

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

执行结果:

四, 生成随机图形验证码

  • import os
  • import math
  • import random
  • from uuid import uuid1
  • from PIL import Image, ImageDraw, ImageFont, ImageFilter
  • class Yzm:
  • """ 生成字符验证码图片 """
  • def __init__(self,ttf):
  • self.ttf = ttf
  • def rnd_char(self):
  • '''
  • 随机一个字母或者数字
  • :return:
  • '''
  • # 随机一个字母或者数字
  • i = random.randint(1, 3)
  • if i == 1:
  • # 随机个数字的十进制ASCII码
  • an = random.randint(97, 122)
  • elif i == 2:
  • # 随机个小写字母的十进制ASCII码
  • an = random.randint(65, 90)
  • else:
  • # 随机个大写字母的十进制ASCII码
  • an = random.randint(48, 57)
  • # 根据Ascii码转成字符,return回去
  • return chr(an)
  • #  干扰
  • def rnd_dis(self):
  • '''
  • 随机一个干扰字
  • :return:
  • '''
  • d = ['^', '-', '~', '_', '.']
  • i = random.randint(0, len(d) - 1)
  • return d[i]
  • # 两个随机颜色都规定不同的区域,防止干扰字符和验证码字符颜色一样
  • # 随机颜色1:
  • def rnd_color(self):
  • '''
  • 随机颜色,规定一定范围
  • :return:
  • '''
  • return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
  • # 随机颜色2:
  • def rnd_color2(self):
  • '''
  • 随机颜色,规定一定范围
  • :return:
  • '''
  • return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
  • def create_code(self):
  • # 240 x 60:
  • width = 60 * 4
  • height = 60
  • image = Image.new('RGB', (width, height), (192, 192, 192))
  • # 创建Font对象:
  • font = ImageFont.truetype(self.ttf, 36)
  • # 创建Draw对象:
  • draw = ImageDraw.Draw(image)
  • # 填充每个像素:
  • for x in range(0, width, 20):
  • for y in range(0, height, 10):
  • draw.point((x, y), fill=self.rnd_color())
  • # 填充字符
  • _str = ""
  • # 填入4个随机的数字或字母作为验证码
  • for t in range(4):
  • c = self.rnd_char()
  • _str = "{}{}".format(_str, c)
  • # 随机距离图片上边高度,但至少距离30像素
  • h = random.randint(1, height - 30)
  • # 宽度的化,每个字符占图片宽度1/4,在加上10个像素空隙
  • w = width / 4 * t + 10
  • draw.text((w, h), c, font=font, fill=self.rnd_color2())
  • # 实际项目中,会将验证码 保存在数据库,并加上时间字段
  • print("保存验证码 {} 到数据库".format(_str))
  • # 给图片加上字符干扰,密集度由 w, h控制
  • for j in range(0, width, 30):
  • dis = self.rnd_dis()
  • w = t * 15 + j
  • # 随机距离图片上边高度,但至少距离30像素
  • h = random.randint(1, height - 30)
  • draw.text((w, h), dis, font=font, fill=self.rnd_color())
  • # 模糊:
  • image.filter(ImageFilter.BLUR)
  • # uuid1 生成唯一的字符串作为验证码图片名称
  • code_name = '{}.jpg'.format(uuid1())
  • save_dir = './{}'.format(code_name)
  • image.save(save_dir, 'jpeg')
  • print("已保存图片: {}".format(save_dir))
  • if __name__ == "__main__":
  • yzm = Yzm('华康少女体\\HKSN.ttf')
  • yzm.create_code()

执行结果:

五, 修改图片尺寸

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

执行结果:

原图: a.jpg, 尺寸为: 518,545

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

六, 图片转换为字符图

  • from PIL import Image, ImageDraw, ImageFont
  • import os
  • import time
  • class IMG_STR:
  • def __init__(self, img_name):
  • self.img_name = img_name
  • def save(self, img, file_name):
  • if os.path.isfile(file_name):
  • file_name=file_name.split('.')
  • self.save(img, file_name[0] + 'o.' + file_name[1])
  • else:
  • img.save(file_name, 'JPEG')
  • def main(self):
  • f_size = 16
  • f_num_x = 100
  • font_map = [' ', '.', 'i', 'I', 'J', 'C', 'D', 'O', 'S', 'Q', 'G', 'F', 'E', '#', '&', '@']
  • im = Image.open(self.img_name).convert('L')
  • im = im.resize((f_num_x, int(f_num_x * im.size[1] / im.size[0])))
  • level = im.getextrema()[-1] / (len(font_map) - 1)
  • im = im.point(lambda i: int(i / level))
  • imn = Image.new('L', (im.size[0] * f_size, im.size[1] * f_size))
  • f = ImageFont.truetype('arial.ttf', f_size)
  • d = ImageDraw.Draw(imn)
  • for y in range(0, im.size[1]):
  • for x in range(0, im.size[0]):
  • pp = im.getpixel((x, y))
  • d.text((x * f_size, y * f_size), font_map[len(font_map) - pp - 1], fill=255, font=f)
  • self.save(imn, self.img_name)
  • if __name__ == '__main__':
  • img = IMG_STR('xn.jpg')
  • img.main()

执行前后比对:


七, 图片写入字符串

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

执行程序前的图片:

执行结果输出:

我爱你

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

八、图片背景透明化

  • from PIL import Image
  • import numpy
  • import os
  • def get_convert_middle(img_path):
  • I = Image.open(img_path)
  • L = I.convert('L')
  • im = numpy.array(L)
  • im4 = 255.0 * (im / 255.0) ** 2 # 对图像的像素值求平方后得到的图像
  • middle = (int(im4.min()) + int(im4.max())) / 2
  • return middle
  • def transparent_background(path):
  • """ 读取图片,把背景透明化,再写入原图片 """
  • try:
  • img = Image.open(path)
  • img = img.convert("RGBA") # 转换获取信息
  • pixdata = img.load()
  • color_no = get_convert_middle(path) + 30 # 抠图的容错值
  • for y in range(img.size[1]):
  • for x in range(img.size[0]):
  • if pixdata[x, y][0] > color_no and pixdata[x, y][1] > color_no and pixdata[x, y][2] > color_no and \
  • pixdata[x, y][3] > color_no:
  • pixdata[x, y] = (255, 255, 255, 0)
  • if not path.endswith('png'):
  • os.remove(path)
  • replace_path_list = path.split('.')
  • replace_path_list = replace_path_list[:-1]
  • path = '.'.join(replace_path_list) + '.png'
  • img.save(path)
  • img.close()
  • except Exception as e:
  • print(e)

九、PDF文件转换为图片

我的环境是Windows10、Python3.6

1、先安装所需要的Python库

pip install traits

pip install fitz

pip install PyMuPDF

2、示例代码如下

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

十、图片转换为PDF文件

1、安装所需的库

pip install reportlab

2、示例代码如下

  • from reportlab.pdfgen import canvas
  • from reportlab.lib.units import inch, cm
  • from reportlab.lib.pagesizes import letter
  • from reportlab.platypus import SimpleDocTemplate, Paragraph, Image, PageBreak
  • from reportlab.lib.pagesizes import A4,A3,A2,A1, legal, landscape
  • from reportlab.lib.utils import ImageReader
  • from PIL import Image, ExifTags
  • from os import listdir
  • import os, re
  • import time
  • from reportlab.lib.units import inch
  • def img_search(mypath, filenames):
  • for lists in os.listdir(mypath):
  • path = os.path.join(mypath,lists)
  • if os.path.isfile(path):
  • expression = r'[\w]+\.(jpg|png|jpeg)$'
  • if re.search(expression, path, re.IGNORECASE):
  • filenames.append(path)
  • elif os.path.isdir(path):
  • img_search(path, filenames)
  • def rotate_img_to_proper(image):
  • try:
  • if hasattr(image, '_getexif'):
  • for orientation in ExifTags.TAGS.keys():
  • if ExifTags.TAGS[orientation] == 'Orientation':
  • break
  • e = image._getexif()
  • if e is not None:
  • exif = dict(e.items())
  • orientation = exif[orientation]
  • if orientation == 3:
  • image = image.transpose(Image.ROTATE_180)
  • elif orientation == 6:
  • image = image.transpose(Image.ROTATE_270)
  • elif orientation == 8:
  • image = image.rotate(90, expand=True)
  • except Exception as ex:
  • print(ex)
  • return image
  • def main(imgs, compress=0.5):
  • """
  • imgs:图片存储路径
  • compress:图片缩放比例
  • """
  • save_name = 'new.pdf' # 保存文件名
  • imgDoc = canvas.Canvas(save_name) # pagesize=0.5
  • imgDoc.setPageSize(A4)
  • document_width, document_height = A4
  • filenames=[]
  • start = time.clock()
  • img_search(imgs, filenames)
  • end = time.clock()
  • print('find file cost time: ', end-start, 'find files: ', len(filenames))
  • for image in filenames:
  • try:
  • image_file = Image.open(image)
  • w, h = image_file.size # 原图尺寸
  • image_file = image_file.resize((int(w*compress), int(h*compress)), Image.ANTIALIAS) # 调整图片尺寸
  • image_file = rotate_img_to_proper(image_file)
  • image_width, image_height = image_file.size
  • print('img size:', image_file.size)
  • if not(image_width>0 and image_height>0):
  • raise Exception
  • image_aspect = image_height/float(image_width)
  • print_width = document_width
  • print_height = document_width*image_aspect
  • imgDoc.drawImage(ImageReader(image_file),document_width-print_width,
  • document_height-print_height,width=print_width,
  • height=print_height,preserveAspectRatio=True)
  • imgDoc.showPage()
  • except Exception as e:
  • print('error:', e, image)
  • imgDoc.save()
  • print(save_name)
  • main(r'C:\Users\Administrator\Desktop\pimg\images')

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

  • from PIL import Image, ImageDraw, ImageFont
  • import cv2
  • import numpy as np
  • def jigsaw(imgs, direction=None, gap=0):
  • """ direction:horizontal,vertical;水平,垂直,为空则根据图片方向选择 """
  • imgs = [Image.fromarray(img) for img in imgs]
  • w, h = imgs[0].size
  • if direction == "horizontal" or (not direction and w <= h):
  • result = Image.new(imgs[0].mode, ((w+gap)*len(imgs)-gap, h))
  • for i, img in enumerate(imgs):
  • result.paste(img, box=((w+gap)*i, 0))
  • elif direction == "vertical" or (not direction and w > h):
  • result = Image.new(imgs[0].mode, (w, (h+gap)*len(imgs)-gap))
  • for i, img in enumerate(imgs):
  • result.paste(img, box=(0, (h+gap)*i))
  • else:
  • result = {}
  • print("请选择拼接方向,水平或者垂直拼接!")
  • return np.array(result)
  • def main():
  • img1 = cv2.imread("a1.jpg")
  • img2 = cv2.imread("a2.jpg")
  • img3 = cv2.imread("a3.jpg")
  • img = jigsaw([img1, img2, img3])
  • # cv2.imwrite("new_img.png", img)
  • cv2.imwrite("new_img.jpg", img)
  • main()
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门