30秒教會你用Python製作表白神器,讓你2019結束單身

轉眼2018即將結束,不知道各位有沒有都由單身dog進化為秀恩愛dog。

30秒教會你用Python製作表白神器,讓你2019結束單身

在我大三的時候,就有一個計算機的朋友用自己做的代碼感動了一個數學系的女生。就是下面這種。(這個愛心是有運行結果的!)也不知道為什麼妹子放棄了全班30多位帥哥(沒錯,他們班就她一個女生),而選擇了頭髮日漸稀疏已經“六月懷胎”的我朋友。

30秒教會你用Python製作表白神器,讓你2019結束單身

今天,我就來教大家一下,在2018最後結束之際如何用Python做一份特別的禮物送給自己的戀人。

30秒教會你用Python製作表白神器,讓你2019結束單身

當然了,如果還是單身的,也可以把這個作為表白神器,和心愛的人表白

會Python編程的人當然不用我說,就知道該如何操作,那些不懂編程的人,如果想嘗試,那該怎麼辦呢?

這裡我特地製作了小程序,你可以去與我頭條號同名的微信公眾號「胖福的小木屋」後臺私信“小程序”即可獲取。運行就可以了。

懂編程的就看下面的吧!送上這份禮物之後,保證你明晚.....巫山雲雨後,天氣晚來秋啊!

30秒教會你用Python製作表白神器,讓你2019結束單身

01

首先教大家一個初級版的。這個就比較簡單,利用Python製作一個愛心。

我先把代碼給貼出來:

import turtle

import time

# 畫愛心的頂部

def LittleHeart():

for i in range (200):

turtle.right(1)

turtle.forward(2)

# 輸入表白的語句,默認I Love you

love=input('Please enter a sentence of love, otherwise the default is "I Love you":\n')

#輸入署名或者贈誰,沒有不執行

me=input('Please enter pen name, otherwise the default do not execute:\n')

if love=='':

love='I Love you'

# 窗口大小

turtle.setup(width=900, height=500)

# 顏色

turtle.color('red','pink')

# 筆粗細

turtle.pensize(3)

# 速度

turtle.speed(1)

# 提筆

turtle.up()

# 隱藏筆

turtle.hideturtle()

# 去到的座標,窗口中心為0,0

turtle.goto(0,-180)

turtle.showturtle()

# 畫上線

turtle.down()

turtle.speed(1)

turtle.begin_fill()

turtle.left(140)

turtle.forward(224)

#調用畫愛心左邊的頂部

LittleHeart()

#調用畫愛右邊的頂部

turtle.left(120)

LittleHeart()

# 畫下線

turtle.forward(224)

turtle.end_fill()

turtle.pensize(5)

turtle.up()

turtle.hideturtle()

# 在心中寫字 一次

turtle.goto(0,0)

turtle.showturtle()

turtle.color('#CD5C5C','pink')

#在心中寫字 font可以設置字體自己電腦有的都可以設 align開始寫字的位置

turtle.write(love,font=('gungsuh',30,),align="center")

turtle.up()

turtle.hideturtle()

time.sleep(2)

# 在心中寫字 二次

turtle.goto(0,0)

turtle.showturtle()

turtle.color('red','pink')

turtle.write(love,font=('gungsuh',30,),align="center")

turtle.up()

turtle.hideturtle()

# 寫署名

if me !='':

turtle.color('black', 'pink')

time.sleep(2)

turtle.goto(180,-180)

turtle.showturtle()

turtle.write(me, font=(20,), align="center", move=True)

#點擊窗口關閉

window=turtle.Screen()

window.exitonclick()

這個代碼最終呈現效果如下,這個是比較初級簡單的愛心,沒有什麼高難度。你也可以把代碼擴充一下,整的更加高大上一些。

30秒教會你用Python製作表白神器,讓你2019結束單身

如果你覺得這個還不夠酷炫,那我好人做到底,幫你製作一個

表白愛心樹

import turtle

import random

def love(x, y): # 在(x,y)處畫愛心lalala

lv = turtle.Turtle()

lv.hideturtle()

lv.up()

lv.goto(x, y) # 定位到(x,y)

def curvemove(): # 畫圓弧

for i in range(20):

lv.right(10)

lv.forward(2)

lv.color('red', 'pink')

