<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python自動(dòng)化辦公-玩轉(zhuǎn)圖片

          共 15432字,需瀏覽 31分鐘

           ·

          2021-07-10 12:29

          有很多非 IT 行業(yè)的朋友都在學(xué) Python,他們的目的也很簡(jiǎn)單,就是想提高下工作效率,簡(jiǎn)單重復(fù)的工作希望用 Python 搞定。

          因此我準(zhǔn)備寫一些 Python 自動(dòng)化辦公系列相關(guān)文章,代碼都是可以在 Python3 上正確運(yùn)行的,復(fù)制下代碼,再調(diào)整下細(xì)節(jié),就可以使用。

          首先發(fā)在公眾號(hào)上,然后同步到知識(shí)星球。

          為什么同步到知識(shí)星球,因?yàn)楣娞?hào)的文章修改起來(lái)非常麻煩,而知識(shí)星球就比較簡(jiǎn)單了,這樣文章里的代碼可以不停迭代更新,重要的是有問(wèn)題還可以一對(duì)一進(jìn)行提問(wèn)。入星球的方式后續(xù)會(huì)公布

          在日常的工作生活中,我們會(huì)經(jīng)常與圖片打交道,比如下載圖片,壓縮圖片,刪除圖片的元數(shù)據(jù)防止隱私泄漏,拼接長(zhǎng)圖,圖片文字識(shí)別,加水印等等。

          今天就來(lái)分享下如何簡(jiǎn)單的使用 Python 來(lái)玩轉(zhuǎn)這些操作。

          1、下載圖片

          下載圖片是最簡(jiǎn)單的操作了,無(wú)非就是先找到圖片的 url,使用標(biāo)準(zhǔn)庫(kù)或者 requests 庫(kù)去請(qǐng)求這個(gè) url,然后將得到的數(shù)據(jù)保存為文件即可。

          下面分享三種方法來(lái)下載圖片。

          方法一,使用標(biāo)準(zhǔn)庫(kù)。

          from urllib.request import urlretrieve
          from pathlib import Path
          import ssl
          def urllib_download(img_url, download_path):
              ssl._create_default_https_context = ssl._create_unverified_context
              urlretrieve(img_url, Path(download_path) / 'image1.png'

          方法二,使用 requests。


          import requests
          def request_download(img_url, download_path):
              r = requests.get(img_url)
              with open(f'{download_path}/image2.png''wb'as f:
                  f.write(r.content)

          方法二,使用 requests 的流式下載,適用于較大,網(wǎng)速慢,容易下載失敗的圖片。

          import requests
          def requests_chunk_download(img_url, download_path):
              r = requests.get(img_url, stream=True)    
              with open(f'{download_path}/image3.png''wb'as f:
                  for chunk in r.iter_content(chunk_size=32):
                      f.write(chunk)

          分別下載一個(gè)圖片看看結(jié)果:

          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())

          三種方法下載圖片的大小是一樣的。

          如果自動(dòng)下載某網(wǎng)站的全部圖片,其實(shí)一點(diǎn)也不復(fù)雜,無(wú)非就是找規(guī)律,如何獲取全部圖片的 url,然后循環(huán)調(diào)用以上三個(gè)函數(shù)。

          獲取圖片 url 可能會(huì)涉及正則表達(dá)式,關(guān)于正則表達(dá)式,可以參考前文學(xué)會(huì)正則表達(dá)式,玩弄文本于股掌之中

          2、壓縮圖片

          有一次我用郵箱向老板發(fā)送 5 張圖片時(shí),foxmail 提示我是否啟用 QQ 郵箱的超大附件功能,原來(lái) 5 張圖片已經(jīng) 40+ MB,現(xiàn)在的手機(jī)拍攝的真是太清晰了。

          不過(guò)工作中的圖片能看清楚內(nèi)容就可以了,完全沒(méi)有必要整那么清晰,文件太大,發(fā)給老板,老板打開圖片也會(huì)卡,體驗(yàn)非常不好,于是我就想如何使用 Python 來(lái)壓縮圖片。

          找了很多方法,都不是很理想,有的軟件下載后才發(fā)現(xiàn)是付費(fèi)的,有的在使用時(shí)直接導(dǎo)致程序卡死,有的壓縮率不夠需要多次壓縮,有的要求原始圖片大小不能超過(guò) 5 M 有的失真有些嚴(yán)重。

          直到我用了 tinypng 的 api 接口,才發(fā)現(xiàn)這真的好用,圖片幾乎不失真,大多都控制在 1 MB 之內(nèi),在此分享給大家。

          先打開 https://tinypng.com/developers, 在下方輸入你的用戶名和郵箱,就可以獲取一個(gè) API KEY。

          然后 pip 安裝一下這個(gè)庫(kù):

          pip install tinify

          編寫三行代碼就可以對(duì)圖片進(jìn)行壓縮處理了:

          import tinify
          tinify.key = '此處填入你的key'
          tinify.from_file(src_img_path).to_file(dst_img_path)

          其中 src_img_path 是原圖片,dst_img_path 是壓縮后的圖片。

          比如找個(gè)目錄,對(duì)文件批量壓縮一下:

          import tinify
          from pathlib import Path
          import os

          tinify.key = '此處填入你的key'
          path = "/Users/aaron/Documents/個(gè)人/origin" # 圖片存放的路徑

          for dirpath, dirs, files in os.walk(path):
              for file in files:
                  file = Path(dirpath)/Path(file)
                  if file.suffix.lower() in ['.jpg','.png','.gif']:
                      print("compressing ..."+ file.as_posix())
                      tinify.from_file(file.as_posix()).to_file(file.with_suffix(".compressed.jpg").as_posix())

          可以看到,壓縮后的文件大小在 1M 左右或 1M 之內(nèi),打開文件對(duì)比,基本看不出任何區(qū)別:


          3、刪除圖片的元數(shù)據(jù)

          現(xiàn)在大部分快遞已經(jīng)可以對(duì)地址信息進(jìn)行加密,大家的隱私保護(hù)意識(shí)也越來(lái)越高,可是一不小心,你隨手發(fā)布的照片就可能暴露了你的位置信息。

          因此,用戶發(fā)布照片時(shí)去除照片的位置、設(shè)備、時(shí)間等隱私信息顯得很有必要,這些信息又叫元數(shù)據(jù),也就是 metadata。

          Python 刪除圖片的元數(shù)據(jù)是有一個(gè)三方庫(kù) piexif,我使用它刪除后,再用 exiftool 查看時(shí),仍然可以查到許多隱私信息。

          也就是說(shuō) piexif 刪除的不夠徹底,于是我用 Python 封裝了 exiftool,這下,圖片的元數(shù)據(jù)可以刪除的干干凈凈。

          文件 exif_tool.py 代碼如下:

          import subprocess
          import os
          import json
          from pathlib import Path
          class ExifTool(object):

              sentinel = "{ready}\n"
              #windows
              #sentinel = "{ready}\r\n"

              def __init__(self, executable="/usr/bin/exiftool"):
                  exiftool1 = Path("/usr/bin/exiftool")
                  exiftool2 = Path("/usr/local/bin/exiftool")
                  self.executable = executable
                  if exiftool1.exists():
                      self.executable = exiftool1.as_posix()
                  elif exiftool2.exists():
                      self.executable = exiftool2.as_posix()
                  else:
                      if Path(self.executable).exists():
                          pass
                      else:
                          raise FileNotFoundError(self.executable)


              def __enter__(self):
                  self.process = subprocess.Popen(
                      [self.executable, "-stay_open""True",  "-@""-"],
                      universal_newlines=True,
                      stdin=subprocess.PIPE, stdout=subprocess.PIPE)
                  return self

              def __exit__(self, exc_type, exc_value, traceback):
                  self.process.stdin.write("-stay_open\nFalse\n")
                  self.process.stdin.flush()

              def execute(self, *args):
                  args = args + ("-execute\n",)
                  self.process.stdin.write(str.join("\n", args))
                  self.process.stdin.flush()
                  output = ""
                  fd = self.process.stdout.fileno()
                  while not output.endswith(self.sentinel):
                      # output += os.read(fd, 4096).decode('utf-8',errors=)
                      output += os.read(fd, 4096).decode('utf-8',"ignore")
                  return output[:-len(self.sentinel)]

              def get_metadata(self, *filenames):
                  """
                  返回多個(gè)文件的 exif 信息
                  """

                  return json.loads(self.execute("-G""-j""-n", *filenames))

              def get_exif_info(self, source_img):
                  """
                  返回單個(gè)文件的 exif 信息
                  """

                  return self.get_metadata(source_img)[0]

              def delete_exif_info(self, source_img):
                  '''
                  刪除 exif 信息后,返回剩余的 exif 信息
                  '''

                  self.execute("-all=",source_img)
                  metadata = self.get_metadata(source_img)
                  return metadata[0]

          使用前先確保操作系統(tǒng)已經(jīng)安裝了 exiftool,程序默認(rèn)讀取兩個(gè)位置:

          /usr/bin/exiftool
          /usr/local/bin/exiftool

          也可以自己傳入 exiftool 的執(zhí)行路徑。

          使用舉例:

          from pprint import pprint
          if __name__ == '__main__':
              with ExifTool() as e:
                  exif = e.get_exif_info('/Users/aaron/Documents/個(gè)人/origin/文件1.jpg')
                  pprint(exif)
                  exif = e.delete_exif_info('/Users/aaron/Documents/個(gè)人/origin/文件1.jpg')
                  print("========刪除 exif 信息后========")
                  pprint(exif)

          大家可以用 piexif 和我這里提供的 exif_tool 做個(gè)對(duì)比,看看哪個(gè)刪除的更徹底,有問(wèn)題請(qǐng)留言討論。

          4、拼接長(zhǎng)圖

          思路也簡(jiǎn)單,也把要拼接的圖片放在數(shù)組里面,然后計(jì)算圖片的最大寬度作為拼接后圖片的寬度,然后一張一張拼接即可。

          排版可以選擇靠左對(duì)齊,或者水平居中對(duì)齊,空白位置的顏色也可以自己定義。

          具體代碼如下:

          from pathlib import Path

          from PIL import Image

          if __name__ == '__main__':
              img_list = []
              imgs_path = Path('/Users/aaron/tmp/images')
              for img in imgs_path.iterdir():
                  if img.suffix.lower() in ['.jpg','.png']:
                      img_list.append(Image.open(img.as_posix()))

              width = 0
              height = 0
              for img in img_list:
                  # 單幅圖像尺寸
                  w, h = img.size
                  height += h
                  # 取最大的寬度作為拼接圖的寬度
                  width = max(width, w)

              # 創(chuàng)建空白長(zhǎng)圖,這里可以傳入 color 設(shè)置空白地方的顏色,默認(rèn)黑色
              result = Image.new(img_list[0].mode, (width, height))
              # 拼接圖片
              height = 0
              for img in reversed(img_list):
                  w, h = img.size
                  # 圖片水平居中
                  result.paste(img, box=(round(width / 2 - w / 2), height))
                  height += h
              # 保存圖片
              result.save('拼接長(zhǎng)圖.png')

          執(zhí)行后的效果如下所示:

          5、如何識(shí)別圖片上的文字

          這其實(shí)就是 OCR 了,非常實(shí)用,不過(guò)個(gè)人很難訓(xùn)練出優(yōu)秀的模型,不如直接用大廠的 API。舉個(gè)例子,百度云的 AI 產(chǎn)品,你可以在終端下執(zhí)行這樣一個(gè)命令來(lái)進(jìn)行安裝。

          pip install baidu-aip

          在這里我使用了百度云提供的在線文字識(shí)別產(chǎn)品,提供了 AipOcr 函數(shù)實(shí)現(xiàn)用戶驗(yàn)證、client.basicGeneral 函數(shù)實(shí)現(xiàn)文字識(shí)別功能。

          代碼如下:


          from aip import AipOcr
          """ 你的 APPID AK SK """
          APP_ID = '你的 App ID'
          API_KEY = '你的 Api Key'
          SECRET_KEY = '你的 Secret Key'
          client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
          """ 讀取圖片 """
          def get_file_content(filePath):
              with open(filePath, 'rb'as fp:
                  return fp.read()
          image = get_file_content('example.png')
          """ 調(diào)用通用文字識(shí)別, 圖片參數(shù)為本地圖片 """
          result = client.basicGeneral(image)
          print(result)

          在這段代碼里,實(shí)現(xiàn)了三個(gè)功能,分別是用戶驗(yàn)證、讀取圖片和識(shí)別圖片。

          為了更直觀地看到效果,我這里對(duì)著書拍個(gè)照片,然后讓它識(shí)別一下:

          原圖如下:

          識(shí)別結(jié)果如下:

          6、給圖片加水印

          添加自己的水印來(lái)防止別人盜圖,也可以宣傳品牌形象,如果要為大量圖片添加文字水印,不妨使用以下方法。

          from PIL import Image, ImageDraw, ImageFont

          def add_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.size
              draw.text((width - 700, height - 250), text, font=myfont, fill=fillcolor)
              return img


          if __name__ == '__main__':
              image = '/Users/aaron/Documents/個(gè)人/IMG_2288.compressed.jpg'
              img1 = add_text_watermark(image,'@Python七號(hào)')
              img1.save("result_text_watermark.jpg","jpeg")

          說(shuō)明 draw.text((width - 700, height - 250), '@Python七號(hào)', font=myfont, fill=fillcolor)第一個(gè)括號(hào)填寫的是位置,左上角的坐標(biāo)是 (0,0),右下角的坐標(biāo)是(width,heigth),本例中 (width - 700, height - 250) 相當(dāng)于是右下角。

          效果如下(紅色部分是程序添加的):

          那你可能又問(wèn)下,如果加圖片水印呢?比如現(xiàn)在有一個(gè) logo 想添加到圖片上,代碼如下:

          from PIL import Image
          def add_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.size
              watermark_x, watermark_y = rgba_watermark.size
              # 縮放圖片
              scale = 10
              watermark_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)
              # 透明度
              rgba_watermark_mask = rgba_watermark.convert("L").point(lambda x: 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)  # 右上角

              return rgba_image.convert("RGB")

          if __name__ == '__main__':
              image = '/Users/aaron/Documents/個(gè)人/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 種關(guān)于圖片的實(shí)用操作,需要的可以直接復(fù)制這里的代碼使用。

          如果想了解關(guān)于圖片的更多的實(shí)用操作,請(qǐng)留言,后續(xù)再發(fā)這方面的文章。

          留言

          瀏覽 62
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  伊人成人在线视频观看 | 小美女逃课去操比 | 亚洲精品suv视频 | 亚洲欧洲日本不卡视频在线观看 | 日本a天堂 |