銆怭ython杩樿兘骞插槢銆戠埇鍙栧井淇″ソ鍙嬪ご鍍忓畬鎴愰┈璧涘厠鎷煎浘锛堝崈鍥炬垚鍍忥級锝�

椹禌鍏嬫嫾鍥�

浣曡皳椹禌鍏嬫嫾鍥撅紙鍗冨浘鎴愬儚锛夛紝绠�鍗曟潵璇村氨鏄皢鑻ュ共灏忓浘鐗囧钩鍑戞垚涓轰竴寮犲ぇ鍥撅紝濡備笅鍥捐矾椋炰竴鏍凤紝濡傛灉鏀惧ぇ鐪嬩綘浼氬彂鐜伴噷闈㈤兘鏄竴浜涙捣璐肩帇閲岄潰鐨勫浘鐗囥��

Our Tragets

  • 鐖彇鎵�鏈夊井淇″ソ鍙嬬殑澶村儚馃暫馃徎馃暫馃徎馃暫馃徎
  • 灏嗘墍鏈夊井淇″ソ鍙嬪ご鍍忔嫾鍑戞垚涓�寮犲浘鐗囸煆欚煆欚煆�
  • 鐒跺悗灏卞彲浠ュ幓鏈嬪弸鍦堟剦蹇殑瑁呴�间簡馃お馃お馃お

Requirements

鍏跺疄鏁翠釜椤圭洰寰堝皬锛岄」鐩�诲叡浠g爜閲忎笉杩�100琛屽乏鍙炽��

  • 鐖彇寰俊澶村儚渚濊禆绗笁鏂瑰簱itchat锛�
  • 椹禌鍏嬫嫾鍥句緷璧栦緷璧�numpy鍜�PIL搴撱��

Content

鐖彇寰俊濂藉弸澶村儚

鎴戣繖杈规槸鐢ㄧ殑鎵�鏈夊井淇″ソ鍙嬪ご鍍忎綔涓虹殑鏁版嵁婧愶紝浣犱滑濡傛灉鏈夊叾浠栫殑鏁版嵁婧愪篃鍙互鐨勶紝鍙互鐩存帴璺宠繃杩欐銆�
鐖彇寰俊濂藉弸澶村儚鎴戜娇鐢ㄧ殑鏄�itchat锛岄噷闈㈠凡缁忔湁灏佽濂戒簡鐨凙PI锛岀洿鎺ヨ皟鐢ㄥ氨鍙互锛屽皢鎵�鏈夌殑濂藉弸澶村儚淇濆瓨鍒颁竴涓枃浠跺す渚涘悗鏈熶娇鐢ㄣ��

  • 浠g爜閮ㄥ垎
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : AwesomeTang
# @File    : Wechat_Icon.py
# @Version : Python 3.7
# @Time    : 2019-06-29 23:35

import os
import itchat

itchat.login()

friends = itchat.get_friends(update=True)

base_folder = 'wechat'
if os.path.isdir(base_folder):
    pass
else:
    os.mkdir(base_folder)

for item in friends:
    img = itchat.get_head_img(item['UserName'])

    # 浣跨敤鐢ㄦ埛鏄电О浣滀负鏂囦欢鍚�
    path = os.path.join(base_folder, '{}.jpg'.format(item['NickName'].replace('/', '')))
    with open(path, 'wb') as f:
        f.write(img)
    print('{} 鍐欏叆瀹屾垚...'.format(item['NickName']))
  • 瀹炵幇鏁堟灉
    銆怭ython杩樿兘骞插槢銆戠埇鍙栧井淇″ソ鍙嬪ご鍍忓畬鎴愰┈璧涘厠鎷煎浘锛堝崈鍥炬垚鍍忥級锝�_第1张图片

椹禌鍏嬫嫾鍥�

鎬濊矾姊崇悊
  1. 閫夊ソ浣犻渶瑕佹嫾鍑戠殑鍥剧墖锛屽皢鍏跺垏鍓蹭负鑻ュ共灏忓潡锛屽垏鍓茬殑瓒婄粏鐢熸垚鐨勫浘鐗囨晥鏋滀細鏇村ソ銆�
    gay閲実ay姘旂殑绀烘剰鍥撅細
    銆怭ython杩樿兘骞插槢銆戠埇鍙栧井淇″ソ鍙嬪ご鍍忓畬鎴愰┈璧涘厠鎷煎浘锛堝崈鍥炬垚鍍忥級锝�_第2张图片
  2. 鍒嗗埆鍘绘垜浠箣鍓嶄繚瀛樼殑鍥剧墖涓壘涓庝笌涔嬫渶鐩镐技鐨勶紝鏈�鍚庡皢鍏舵嫾鎺ュ畬鎴愩��

璇磋捣鏉ュソ鍍忓緢绠�鍗曪紝浣嗗疄闄呮搷浣滆捣鏉ュ彧鑳�......
銆怭ython杩樿兘骞插槢銆戠埇鍙栧井淇″ソ鍙嬪ご鍍忓畬鎴愰┈璧涘厠鎷煎浘锛堝崈鍥炬垚鍍忥級锝�_第3张图片

鏈�鐩镐技鐨勫浘鐗�

鍏跺疄鍥伴毦鐨勫湴鏂瑰緢鏄庢樉锛岄偅灏辨槸鎴戜滑濡備綍浠庝竴鍫嗗浘鐗囦腑鎵惧嚭鏈�鐩镐技鐨勯偅寮犮��
鎴戜滑鍙互鍒嗕负涓や釜姝ラ锛�

棰滆壊鐩镐技

杩欎釜搴旇涓嶉毦鐞嗚В锛屾垜鍦ㄤ唬鐮佷腑瀹炵幇浜嗙伆搴﹀浘鍍忓拰RGB閫氶亾鍥惧儚鐨勭瓫閫夋柟娉曪細

  • 鐏板害鍥惧儚锛�
    鐩存帴璁$畻鎵�鏈夊儚绱犵伆搴﹀�肩殑骞冲潎鍊硷紝鍙栨渶鎺ヨ繎n涓浘鍍忎緵鍚庢湡鍐嶆绛涢�夛紱
  • RGB閫氶亾锛�
    鍒嗗埆璁$畻R,G,B鐨勫钩鍧囧�硷紝瀵逛簬涓�涓浘鍍忔垜浠緱鍒扮殑鏄竴涓被浼间笌[20, 30,40]鐨勬暟缁勶紝鐒跺悗鎴戜滑璁$畻娆у紡璺濈锛屽彇鏈�鎺ヨ繎n涓浘鍍忎緵鍚庢湡鍐嶆绛涢�夈��
缁撴瀯鐩镐技

涓轰粈涔堣繕闇�瑕佺粨鏋勭浉浼硷紝涓句釜渚嬪瓙锛�
銆怭ython杩樿兘骞插槢銆戠埇鍙栧井淇″ソ鍙嬪ご鍍忓畬鎴愰┈璧涘厠鎷煎浘锛堝崈鍥炬垚鍍忥級锝�_第4张图片
濡傛灉鍗曠函鎸夌収涓婅堪鏂规硶鍘诲垽瀹氱浉浼硷紝閭d笂鍥句腑鐨勫浘A鍜屽浘B鑲畾鏄渶鐩镐技鐨勶紝鎵�浠ユ垜浠笉鑳藉崟绾殑鍥犱负涓ゅ紶鍥剧墖涓寘鍚殑棰滆壊宸笉澶氬氨鍘诲垽鏂负鏈�鐩镐技锛岃繕闇�瑕佸幓鍒ゆ柇棰滆壊鐨勨�滀綅缃�濅篃瑕佺浉浼笺��
杩欓儴鍒嗗疄鐜版柟娉曞弬鑰冧簡闃竴宄�鐨勫崥瀹紝鍏蜂綋閫昏緫濡備笅锛�

  1. 鍙渶瑕佹彁鍙栧浘鐗囩粨鏋勶紝棰滆壊鎰忎箟涓嶅ぇ锛屼负璁$畻绠�渚匡紝鎴戜滑鐩存帴灏嗘墍鏈夊浘鐗囪浆涓虹伆搴﹂�氶亾锛�
  2. 灏嗘瘡寮犲ご鍍弐esize涓猴紙8锛�8锛夛紝鐒跺悗璁$畻鎵�鏈夊儚绱犲�肩殑骞冲潎鍊笺��
  3. 鎴戜滑鎬诲叡鏈�64锛堝嵆$8*8$锛変釜鍍忕礌鐐癸紝鍒嗗埆鍘讳笌骞冲潎鍊兼瘮杈冨ぇ灏忥紝楂樹簬骞冲潎鍊肩殑璁颁负1锛屽皬浜庡钩鍧囧�肩殑璁颁负0锛岃繖鏍锋垜浠瘡寮犲浘鐗囬兘浼氬緱鍒颁竴涓暱搴︿负64绫讳技[0,1,1,0,1,0....0,1,1]鐨勨��缂栫爜鈥欍��
  4. 瀵逛簬鍒囧壊鐨勫皬鍥剧墖鎴戜滑涔熻繘琛屼笂杩版搷浣滐紝娉ㄦ剰瑕佷繚璇佹槸鍚屼竴椤哄簭锛堣濡備粠宸︿笂瑙掑埌鍙充笅瑙掞級锛岀劧鍚庡垎鍒幓涓庢瘡涓ご鍍忕殑鈥�缂栫爜鈥欒繘琛屾瘮杈冿紝杩欒竟鍦�闃竴宄�鐨勫崥瀹腑鏄噰鐢ㄧ殑璁$畻姹夋槑璺濈锛屾垜杩欒竟浣跨敤鐨勫氨鐩存帴閫氳繃np.equal()璁$畻鐩稿悓鐨勭偣浜嗭紝鍙栫浉鍚屼綅鏁版渶澶氱殑閭e紶澶村儚鍗充负鏈�鐩镐技鐨勫浘鐗囥��

鎴戝湪浠g爜涓槸鍏堢瓫閫夐鑹叉渶鎺ヨ繎鐨�50寮犲浘鐗囷紝鐒跺悗鍐嶅湪杩�50涓浘鐗囧幓瀵绘壘缁撴瀯鏈�鐩镐技鐨勫浘鐗囷紝鏈�鍚庡疄鐜版晥鏋滃涓嬶細

  • RGB閫氶亾
    鍥犱负鍥剧墖婧愬彧鏈�500鏉ュ紶锛屾晥鏋滃彧鑳借鍑戝悎锛屽媺寮鸿兘鐪嬪嚭鏉ユ槸鍟ャ��

  • 鐏板害
    銆怭ython杩樿兘骞插槢銆戠埇鍙栧井淇″ソ鍙嬪ご鍍忓畬鎴愰┈璧涘厠鎷煎浘锛堝崈鍥炬垚鍍忥級锝�_第5张图片

  • 鏀惧ぇ涔嬪悗鏄繖涓晥鏋滐細

鐒跺悗渚胯兘鍘绘湅鍙嬪湀鎰夊揩鐨勮閫间簡馃槑馃槑馃槑
銆怭ython杩樿兘骞插槢銆戠埇鍙栧井淇″ソ鍙嬪ご鍍忓畬鎴愰┈璧涘厠鎷煎浘锛堝崈鍥炬垚鍍忥級锝�_第6张图片

  • Talk is cheap, show me the code.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : AwesomeTang
# @Version : Python 3.7
# @Time    : 2019-06-23 13:52


from PIL import Image
import os
import numpy as np
from tqdm import tqdm


class Config:
    corp_size = 40
    filter_size = 20
    num = 100


class PicMerge:

    def __init__(self, pic_path, mode='RGB', pic_folder='wechat'):
        if mode.upper() not in ('RGB', 'L'):
            raise ValueError('Only accept "RGB" or "L" MODE, but we received "{}".'.format(self.mode))
        else:
            self.mode = mode.upper()
        print('Coding for every picture in folder "{}".'.format(pic_folder))
        self.mapping_table, self.pictures = self.mapping_table(pic_folder)
        self.picture = self.resize_pic(pic_path).convert(self.mode)

    @staticmethod
    def resize_pic(pic_path):
        picture = Image.open(pic_path)
        width, height = picture.size
        to_width = Config.corp_size * Config.num
        to_height = ((to_width / width) * height // Config.corp_size) * Config.corp_size
        picture = picture.resize((int(to_width), int(to_height)), Image.ANTIALIAS)
        return picture

    def merge(self):
        width, height = self.picture.size
        w_times, h_times = int(width / Config.corp_size), int(height / Config.corp_size)
        picture = np.array(self.picture)
        print('Corp & Merge...')
        for i in tqdm(range(w_times), desc='CORP'):
            for j in range(h_times):
                if self.mode == 'L':
                    section = picture[j * Config.corp_size:(j + 1) * Config.corp_size,
                                      i * Config.corp_size:(i + 1) * Config.corp_size]
                    section_mean = section.mean()
                    candidate = sorted([(key_, abs(np.array(value_).mean() - section_mean))
                                        for key_, value_ in self.pictures.items()],
                                       key=lambda item: item[1])[:Config.filter_size]
                    most_similar = self.structure_similarity(section, candidate)
                    picture[j * Config.corp_size:(j + 1) * Config.corp_size,
                            i * Config.corp_size:(i + 1) * Config.corp_size] = most_similar
                elif self.mode == 'RGB':
                    section = picture[j * Config.corp_size:(j + 1) * Config.corp_size,
                                      i * Config.corp_size:(i + 1) * Config.corp_size, :]
                    candidate = self.color_similarity(section)
                    most_similar = self.structure_similarity(section, candidate)
                    picture[j * Config.corp_size:(j + 1) * Config.corp_size,
                            i * Config.corp_size:(i + 1) * Config.corp_size, :] = most_similar

        picture = Image.fromarray(picture)
        picture.show()
        picture.save('result.jpg')
        print('Work Done...')

    def structure_similarity(self, section, candidate):
        section = Image.fromarray(section).convert('L')
        one_hot = self.pic_code(np.array(section.resize((8, 8), Image.ANTIALIAS)))
        candidate = [(key_, np.equal(one_hot, self.mapping_table[key_]).mean()) for key_, _ in candidate]
        most_similar = max(candidate, key=lambda item: item[1])
        return self.pictures[most_similar[0]]

    def color_similarity(self, pic_slice, top_n=Config.filter_size):
        slice_mean = self.rgb_mean(pic_slice)
        diff_list = [(key_, np.linalg.norm(slice_mean - self.rgb_mean(value_)))
                     for key_, value_ in self.pictures.items()]
        filter_ = sorted(diff_list, key=lambda item: item[1])[:top_n]
        return filter_

    @staticmethod
    def rgb_mean(rgb_pic):
        """
        if picture is RGB channel, calculate average [R, G, B].
        """
        r_mean = np.mean(rgb_pic[:, :, 0])
        g_mean = np.mean(rgb_pic[:, :, 1])
        b_mean = np.mean(rgb_pic[:, :, 2])
        val = np.array([r_mean, g_mean, b_mean])
        return val

    def mapping_table(self, pic_folder):
        """
        What this function do?
        1. transverse every image in PIC_FOLDER;
        2. resize every image in (8, 8) and covert into GREY;
        3. CODE for every image, CODE like [1, 0, 1, 1, 0....1]
        4. build a dict to gather all image and its CODE.
        :param pic_folder: path of pictures folder.
        :return: a dict
        """
        suffix = ['jpg', 'jpeg', 'JPG', 'JPEG', 'gif', 'GIF', 'png', 'PNG']
        if not os.path.isdir(pic_folder):
            raise OSError('Folder [{}] is not exist, please check.'.format(pic_folder))

        pic_list = os.listdir(pic_folder)
        results = {}
        pic_dic = {}
        for idx, pic in tqdm(enumerate(pic_list), desc='CODE'):
            if pic.split('.')[-1] in suffix:
                path = os.path.join(pic_folder, pic)
                try:
                    img = Image.open(path).resize((Config.corp_size, Config.corp_size), Image.ANTIALIAS)
                    results[idx] = self.pic_code(np.array(img.convert('L').resize((8, 8), Image.ANTIALIAS)))
                    if self.mode == 'RGB':
                        pic_dic[idx] = np.array(img.convert(self.mode))
                    else:
                        pic_dic[idx] = np.array(img.convert(self.mode))
                except OSError:
                    pass
        return results, pic_dic

    @staticmethod
    def pic_code(image: np.ndarray):
        """
        To make a one-hot code for IMAGE.
        AVG is mean of the array(IMAGE).
        Traverse every pixel of IMAGE, if the pixel value is more then AVG, make it 1, else 0.
        :param image: an array of picture
        :return: A sparse list with length [picture's width * picture's height].
        """
        width, height = image.shape
        avg = image.mean()
        one_hot = np.array([1 if image[i, j] > avg else 0 for i in range(width) for j in range(height)])
        return one_hot


if __name__ == "__main__":
    P = PicMerge(pic_path='娴疯醇鐜�.jpeg', mode='RGB')
    P.merge()

鍙傝�冭祫鏂�

  1. 鐩镐技鍥剧墖鎼滅储鐨勫師鐞� 锛�鐐规垜璺宠浆

skr~~ skr~~~

你可能感兴趣的:(銆怭ython杩樿兘骞插槢銆戠埇鍙栧井淇″ソ鍙嬪ご鍍忓畬鎴愰┈璧涘厠鎷煎浘锛堝崈鍥炬垚鍍忥級锝�)