lv.speed(10000000)

lv.pensize(1)

# 開始畫愛心lalala

lv.down()

lv.begin_fill()

lv.left(140)

lv.forward(22)

curvemove()

lv.left(120)

curvemove()

lv.forward(22)

lv.write("WM", font=("Arial", 12, "normal"), align="center") # 寫上表白的人的名字

lv.left(140) # 畫完復位

lv.end_fill()

def tree(branchLen, t):

if branchLen > 5: # 剩餘樹枝太少要結束遞歸

if branchLen < 20: # 如果樹枝剩餘長度較短則變綠

t.color("green")

t.pensize(random.uniform((branchLen + 5) / 4 - 2, (branchLen + 6) / 4 + 5))

t.down()

t.forward(branchLen)

love(t.xcor(), t.ycor()) # 傳輸現在turtle的座標

t.up()

t.backward(branchLen)

t.color("brown")

return

t.pensize(random.uniform((branchLen + 5) / 4 - 2, (branchLen + 6) / 4 + 5))

t.down()

t.forward(branchLen)

# 以下遞歸

ang = random.uniform(15, 45)

t.right(ang)

tree(branchLen - random.uniform(12, 16), t) # 隨機決定減小長度

t.left(2 * ang)

tree(branchLen - random.uniform(12, 16), t) # 隨機決定減小長度

t.right(ang)

t.up()

t.backward(branchLen)

myWin = turtle.Screen()

t = turtle.Turtle()

t.hideturtle()

t.speed(1000)

t.left(90)

t.up()

t.backward(200)

t.down()

t.color("brown")

t.pensize(32)

t.forward(60)

tree(100, t)

myWin.exitonclick()

圖中的“WM”是可以改的!看到代碼裡的“WM”兩個字了沒?直接把這兩個字母替換成你心上人的名字就好。中文英文都可以。

30秒教會你用Python製作表白神器,讓你2019結束單身

30秒教會你用Python製作表白神器,讓你2019結束單身

02

除了上面這個,你還可以利用Python畫畫啊,製作一份獨一無二的畫作送給自己的心上人。

這個可和美圖濾鏡不一樣,可以利用深度學習copy世界任何名畫、甚至任何圖片,給你愛人制作一份獨一無二的畫像。

在這裡,我教你兩個畫畫的方式,各位瞧好了,看我大展身手。

30秒教會你用Python製作表白神器,讓你2019結束單身

先第一個:畫像重疊。

我們先選擇兩幅畫,你們也可以一幅選你們心上人的畫像,一幅選擇風景或者其他。這個時候就看各位的審美了。這裡我選擇的都是風景。

30秒教會你用Python製作表白神器,讓你2019結束單身

30秒教會你用Python製作表白神器,讓你2019結束單身

首先,第一步:

