本文转载自微信公众号《Python7号》,作者somenzz。转载本文请联系Python七号公众号。很多不是IT行业的朋友都在学习Python。他们的目的也很简单,就是提高工作效率。希望用Python来完成简单和重复的任务。因此,我准备写一些Python自动化办公系列相关的文章。代码在Python3上可以正常运行。复制代码并调整细节以使用它。先发在公众号,再同步到知识星球。为什么要同步到知识星球,因为修改公众号的文章很麻烦,但是知识星球比较简单,这样就可以迭代更新文章中的代码,重要的是可以问一个-如果您有任何问题,请单独提问。加入星球的方式稍后公布。在我们的日常工作和生活中,我们经常会和图片打交道,比如下载图片、压缩图片、删除图片元数据防止隐私泄露、拼接长图片、识别图片中的文字、添加水印等。今天分享一下如何用Python简单的玩转这些操作。1.下载图片下载图片是最简单的操作。无非就是找到图片的url,使用标准库或者requests库去请求url,然后将得到的数据保存为文件。下面介绍三种下载图片的方法。方法一,使用标准库。fromurllib.requestimporturlretrievefrompathlibimportPathimportssldefurllib_download(img_url,download_path):ssl._create_default_https_context=ssl._create_unverified_contexturlretrieve(img_url,Path(download_path)/'image1.png')方法二,使用requests。importrequestsdefrequest_download(img_url,download_path):r=requests.get(img_url)withopen(f'{download_path}/image2.png','wb')asf:f.write(r.content)方法二,使用流方式requestsDownload,适合大,网速慢,容易下载失败的图片。importrequestsdefrequests_chunk_download(img_url,download_path):r=requests.get(img_url,stream=True)withopen(f'{download_path}/image3.png','wb')asf:forchunkinr.iter_content(chunk_size=32):f.write(chunk)单独下载一张图片看结果:if__name__=='__main__':img_url='https://tinypng.com/images/panda-developing-2x.png'download_path=Path('/Users/aaron/tmp/images')download_path.mkdir(exist_ok=True)urllib_download(img_url,download_path.as_posix())request_download(img_url,download_path.as_posix())requests_chunk_download(img_url,download_path.as_posix())三个方法来获取大小下载图像是一样的。如果自动下载某个网站的所有图片,其实一点都不复杂。无非就是找规律,怎么得到所有图片的url,然后循环调用上面三个函数。获取图片url可能涉及到正则表达式。关于正则表达式,大家可以参考之前的文章学习正则表达式,玩转手掌上的文字。2.压缩图片有一次我发5张图片给老板发邮件的时候,foxmail提示我是否启用QQ邮箱的超大附件功能,原来5张图片已经40+MB了,现在手机拍的照片真的太清楚了。不过工作中能看清楚图片内容就够了。没必要讲得那么清楚。文件太大。如果发给老板,老板打开图片的时候会卡住。体验很差,所以想用Python压缩图片。.我搜索了很多方法,但没有一个是理想的。有的软件是下载后付费的,有的直接导致程序在使用时卡死,有的压缩率不够需要多次压缩,有的要求原图大小不超过5M,有的失真有点严肃的。直到用了tinypng的api接口,才发现原来真的好用。图片几乎没有失真,大部分都控制在1MB以内。我想在这里与您分享。首先打开https://tinypng.com/developers,在下面输入你的用户名和邮箱,就可以得到一个APIKEY。然后pip安装这个库:pipinstalltinify可以通过写三行代码来压缩图片:importtinifytinify.key='fillinyourkeyhere'tinify.from_file(src_img_path).to_file(dst_img_path)其中src_img_path是原图,dst_img_path是压缩图像。比如找一个目录,批量压缩文件:importtinifyfrompathlibimportPathimportostinify.key='这里填写你的key'path="/Users/aaron/Documents/personal/origin"#图片存放路径为dirpath,dirs,filesinos.walk(path):forfileinfiles:file=Path(dirpath)/Path(file)iffile.suffix.lower()in['.jpg','.png','.gif']:print("正在压缩。."+file.as_posix())tinify.from_file(file.as_posix()).to_file(file.with_suffix(".compressed.jpg").as_posix())可以看到压缩后的文件大小在1M左右还是1M以内,打开文件对比,基本看不出有什么区别:3.删除图片的元数据现在大部分快递员已经可以对地址信息进行加密,大家的隐私保护意识也越来越高,但是如果您不小心,您随意发布的照片??可能会泄露您的位置信息。因此,用户在发布照片时,需要去除照片的位置、设备、时间等隐私信息。这些信息也称为元数据,或元数据。Python有一个第三方库piexif可以删除图片的元数据。我用它删除后,再用exiftool查看,还是能查到很多私密信息。也就是piexif删除的不够彻底,所以我用Python封装了exiftool,现在可以把图片的元数据彻底删除了。文件exif_t??ool.py代码如下:importsubprocessimportosimportjsonfrompathlibimportPathclassExifTool(object):sentinel="{ready}\n"#windows#sentinel="{ready}\r\n"def__init__(self,executable="/usr/bin/exiftool"):exiftool1=路径("/usr/bin/exiftool")exiftool2=路径("/usr/local/bin/exiftool")self.executable=executableifexiftool1.exists():self.executable=exiftool1.as_posix()elifexiftool2。exists():self.executable=exiftool2.as_posix()else:ifPath(self.executable).exists():passelse:raiseFileNotFoundError(self.executable)def__enter__(self):self.process=subprocess.Popen([self.可执行文件,"-stay_open","True","-@","-"],universal_newlines=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE)returnsselfdef__exit__(self,exc_type,exc_value,traceback):self。process.stdin.write("-stay_open\nFalse\n")self.process.stdin.flush()deexecute(self,*args):args=args+("-execute\n",)self。process.stdin.write(str.join("\n",args))self.process.stdin.flush()output=""fd=self.process.stdout.fileno()whilenotoutput.endswith(self.sentinel):#output+=os.read(fd,4096).decode('utf-8',errors=)output+=os.read(fd,4096).decode('utf-8',"忽略")returnoutput[:-len(self.sentinel)]defget_metadata(self,*filenames):"""返回多个文件的exif信息"""returnjson.loads(self.execute("-G","-j","-n",*filenames))defget_exif_info(self,source_img):"""返回单个文件的exif信息"""returnsself.get_metadata(source_img)[0]defdelete_exif_info(self,source_img):'''删除exif信息后,返回剩余的exif信息'''self.execute("-all=",source_img)metadata=self.get_metadata(source_img)returnmetadata[0]使用前确保操作系统已经安装exiftool,程序读取默认两个位置:/usr/bin/exiftool/usr/local/bin/exiftool也可以传入exiftool的执行路径用法示例:frompprintimportpprintif__name__=='__main__':withExifTool()ase:exif=e.get_exif_info('/Users/aaron/Documents/personal/origin/file1.jpg')pprint(exif)exif=e.delete_exif_info('/users/aaron/Documents/personal/origin/file1.jpg')print("========删除exif信息后========")pprint(exif)可以用piexif对比一下用我这里提供的exif_t??ool看哪个删除的更彻底。如果您有任何问题,请留言讨论。4.长图拼接的思路也很简单。将要拼接的图片放在数组中,然后计算图片的最大宽度作为拼接图片的宽度,然后一张一张拼接。排版可以选择左对齐,或者水平居中对齐,空白位置的颜色也可以自己定义。具体代码如下:5.如何识别图片上的文字这个其实就是OCR,非常实用,但是个人很难训练出一个优秀的模型,所以还是直接用某某的API比较好大厂家。比如百度云的AI产品,你可以在终端下执行这样的命令来安装。pipinstallbaidu-aip这里我使用的是百度云提供的在线文字识别产品,它提供了AipOcr函数用于用户认证,client.basicGeneral函数用于文字识别。代码如下:fromaipimportAipOcr"""你的APPIDAKSK"""APP_ID='你的AppID'API_KEY='你的ApiKey'SECRET_KEY='你的SecretKey'client=AipOcr(APP_ID,API_KEY,SECRET_KEY)"""读取图片"""defget_file_content(filePath):withopen(filePath,'rb')asfp:returnfp.read()image=get_file_content('example.png')"""调用通用文字识别,image参数为本地图片"""result=client.basicGeneral(image)print(result)在这段代码中,实现了三个功能,分别是用户验证、图片读取和图片识别。为了更直观的看到效果,我这里给书拍个图,让它识别一下:原图如下:识别结果如下:6.给图片加水印,加自己的水印可以防止别人盗图,还可以宣传品牌形象,如果要给大量图片加文字水印,不妨使用以下方法。fromPILimportImage,ImageDraw,ImageFontdefadd_text_watermark(img,text):img=Image.open(img)draw=ImageDraw.Draw(img)myfont=ImageFont.truetype('/System/Library/Fonts/PingFang.ttc',size=100)fillcolor="#ff0000"width,height=img.sizeddraw.text((width-700,height-250),text,font=myfont,fill=fillcolor)returnimgif__name__=='__main__':image='/Users/aaron/Documents/personal/IMG_2288.compressed.jpg'img1=add_text_watermark(image,'@Python7')img1.save("result_text_watermark.jpg","jpeg")Descriptiondraw.text((宽度-700,高度-250),'@Python7',font=myfont,fill=fillcolor)第一个括号填入位置,左上角坐标为(0,0),右下角坐标为(width,heigth).在例子中(width-700,height-250)相当于右下角。效果如下(红色部分是程序添加的):那你可能又会问了,给图片加水印怎么办?比如现在有一个logo要添加到图片中,代码如下:fromPILimportImagedefadd_img_watermark(img,img_watermark):rgba_image=Image.open(img).convert("RGBA")rgba_watermark=Image.open(img_watermark).convert("RGBA")image_x,image_y=rgba_image.sizewatermark_x,watermark_y=rgba_watermark.size#缩放图像scale=10watermark_scale=max(image_x/(scale*watermark_x),image_y/(scale*watermark_y))new_size=(int(watermark_x*watermark_scale),int(watermark_y*watermark_scale))rgba_watermark=rgba_watermark.resize(new_size,resample=Image.ANTIALIAS)#Transparencyrgba_watermark_mask=rgba_watermark.convert("L").point(lambdax:min(x,180))rgba_watermark.putalpha(rgba_watermark_mask)watermark_x,watermark_y=rgba_watermark.size#水印位置rgba_image.paste(rgba_watermark,((image_x-watermark_x)//2,image_y-watermark_y-100),rgba_watermark_mask)#右上角returnrgba_image.convert("RGB")if__name__=='__main__':image='/Users/aaron/Documents/personal/IMG_2288.compressed.jpg'img_watermark="/Users/aaron/Downloads/IMG_2568.JPG"img2=add_img_watermark(image,img_watermark)img2.save("result_img_watermark.jpg")效果如下图所示:最终图??片就是我们触摸的媒体文件最多。下面是图片上的6种实用操作,大家可以直接复制这里的代码使用
