<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    有趣的 Python 圖片制作,用 QQ 好友頭像拼接出里昂

    共 7934字,需瀏覽 16分鐘

     ·

    2021-03-16 12:22

    來(lái)blog.csdn.net/the_sangzi_home

    在本篇文章中,我們將實(shí)現(xiàn)兩個(gè)功能:

    • 將所有頭像合并為大圖

    • 將所有頭像以某個(gè)模板合成大圖

    同樣,先給上所有運(yùn)行效果圖:

    代碼實(shí)現(xiàn)

    1、代碼所需庫(kù)
    import requests,codecs,re,urllib,os,random,math
    from PIL import Image
    import numpy as np
    import cv2 as cv
    2、代碼講解

    2.1、將小頭像合并為大圖

    對(duì)于這個(gè),就是直接將每個(gè)小頭像貼在大圖上就行了,這個(gè)利用Image的paste函數(shù)就可以解決。對(duì)于貼的順序就可以直接按照下面圖示一個(gè)個(gè)貼:

    所以,直接給出代碼:


    def simple_split(filepackage,size,littlesize): #簡(jiǎn)單拼接,參數(shù)為圖片文件名,每行每列的size,小頭像圖片的大小
      row = size[0]
      col = size[1]
      bigimg = Image.new('RGBA',(littlesize*row,littlesize*col))  #結(jié)果圖
      number = 0
      for i in range(row):  #行
        for j in range(col):  #列
          randpic = random.randint(1,friends_count)
          img = Image.open(filepackage+str(randpic)+'.png').convert('RGBA')
          img = img.resize((littlesize,littlesize))
          loc = (i*littlesize,j*littlesize,(i+1)*littlesize,(j+1)*littlesize)
          print(loc,number)
          number+=1
          bigimg.paste(img,loc)
      bigimg.save(resultSavePath)

    由于好友不多,所以我們每次就隨機(jī)選擇一個(gè)好友頭像貼上去,所以如果你的密度大的話(huà)最后出現(xiàn)的頭像有很多重復(fù)的頭像。

    給大家展示下最后我的圖片吧:

    2.2、以某個(gè)圖片為模板拼接圖片

    由于不清楚有沒(méi)有能夠直接做出來(lái)的第三方庫(kù),所有我就自己造了個(gè)小輪子。

    思路:

    將模板分為A x B的小圖,就將它的位置形容為 pic[i][j] 吧,然后獲取每個(gè)小圖的平均RGB值,將 pic[i][j] 的平均RGB值和好友頭像的RGB值做對(duì)比,找出最接近的頭像,然后將該頭像插入在圖像的 pic[i][j] 處。

    思路還是比較簡(jiǎn)單吧??

    接下來(lái)就是實(shí)現(xiàn)了:代碼很多地方都給出了注釋?zhuān)揖筒欢嘀v了,直接給出代碼:

    import requests,codecs,re,urllib,os,random,math
    from PIL import Image
    import numpy as np
    import cv2 as cv

    txtpath = 'C:/Users/11037/Desktop/test/qqfriends.txt'  #你從QQ郵箱中粘貼的文件
    savepath = 'C:/Users/11037/Desktop/touxiang/'  #頭像存儲(chǔ)位置

    resultSavePath = 'C:/Users/11037/Desktop/result2.png'   #結(jié)果存儲(chǔ)位置
    modePath = 'C:/Users/11037/Desktop/leno.jpg'    #模板存儲(chǔ)位置

    friends_count = 0   #好友數(shù)量
    all_mean_rgbs = []   #存儲(chǔ)計(jì)算出的所有平均rgb值

    def meanrbg(img):  #計(jì)算圖片平均rgb
      rgb = np.array(img)
      r = int(round(np.mean(rgb[:, :, 0])))
      g = int(round(np.mean(rgb[:, :, 1])))
      b = int(round(np.mean(rgb[:, :, 2])))
      return (r,g,b)

    def gettouxiang(txtpath):#輸入你的txt文件存儲(chǔ)位置
      file = codecs.open(txtpath,'rb','utf-8')
      s = file.read()
      pattern = re.compile(r'\[email protected]')
      all_mail = pattern.findall(s)  #正則表達(dá)式匹配所有的qq號(hào)
      all_link = []  #用于存儲(chǔ)需要訪(fǎng)問(wèn)的鏈接
      url = 'http://qlogo.store.qq.com/qzone/'
      for mail in all_mail:
        qq = mail.replace('@qq.com','')
        l = url + qq +'/'+qq+'/100'
        all_link.append(l)
      i = 1
      for link in all_link:   #遍歷鏈接,下載頭像
        saveurl = savepath+str(i)+'.png'
        savaImg(link,saveurl)
        i +=1
        print('已下載',i)
      friends_count = len(all_link) #獲取朋友頭像數(shù)量
      return True

    def savaImg(picurl,saveurl):  #存儲(chǔ)圖片函數(shù),picurl是圖片的URL,saveurl是本地存儲(chǔ)位置
      try:
        bytes = urllib.request.urlopen(picurl)
        file = open(saveurl,'wb')
        file.write(bytes.read())
        file.flush()
        file.close()
        return True
      except:
        print('worry')
        savaImg(picurl,saveurl)


    def simple_split(filepackage,size,littlesize): #簡(jiǎn)單拼接,參數(shù)為圖片文件名,每行每列的size,小頭像圖片的大小
      row = size[0]
      col = size[1]
      bigimg = Image.new('RGBA',(littlesize*row,littlesize*col))
      number = 0
      for i in range(row):
        for j in range(col):
          randpic = random.randint(1,friends_count)
          img = Image.open(filepackage+str(randpic)+'.png').convert('RGBA')
          img = img.resize((littlesize,littlesize))
          loc = (i*littlesize,j*littlesize,(i+1)*littlesize,(j+1)*littlesize)
          print(loc,number)
          number+=1
          bigimg.paste(img,loc)
      bigimg.save(resultSavePath)


    def mode_split(filepackage,modepath,bigsize,littlesize):  #以模板存儲(chǔ)頭像
      row = bigsize[0#大圖每行多少個(gè)小頭像
      col = bigsize[1#每列
      suitSize = (littlesize*row,littlesize*col)  #大圖最終的像素size
      bigImg = Image.open(modepath)
      bigImg = bigImg.resize(suitSize)
      resultImg = Image.new('RGBA',suitSize) 

      for i in range(row):
        for j in range(col):
          cutbox = (i*littlesize,j*littlesize,(i+1)*littlesize,(j+1)*littlesize)  #模板剪切用于對(duì)比的某個(gè)區(qū)域
          cutImg = bigImg.crop(cutbox) #復(fù)制到cutImg中
          tmprgb = meanrbg(cutImg) 
          suitOne = mostSuitImg(tmprgb) + 1  #對(duì)比出最合適的頭像

          img = Image.open(filepackage + str(suitOne) + '.png').convert('RGBA')
          img = img.resize((littlesize,littlesize))
          resultImg.paste(img,cutbox)
          print('已粘貼',cutbox)
      resultImg.save(resultSavePath)  #存儲(chǔ)


    def mostSuitImg(tmprgb):  #進(jìn)行對(duì)比,找出最合適的頭像
      global all_mean_rgbs
      minRange = 200000
      id = 0
      for rgb in all_mean_rgbs:
        tmp = (rgb[1][0]-tmprgb[2])**2+(rgb[1][1]-tmprgb[1])**2+(rgb[1][2]-tmprgb[1])**2
        if tmp<minRange:
          minRange = tmp
          id = rgb[0]
      return id


    if __name__ == '__main__':
      # gettouxiang(txtpath)   #獲取頭像,如果已經(jīng)獲取就可以給注釋掉了
      # simple_split(savepath,(20,20),30)   #簡(jiǎn)單拼接
      
      #模板拼接
      for i in range(1,friends_count+1):
        img = cv.imread(savepath+str(i)+'.png')
        rgb = meanrbg(img)
        all_mean_rgbs.append(rgb)
      all_mean_rgbs = list(enumerate(all_mean_rgbs))  #給列表增加一個(gè)索引
      
      mode_split(savepath,modePath,(50,80),20)  #模板拼接

    給大家看看最終的效果:

    這樣一看還是都不錯(cuò)是吧。哈哈。

    再給出里昂的模板和最終成果:

    添加【修改后的Leon】:

    我默認(rèn)將每個(gè)頭像以數(shù)字命名,可以便于后續(xù)的操作。

    同時(shí),以上代碼都進(jìn)行了封裝,很多函數(shù)都可以獨(dú)立使用,用于滿(mǎn)足不同的功能。可以自己讀完代碼進(jìn)行改寫(xiě)實(shí)現(xiàn)自己需要的功能,比如說(shuō)以上我默認(rèn)頭像圖片都是正方形,你如果圖片有長(zhǎng)方形的改變下代碼也可以滿(mǎn)足。

    理論上來(lái)說(shuō),你的好友頭像越多,制作出來(lái)的圖片與模板的差異也就越小。以mode_split這個(gè)函數(shù)為例,你設(shè)置的bigsize越大,你的圖片也就越清晰。

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

    手機(jī)掃一掃分享

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

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    日韩视频久久 | 亚洲天堂免费 | 蜜乳一区二区三区四区 | 大鳮巴久久久久久久久 | 无码a√中文字幕 |