print('---Please put the picture in this file-----0<percent>

img1_addres=input("Please enter the first picture's name plus the file suffix:\n")

img2_address=input("Please enter the name of the second picture plus the file suffix:\n")

percent1=input('Please enter the first picture to display the weight, the default is 0.5:\n')

percent2=input('Please enter the second picture to show the proportion, the default is 0.5:\n')

merge2(img1_addres,img2_address,percent1,percent2)

/<percent>

然後自行設置顯示比,如果沒有輸入,就會按照默認設置進行:

# 如果兩張圖片中有一張沒有輸入顯示比,默認設置為0.5

if percent1=='' or percent2=='':

percent1 = 0.50

percent2 = 0.50

獲取圖片地址:

# 獲取圖片的地址

img1=Image.open(img1_address)

img2=Image.open(img2_address)

然後再第三步:

# 讓兩張圖片的顯示比相加等於1

if percent1+percent2!=1:

percent2=1-percent1

再獲取圖片寬高:

# 獲取圖片的最小寬高

width = min(img1.size[0],img2.size[0])

height = min(img1.size[1],img2.size[1])

img_new = Image.new('RGB',(width,height))

# 渲染圖片

for x in range(width):

for y in range(height):

r1,g1,b1=img1.getpixel((x,y))

r2,g2,b2=img2.getpixel((x,y))

r=int(percent1*r1+percent2*r2)

g=int(percent1*g1+percent2*g2)

b=int(percent1*b1+percent2*b2)

img_new.putpixel((x,y),(r,g,b))

最後保存就好了!

# 保存圖片

img_new.save('new.jpg')

大家可以看一下渲染效果:

30秒教會你用Python製作表白神器,讓你2019結束單身

是不是特別好看,有世界名畫的感覺。特別有莫奈的印象畫風格。你可以利用這個代碼給你心上人做一幅特別而好看的畫像。這個我也是幫各位做好了小程序

第二個是圖像渲染:

通過Python的深度學習算法包去訓練計算機模仿世界名畫的風格,然後應用到另一幅畫中!

這個就沒有小程序了。因為這個有幾百個依賴包。

專業難度比較高一些,首先,需要安裝使用的模塊,pip一鍵搞定:

pip3 install keras

pip3 install h5py

pip3 install tensorflow

TensorFlow的安裝可能不翻牆的話下載的比較慢,也可以源碼安裝。自己把握。(TensorFlow只能python3.5安裝,所以先下載一個3.5版本的)

然後再下載VGG16模型。把代碼生成py格式和需要渲染圖片放在同一個文件夾。

30秒教會你用Python製作表白神器,讓你2019結束單身

這個是世界名畫蒙娜麗莎,以這張圖片為模板,讓計算機去學習這張圖片的風格應用到自己的這張圖片上。

30秒教會你用Python製作表白神器,讓你2019結束單身

我先把代碼貼出來(這個代碼是根據知乎大佬:楊航鋒的代碼修改而成):

from __future__ import print_function

from keras.preprocessing.image import load_img, img_to_array

from scipy.misc import imsave

import numpy as np

import time

import argparse

from keras.applications import vgg16

from keras import backend as K

from scipy.optimize.lbfgsb import fmin_l_bfgs_b

parser = argparse.ArgumentParser(description='Neural style transfer with Keras.')

parser.add_argument('base_image_path', metavar='base', type=str,help='Path to the image to transform.')

parser.add_argument('style_reference_image_path', metavar='ref', type=str, help='Path to the style reference image.')

parser.add_argument('result_prefix', metavar='res_prefix', type=str,help='Prefix for the saved results.')

parser.add_argument('--iter', type=int, default=15, required=False,help='Number of iterations to run.')

parser.add_argument('--content_weight', type=float, default=0.025, required=False,help='Content weight.')

parser.add_argument('--style_weight', type=float, default=1.0, required=False,help='Style weight.')

parser.add_argument('--tv_weight', type=float, default=1.0, required=False,help='Total Variation weight.')

args = parser.parse_args()

base_image_path = args.base_image_path

style_reference_image_path = args.style_reference_image_path

result_prefix = args.result_prefix

iterations = args.iter

# 不同損失分量的權重

total_variation_weight = args.tv_weight

style_weight = args.style_weight

content_weight = args.content_weight

# 生成圖片的尺寸

width, height = load_img(base_image_path).size

img_nrows = 400

img_ncols = int(width * img_nrows / height)

# util function to open, 調整和格式化圖片到適當的張量

def preprocess_image(image_path):

img = load_img(image_path, target_size=(img_nrows, img_ncols))

img = img_to_array(img)

img = np.expand_dims(img, axis=0)

img = vgg16.preprocess_input(img)

return img

# util函數將一個張量轉換成一個有效的圖像

def deprocess_image(x):

if K.image_data_format() == 'channels_first':

x = x.reshape((3, img_nrows, img_ncols))

x = x.transpose((1, 2, 0))

else:

x = x.reshape((img_nrows, img_ncols, 3))

# Remove zero-center by mean pixel

# 用平均像素去除零中心

x[:, :, 0] += 103.939

x[:, :, 1] += 116.779

x[:, :, 2] += 123.68

# 'BGR'->'RGB' 轉換

x = x[:, :, ::-1]

x = np.clip(x, 0, 255).astype('uint8')

return x

# get tensor representations of our images

# 得到圖像的張量表示

base_image = K.variable(preprocess_image(base_image_path))

style_reference_image = K.variable(preprocess_image(style_reference_image_path))

# this will contain our generated image

# 包含我們生成的圖片

if K.image_data_format() == 'channels_first':

combination_image = K.placeholder((1, 3, img_nrows, img_ncols))

else:

combination_image = K.placeholder((1, img_nrows, img_ncols, 3))

# combine the 3 images into a single Keras tensor

# 將3個圖像合併成一個Keras張量

input_tensor = K.concatenate([base_image,

style_reference_image,

combination_image], axis=0)

# build the VGG16 network with our 3 images as input

# the model will be loaded with pre-trained ImageNet weights

# 以我們的3個圖像作為輸入構建VGG16網絡

# 該模型將加載預先訓練的ImageNet權重

model = vgg16.VGG16(input_tensor=input_tensor,

weights='imagenet', include_top=False)

print('Model loaded.')

# get the symbolic outputs of each "key" layer (we gave them unique names).

# 獲取每個“鍵”層的符號輸出(我們給它們取了唯一的名稱)

outputs_dict = dict([(layer.name, layer.output) for layer in model.layers])

# compute the neural style loss

# 計算神經類型的損失

# first we need to define 4 util functions

# 首先我們需要定義是個until函數

# the gram matrix of an image tensor (feature-wise outer product)

# 圖像張量的克矩陣

def gram_matrix(x):

assert K.ndim(x) == 3

if K.image_data_format() == 'channels_first':

features = K.batch_flatten(x)

else:

features = K.batch_flatten(K.permute_dimensions(x, (2, 0, 1)))

gram = K.dot(features, K.transpose(features))

return gram

# the "style loss" is designed to maintain

# 風格損失”是為了維護而設計的

# the style of the reference image in the generated image.

# 生成圖像中引用圖像的樣式

# It is based on the gram matrices (which capture style) of feature maps from the style reference image and from the generated image

# 它基於從樣式引用圖像和生成的圖像中獲取特徵映射的gram矩陣(捕獲樣式)

def style_loss(style, combination):

assert K.ndim(style) == 3

assert K.ndim(combination) == 3

S = gram_matrix(style)

C = gram_matrix(combination)

channels = 3

size = img_nrows * img_ncols

return K.sum(K.square(S - C)) / (4. * (channels ** 2) * (size ** 2))

# an auxiliary loss function

# 一個輔助的損失函數

# designed to maintain the "content" of the base image in the generated image

#設計用於維護生成圖像中基本圖像的“內容

def content_loss(base, combination):

return K.sum(K.square(combination - base))

# the 3rd loss function, total variation loss,designed to keep the generated image locally coherent

# 第三個損失函數,總變異損失,設計來保持生成的圖像局部一致

def total_variation_loss(x):

assert K.ndim(x) == 4

if K.image_data_format() == 'channels_first':

a = K.square(x[:, :, :img_nrows - 1, :img_ncols - 1] - x[:, :, 1:, :img_ncols - 1])

b = K.square(x[:, :, :img_nrows - 1, :img_ncols - 1] - x[:, :, :img_nrows - 1, 1:])

else:

a = K.square(x[:, :img_nrows - 1, :img_ncols - 1, :] - x[:, 1:, :img_ncols - 1, :])

b = K.square(x[:, :img_nrows - 1, :img_ncols - 1, :] - x[:, :img_nrows - 1, 1:, :])

return K.sum(K.pow(a + b, 1.25))

# combine these loss functions into a single scalar

# 將這些損失函數合併成一個標量。

loss = K.variable(0.)

layer_features = outputs_dict['block4_conv2']

base_image_features = layer_features[0, :, :, :]

combination_features = layer_features[2, :, :, :]

loss += content_weight * content_loss(base_image_features,

combination_features)

feature_layers = ['block1_conv1', 'block2_conv1',

'block3_conv1', 'block4_conv1',

'block5_conv1']

for layer_name in feature_layers:

layer_features = outputs_dict[layer_name]

style_reference_features = layer_features[1, :, :, :]

combination_features = layer_features[2, :, :, :]

sl = style_loss(style_reference_features, combination_features)

loss += (style_weight / len(feature_layers)) * sl

loss += total_variation_weight * total_variation_loss(combination_image)

# get the gradients of the generated image wrt the loss

# 得到所生成圖像的梯度,並對損失進行wrt。

grads = K.gradients(loss, combination_image)

outputs = [loss]

if isinstance(grads, (list, tuple)):

outputs += grads

else:

outputs.append(grads)

f_outputs = K.function([combination_image], outputs)

def eval_loss_and_grads(x):

if K.image_data_format() == 'channels_first':

x = x.reshape((1, 3, img_nrows, img_ncols))

else:

x = x.reshape((1, img_nrows, img_ncols, 3))

outs = f_outputs([x])

loss_value = outs[0]

if len(outs[1:]) == 1:

grad_values = outs[1].flatten().astype('float64')

else:

grad_values = np.array(outs[1:]).flatten().astype('float64')

return loss_value, grad_values

"""

this Evaluator class makes it possible

to compute loss and gradients in one pass

while retrieving them via two separate functions,

"loss" and "grads". This is done because scipy.optimize

requires separate functions for loss and gradients,

but computing them separately would be inefficient.

這個評估器類使它成為可能。

在一個通道中計算損耗和梯度。

當通過兩個不同的函數檢索它們時,

“損失”和“梯度”。這是因為scipy.optimize

要求分離的函數用於損失和梯度,

但是單獨計算它們將是低效的

"""

class Evaluator(object):

def __init__(self):

self.loss_value = None

self.grads_values = None

def loss(self, x):

assert self.loss_value is None

loss_value, grad_values = eval_loss_and_grads(x)

self.loss_value = loss_value

self.grad_values = grad_values

return self.loss_value

def grads(self, x):

assert self.loss_value is not None

grad_values = np.copy(self.grad_values)

self.loss_value = None

self.grad_values = None

return grad_values

evaluator = Evaluator()

# run scipy-based optimization (L-BFGS) over the pixels of the generated image

# 運行 scipy-based optimization (L-BFGS) 覆蓋 生成的圖像的像素

# so as to minimize the neural style loss

# 這樣可以減少神經類型的損失

if K.image_data_format() == 'channels_first':

x = np.random.uniform(0, 255, (1, 3, img_nrows, img_ncols)) - 128.

else:

x = np.random.uniform(0, 255, (1, img_nrows, img_ncols, 3)) - 128.

for i in range(iterations):

print('Start of iteration', i)

start_time = time.time()

x, min_val, info = fmin_l_bfgs_b(evaluator.loss, x.flatten(),

fprime=evaluator.grads, maxfun=20)

print('Current loss value:', min_val)

# save current generated image

img = deprocess_image(x.copy())

fname = result_prefix + '_at_iteration_%d.png' % i

imsave(fname, img)

end_time = time.time()

print('Image saved as', fname)

print('Iteration %d completed in %ds' % (i, end_time - start_time))

它會有一個不斷漸進渲染的過程:

30秒教會你用Python製作表白神器,讓你2019結束單身

雖然我有老婆,而且我老婆特別好看,漂亮。但是為了不傷害到你們,我就用大樓渲染一下莫奈的名畫。給你們具體看一下。

30秒教會你用Python製作表白神器,讓你2019結束單身

30秒教會你用Python製作表白神器,讓你2019結束單身

30秒教會你用Python製作表白神器,讓你2019結束單身

看起來還是非常有質感的,代碼貼在這裡,我相信有很多人一定會比我有創意。做出來的圖一定會獨一無二。比如下面這個就做的特別好看。你們可以嘗試用人像渲染名畫,出來的效果真心非常美麗好看而且獨具個性!

30秒教會你用Python製作表白神器,讓你2019結束單身

但是,如果審美觀比較差的,還是要問問旁邊的人,以下就是我朋友用劉亦菲做的失敗案例。

他是用劉亦菲照片去模仿《無名女郎》的風格,把照片糊了一片,我把照片發出來給大家笑笑......

30秒教會你用Python製作表白神器,讓你2019結束單身

30秒教會你用Python製作表白神器,讓你2019結束單身

其實,只要是自己用心做出的禮物,你喜歡的人一定會非常感動。

所以誰說程序員不浪漫了!只要真的喜歡一個妹子,會為她做盡溫暖之事!哪怕是用自己的方式。追妹子,只要用心,她都會被感動。

30秒教會你用Python製作表白神器,讓你2019結束單身

愛情沒有性價比,沒有風險控制,但只要你盡了力付出過,就不會後悔。

願每一個渴望戀愛的人都能今年最後一天找到自己的心有所屬。

30秒教會你用Python製作表白神器,讓你2019結束單身


分享到:


相關文章: