首頁>美文>

前言

當走上街頭時能隱約察覺到多了些許“紅白綠”的色彩,那是:聖誕老人、雪花❄️、聖誕樹。彌紅燈閃爍,各類促銷活動海報令郎滿目。沒有錯,聖誕節快來了~

從寫部落格開始,一路上得到了不少小夥伴的支援和鼓勵,而這周的總排名不偏不倚,恰好100名整。我想,這大概是某種巧合,更確切來說應該是一種激勵。近些日,嚴酷寒冬似乎柔情了許多,有了那麼幾日的柔柔暖陽,而我希望可以把這份溫暖也帶給大家。

我將用粉絲的頭像拼接出一幅聖誕樹,正所謂,“千圖成像,集萬千之美”。

原文地址:千圖成像!祝可愛的小夥伴們聖誕快樂_kimol君的部落格-CSDN部落格

一、聖誕樹

圖片上傳失敗

重試

該圖的畫素為6200x10250,將其區域性放大後的效果為:

今天所用到的程式碼是比較通用的,只需要替換背景圖和圖片庫即可打造屬於你自己的專屬圖片。詳情分析,客觀您往下瞅瞅~

帥小夥!聖誕來襲,還不趕快用來表白一波,還在猶豫啥呢?

二、程式碼分析1.頭像爬取

透過爬蟲將粉絲的頭像下載到本地,具體分析大家可以參考我之前的部落格【前方高能!看小夥是怎麼表白粉絲的】,完整程式碼如下:

# -*- coding: utf-8 -*-"""Created on Sat Oct 17 12:27:33 2020@author: kimol_love"""import requestsdef get_fansInfo():    '''    獲取粉絲相關資訊    '''    url = 'https://me.csdn.net/api/relation/index?pageno=%d&pagesize=%d&relation_type=fans' # 介面地址    cookies = {} # CSDN登陸後的cookies    headers = {  # 請求頭        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0',        'Accept': 'application/json, text/plain, */*',        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',        'Referer': 'https://i.csdn.net/',        'Origin': 'https://i.csdn.net',        'Connection': 'keep-alive',        'TE': 'Trailers',    }    # 獲取粉絲總數    res = requests.get(url%(1,10),headers=headers,cookies=cookies)    res_json = res.json()    N_fans = res_json['data']['data_all']    print('一共有%d個粉絲'%N_fans)    # 獲取全部粉絲資料    res = requests.get(url%(1,N_fans),headers=headers,cookies=cookies)    res_json = res.json()    return res_jsondef download_avatar(username,url):    '''    下載使用者頭像    '''    savePath = './avatars' # 頭像儲存目錄    res = requests.get(url)    with open('%s/%s.jpg'%(savePath,username),'wb') as f:        f.write(res.content)     if __name__ == '__main__':    fans = get_fansInfo()    for f in fans['data']['list']:        username = f['fans'] # 使用者名稱        url = f['avatar']    # 頭像地址        download_avatar(username,url)        print('使用者"%s"頭像下載完成!'%username)

將頭像下載完畢並去重,結果如下:

一共有2796張非重複圖片,有了它們,我們便可以開始——搞事情!

2.千圖成像

所謂千圖成像就是用很多張圖片拼接成一張完整的圖片,它需要兩個部分:一張背景圖,一個圖片庫。根據背景圖的結構用圖片庫中的圖片來進行拼接,最終形成新的圖片。

一種最簡單直觀的思路便是:遍歷背景圖中的每個畫素點,並用相簿中與之顏色最相近的圖片貼上在這個位置。

因此,我們首先需要計算每個圖片的“平均顏色”,即圖片畫素點(R,G,B)的平均值,程式碼如下:

def compute_mean(imgPath):    '''    計算平均(R,G,B)    '''    img = Image.open(imgPath)    img = img.convert('RGB')    imgArray = np.array(img)    R = np.mean(imgArray[:,:,0])    G = np.mean(imgArray[:,:,1])    B = np.mean(imgArray[:,:,2])    return (R,G,B)

遍歷圖片庫中的每張圖片,並得到它們的平均距離,生成一個圖片列表,以便後續的使用:

def get_imgList(imgDir):    '''    獲取圖片列表(圖片目錄及平均顏色)    '''    imgList = []    for imgName in os.listdir(imgDir):        path = imgDir+imgName        color = compute_mean(path)        imgList.append({'path':path,'RGB':color})    return imgList

該列表的每個元素是一個字典,包括了path和RGB,分別表示圖片的路徑以及圖片的平均顏色,如下:

在得到了圖片的“平均顏色”後,便是比較背景圖的畫素點與它的相似性,這裡採用了歐式距離:

def compute_distance(color1, color2):    '''    計算兩張圖的顏色差    '''    dis = 0    for i in range(len(color1)):        dis += (color1[i]-color2[i])**2    dis = dis**0.5    return dis

剩下的便是遍歷背景圖,並進行比較填充,程式碼如下:

def create_image(bgImg,imgDir,N=10,M=50):    '''    根據背景圖,用頭像填充出新圖    bgImg:背景圖地址    imgDir:頭像目錄    N:背景圖縮放的倍率    M:頭像的大小(MxM)    '''    # 獲取圖片列表    imgList = get_imgList(imgDir)        # 讀取背景圖    bg = Image.open(bgImg)    bg = bg.resize((bg.size[0]//N,bg.size[1]//N)) # 縮放    bgArray = np.array(bg)    width = bg.size[0]*M  # 新生成圖片的寬度    height = bg.size[1]*M # 新生成圖片的高度        # 建立空白的新圖    newImg = Image.new('RGB',(width,height))        # 迴圈填充圖    for x in range(bgArray.shape[0]):        for y in range(bgArray.shape[1]):            ## 找到距離最小的圖片            minDis = 10000            index = 0            for img in imgList:                dis = compute_distance(img['RGB'],bgArray[x][y])                if dis < minDis:                    index = img['path']                    minDis = dis            ## 填充            tempImg = Image.open(index)            tempImg = tempImg.resize((M,M))            newImg.paste(tempImg,(y*M,x*M))            print('(%d, %d)'%(x,y))                # 儲存圖片    newImg.save('千圖成像.jpg')

呼叫它:

create_image('bg.jpg','./avatars(dr)/',5,50)

函式的輸入有bgImg、imgDir、N、M,它們分別表示:

引數

含義

注:imgDir最後需要有目錄連線符/,否則會報錯;N是為了將背景圖的尺寸進行調整壓縮,否則容易因為畫素點太多而執行緩慢。

最後,程式碼一Run,小圖在手,簡單的快樂,美滋滋~

寫在最後

由於kimol君太想趕在聖誕前將這份禮物送出,所以程式碼以及文字略顯倉促,還望大家見諒。

客觀來說,該程式碼的執行效率並不高,特別是當N設定得較小(即背景圖片畫素點很多)或者圖片庫中的圖片很多時。針對這個問題,也有很多最佳化方法,例如採用圖片向量的方式對圖片進行編碼,進而比較等等。感興趣的小夥伴可以參考這篇文章。

最後,提前祝最可愛的小夥伴們聖誕快樂,願我們聚於一圖,煥盡萬丈芒!另祝即將奔赴考研戰場的小夥伴考的都會,會的都考!

我是kimol君,咋們下次再會~

6
最新評論
  • 於德慶:做人不要太張揚〈雜文)
  • 2020年底了,這10條掏心掏肺的話請記住,句句有用