python庫之–turtle,matplotlib,numpy,opencv,os,pillow

  • 2019 年 11 月 27 日
  • 筆記

引言

下面部分為本人初窺python的世界有感所作。

在學python之前,我總覺得這個東西很玄乎,而且認為網上傳的很邪門:幾行畫出一個函數圖,幾十行做出一個人物形象,幾十行寫出一個小遊戲。當時只覺得時誇大其詞了。後來慢慢學習python,雖然知道了它可以用好多庫,但也並沒有覺得有什麼。直到這次學長給我機會讓我做一些東西,我才真正了解到它如何去使用,才真正發現它的樂趣,因此開啟了新世界的大門,非常感謝學長!!!

在學習python的初期,思維總被束縛,總覺得去實現讀取網頁連接、打開文件讀取每個文件、修改圖片資訊等等這些很難實現,結果發現這些。。。其實都在庫裡面實現好了,只需要去調用它即可。直到我認識到了這一點,我才開始走進這個python的世界。(不愧為超級語言)

在學習pyhton中,陸陸續續也了解到了其他的知識,例如Linux,伺服器,網站等等知識。對我來說,這些東西有著很大的吸引力。學習這些東西非常有趣,好玩,在休閑時間做做這些,挺享受,但是也挺虐心(庫中的各種函數不會使用)。唯一遺憾的是,到了現在才了解到這些東西。

以後繼續努力把~~~

turtle庫

turtle庫,也叫海龜庫。是入門級的圖形繪製函數庫。

turtle的原(wan)理(fa):

想像一隻小烏龜,在一個橫軸為x、縱軸為y的坐標系原點,(0,0)位置開始,在窗體正中心,在畫布上遊走,它走過的軌跡就形成了繪製的圖形。它由程式控制,當然,我們可以改變它的顏色,寬度,速度,行動軌跡等等。

畫筆的屬性

畫筆(畫筆的屬性,顏色、畫線的寬度等)

1) turtle.pensize():設置畫筆的寬度;

2) turtle.pencolor():沒有參數傳入,返回當前畫筆顏色,傳入參數設置畫筆顏色,可以是字元串如」green」, 「red」,也可以是RGB 3元組。例如turtle.pencolor(「red」),畫筆就會改成紅色。

3) turtle.speed (speed):設置畫筆移動速度,畫筆繪製的速度範圍[0,10]整數,數字越大越快。turtle.speed(10)為最快。(畫筆最快,而不是你最快  – .- 手動狗頭)

繪圖命令

操縱海龜繪圖有著許多的命令,這些命令可以劃分為3種:

一種為運動命令,一種為畫筆控制命令,還有一種是全局控制命令。

(1)    畫筆運動命令

命令

說明

turtle.forward(distance)

向當前畫筆方向移動distance像素長度

turtle.backward(distance)

向當前畫筆相反方向移動distance像素長度

turtle.right(degree)

順時針移動degree°

turtle.left(degree)

逆時針移動degree°

turtle.pendown()

移動時繪製圖形,預設時也為繪製

turtle.goto(x,y)

將畫筆移動到坐標為x,y的位置

turtle.penup()

提起筆移動,不繪製圖形,用於另起一個地方繪製

turtle.circle()

畫圓,半徑為正(負),表示圓心在畫筆的左邊(右邊)畫圓

setx( )

將當前x軸移動到指定位置

sety( )

將當前y軸移動到指定位置

setheading(angle)

設置當前朝向為angle角度

home()

設置當前畫筆位置為原點,朝向東。

dot(r)

繪製一個指定直徑和顏色的圓點

(2)     畫筆控制命令

命令

說明

turtle.fillcolor(colorstring)

繪製圖形的填充顏色

turtle.color(color1, color2)

同時設置pencolor=color1, fillcolor=color2

turtle.filling()

返回當前是否在填充狀態

turtle.begin_fill()

準備開始填充圖形

turtle.end_fill()

填充完成

turtle.hideturtle()

隱藏畫筆的turtle形狀

turtle.showturtle()

顯示畫筆的turtle形狀

(3)    全局控制命令

命令

說明

turtle.clear()

清空turtle窗口,但是烏龜的位置和狀態不會改變

turtle.reset()

清空窗口,重置turtle狀態為起始狀態

turtle.undo()

撤銷上一個turtle動作

turtle.isvisible()

返回當前turtle是否可見

stamp()

複製當前圖形

turtle.write(s [,font=(「font-name」,font_size,」font_type」)])

寫文本,s為文本內容,font是字體的參數,分別為字體名稱,大小和類型;font為可選項,font參數也是可選項

好了,現在我們可以舉個實例來運用這些操作了:

簡單時鐘 Python import turtle from datetime import * # 抬起畫筆,向前運動一段距離放下 def Skip(step): turtle.penup() turtle.forward(step) turtle.pendown() def mkHand(name, length): # 註冊Turtle形狀,建立錶針Turtle turtle.reset() Skip(-length * 0.1) # 開始記錄多邊形的頂點。當前的烏龜位置是多邊形的第一個頂點。 turtle.begin_poly() turtle.forward(length * 1.1) # 停止記錄多邊形的頂點。當前的烏龜位置是多邊形的最後一個頂點。將與第一個頂點相連。 turtle.end_poly() # 返回最後記錄的多邊形。 handForm = turtle.get_poly() turtle.register_shape(name, handForm) def Init(): global secHand, minHand, hurHand, printer # 重置Turtle指向北 turtle.mode("logo") # 建立三個錶針Turtle並初始化 mkHand("secHand", 135) mkHand("minHand", 125) mkHand("hurHand", 90) secHand = turtle.Turtle() secHand.shape("secHand") minHand = turtle.Turtle() minHand.shape("minHand") hurHand = turtle.Turtle() hurHand.shape("hurHand") for hand in secHand, minHand, hurHand: hand.shapesize(1, 1, 3) hand.speed(0) # 建立輸出文字Turtle printer = turtle.Turtle() # 隱藏畫筆的turtle形狀 printer.hideturtle() printer.penup() def SetupClock(radius): # 建立表的外框 turtle.reset() turtle.pensize(7) for i in range(60): Skip(radius) if i % 5 == 0: turtle.forward(20) Skip(-radius – 20) Skip(radius + 20) if i == 0: turtle.write(int(12), align="center", font=("Courier", 14, "bold")) elif i == 30: Skip(25) turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) Skip(-25) elif (i == 25 or i == 35): Skip(20) turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) Skip(-20) else: turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) Skip(-radius – 20) else: turtle.dot(5) Skip(-radius) turtle.right(6) def Week(t): week = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"] return week[t.weekday()] def Date(t): y = t.year m = t.month d = t.day return "%s %d%d" % (y, m, d) def Tick(): # 繪製錶針的動態顯示 t = datetime.today() second = t.second + t.microsecond * 0.000001 minute = t.minute + second / 60.0 hour = t.hour + minute / 60.0 secHand.setheading(6 * second) minHand.setheading(6 * minute) hurHand.setheading(30 * hour) turtle.tracer(False) printer.forward(65) printer.write(Week(t), align="center", font=("Courier", 14, "bold")) printer.back(130) printer.write(Date(t), align="center", font=("Courier", 14, "bold")) printer.h0ome() turtle.tracer(True) # 100ms後繼續調用tick turtle.ontimer(Tick, 100) def main(): # 打開/關閉龜動畫,並為更新圖紙設置延遲。 turtle.tracer(False) Init() SetupClock(160) turtle.tracer(True) Tick() turtle.mainloop() if __name__ == "__main__": main() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 import turtle from datetime import * # 抬起畫筆,向前運動一段距離放下 def Skip(step): turtle.penup() turtle.forward(step) turtle.pendown() def mkHand(name, length): # 註冊Turtle形狀,建立錶針Turtle turtle.reset() Skip(-length * 0.1) # 開始記錄多邊形的頂點。當前的烏龜位置是多邊形的第一個頂點。 turtle.begin_poly() turtle.forward(length * 1.1) # 停止記錄多邊形的頂點。當前的烏龜位置是多邊形的最後一個頂點。將與第一個頂點相連。 turtle.end_poly() # 返回最後記錄的多邊形。 handForm = turtle.get_poly() turtle.register_shape(name, handForm) def Init(): global secHand, minHand, hurHand, printer # 重置Turtle指向北 turtle.mode("logo") # 建立三個錶針Turtle並初始化 mkHand("secHand", 135) mkHand("minHand", 125) mkHand("hurHand", 90) secHand = turtle.Turtle() secHand.shape("secHand") minHand = turtle.Turtle() minHand.shape("minHand") hurHand = turtle.Turtle() hurHand.shape("hurHand") for hand in secHand, minHand, hurHand: hand.shapesize(1, 1, 3) hand.speed(0) # 建立輸出文字Turtle printer = turtle.Turtle() # 隱藏畫筆的turtle形狀 printer.hideturtle() printer.penup() def SetupClock(radius): # 建立表的外框 turtle.reset() turtle.pensize(7) for i in range(60): Skip(radius) if i % 5 == 0: turtle.forward(20) Skip(-radius – 20) Skip(radius + 20) if i == 0: turtle.write(int(12), align="center", font=("Courier", 14, "bold")) elif i == 30: Skip(25) turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) Skip(-25) elif (i == 25 or i == 35): Skip(20) turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) Skip(-20) else: turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) Skip(-radius – 20) else: turtle.dot(5) Skip(-radius) turtle.right(6) def Week(t): week = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"] return week[t.weekday()] def Date(t): y = t.year m = t.month d = t.day return "%s %d%d" % (y, m, d) def Tick(): # 繪製錶針的動態顯示 t = datetime.today() second = t.second + t.microsecond * 0.000001 minute = t.minute + second / 60.0 hour = t.hour + minute / 60.0 secHand.setheading(6 * second) minHand.setheading(6 * minute) hurHand.setheading(30 * hour) turtle.tracer(False) printer.forward(65) printer.write(Week(t), align="center", font=("Courier", 14, "bold")) printer.back(130) printer.write(Date(t), align="center", font=("Courier", 14, "bold")) printer.h0ome() turtle.tracer(True) # 100ms後繼續調用tick turtle.ontimer(Tick, 100) def main(): # 打開/關閉龜動畫,並為更新圖紙設置延遲。 turtle.tracer(False) Init() SetupClock(160) turtle.tracer(True) Tick() turtle.mainloop() if __name__ == "__main__": main()

這段程式碼運行後,會畫出一個簡單的時鐘,實時的表示現在的時間。

然而,運行出來的鐘錶是黑色的。。。很不酷,,,

所以我們只要在繪製圖形時設置畫筆的顏色就行了,那麼我們應該怎麼告訴電腦我們想用什麼顏色的呢?

這裡我們就了解到了RGB色彩模式

RGB色彩模式

RGB色彩模式是由三種顏色,也就是R(red),G(green),B(blue)構成的萬物色。它的每個取值範圍為0-255整數或者0-1小數,三種顏色不同的取值就構成了不同的顏色,具體的某個顏色可以網上搜出來表來對照。ex:

藍色(blue): (0,0,255)or (0,0,1)

粉色(pink):(255,192,203) or (1,0.75,0.8)

於是我們有三種變換顏色的方法:pencolor(「blue」)    pencolor(0,0,255)   pencolor(0,0,1)

這三種方法都是把顏色變為藍色,一般來說,記住顏色的英文名稱為最好。

然而,我們發現這還不夠,turtle雖然功能很齊全,但是在繪製函數圖等某種具體的需求上顯得有些乏力,所以我們渴望有新的東西可以滿足我們的需求。

於是——–matplotlib庫與NumPy 庫腳踏七彩祥雲從西邊歸來了。

matplotlib庫 and NumPy庫

在這裡為什麼將這兩個庫合起來介紹呢?是因為:matplotlib庫是一個數據可視化庫,顧名思義,就是將數據以表的形式呈現出來。而NumPy是 Python 語言的一個擴展程式庫,支援大量的維度數組與矩陣運算,此外也針對數組運算提供大量的數學函數庫。所以它們兩個結合在一起就可以根據我們的需求來繪製相應的圖形。例如繪製我們最熟悉的sin,cos這些三角函數影像。

程式碼如下:

Python

import numpy as np import matplotlib.pyplot as plt # 設置x,y軸的數值 x1 = np.linspace(0, 4*np.pi, 100) y1 = np.sin(x1) y2 = np.cos(x1) # 畫圖(x軸,y軸,給所繪製的曲線的名字,畫線顏色,畫線寬度) plt.plot(x1, y1, label="$sin(x)$", color="blue", linewidth=2) plt.plot(x1, y2, label="$cos(x)$", color="red", linewidth=2) # X和Y坐標軸 plt.xlabel("x") plt.ylabel("sin(x) and cos(x)") # 圖表的標題 plt.title("sin and cos") # Y軸的範圍 plt.ylim(-1.5, 1.5) plt.xlim(0,4*np.pi) # 顯示圖示 plt.legend() # 顯示圖 plt.show()

12345678910111213141516171819202122232425262728

import numpy as npimport matplotlib.pyplot as plt # 設置x,y軸的數值x1 = np.linspace(0, 4*np.pi, 100)y1 = np.sin(x1)y2 = np.cos(x1) # 畫圖(x軸,y軸,給所繪製的曲線的名字,畫線顏色,畫線寬度)plt.plot(x1, y1, label="$sin(x)$", color="blue", linewidth=2)plt.plot(x1, y2, label="$cos(x)$", color="red", linewidth=2) # X和Y坐標軸plt.xlabel("x")plt.ylabel("sin(x) and cos(x)") # 圖表的標題plt.title("sin and cos") # Y軸的範圍plt.ylim(-1.5, 1.5)plt.xlim(0,4*np.pi) # 顯示圖示plt.legend() # 顯示圖plt.show()

解釋一下其中的函數:

numpy.linspace(start, stop, num, endpoint=True, retstep=False, dtype=None)

在指定的間隔內返回均勻間隔的數字,在[start, stop]返回num均勻分布的樣本。即在x從0-4Π中返回100個均勻分布的點。

numpy.sin(t)

這個就很好理解了,根據t值來確定sin的函數值。同理numpy.cos也是。

那麼前三行的意思就是畫0-4Π範圍上的sin,cos的圖。

plt.plot(x,y,format_string,**kwargs) x軸數據,y軸數據,format_string控制曲線的格式字串 format_string 由顏色字元,風格字元,和標記字元 ,下面有鏈接介紹。

https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot

不過這些影像好像沒什麼意思??

所以我們找到了笛卡爾愛心曲線(-.-嘿嘿嘿嘿嘿嘿 十八禁)

於是程式碼就出來了:

Python

import matplotlib.pyplot as plt from matplotlib import animation import numpy as np import math def drawHeart(): t = np.linspace(0, math.pi, 1000) x = np.sin(t) y = np.cos(t) + np.power(x, 2.0/3) plt.plot(x, y, color='red', linewidth=2, label='h') plt.plot(-x, y, color='red', linewidth=2, label='-h') plt.xlabel('t') plt.ylabel('h') plt.ylim(-2, 2) plt.xlim(-2, 2) plt.title("愛心曲線",fontproperties='SimHei') plt.show() drawHeart()

123456789101112131415161718

import matplotlib.pyplot as pltfrom matplotlib import animationimport numpy as npimport math def drawHeart():    t = np.linspace(0, math.pi, 1000)    x = np.sin(t)    y = np.cos(t) + np.power(x, 2.0/3)    plt.plot(x, y, color='red', linewidth=2, label='h')    plt.plot(-x, y, color='red', linewidth=2, label='-h')    plt.xlabel('t')    plt.ylabel('h')    plt.ylim(-2, 2)    plt.xlim(-2, 2)    plt.title("愛心曲線",fontproperties='SimHei')    plt.show()drawHeart()

這段程式碼就是用數學函數計算出具體值,然後畫出來一個愛心。

我們發現這還不夠好玩(nan),有沒有更好玩的,可以更考(ke)驗(yi)技(de)術(se)的呢?自然有啦,人的天性本就如此。所以我們找到了圖片轉化字元的樣例,就是一張圖片轉化為字元存到文本里,實現用字元實現對圖片的轉化。而我們怎麼進行對圖片的處理呢?由此,我們用到了pillow庫(又學到了)。

Pillow庫

要知道Pillow庫,首先要知道PIL。

PIL:Python imaging Library  即python的影像處理庫。

Pillow 是PIL派生的一個分支,支援3以上Python版本。

Pillow庫支援相當多的圖片格式。直接使用Image模組中的open()函數讀取圖片,而不必先處理圖片的格式,Pillow庫自動根據文件決定格式。

Image模組中的save()函數可以保存圖片,除非你指定文件格式,那麼文件名中的擴展名用來指定文件格式。

例:

Python

im = Image.open('demo.gif') im.save('demo.BMP')

12

im = Image.open('demo.gif')im.save('demo.BMP')

回到正題上,我們要處理圖片,讓其用字元填充,那麼字元一定不能填充其顏色,也就是說,我們用字元去生成的圖片只是黑白的。那麼,我們就要將圖片轉化為黑白的,然後一個一個的對比並填充,所以我們用到了模式轉換函數。即:

Python

# 黑白 img = Image.open('s.png') img.show() #原圖,為彩色的 img = img.convert("L") img.show() #轉換後的,只有黑白

12345

# 黑白img = Image.open('s.png')img.show() #原圖,為彩色的img = img.convert("L")img.show() #轉換後的,只有黑白

這樣就完成了我們關鍵的第一步,接下來就開始進行對比。

在這裡有一個重要的函數getpixel,該函數檢索指定坐標點的像素的RGB顏色值。然後下面對比選取相應坐標的字元值即可。

接下來只要每個位置對比,選取合適的字元去填充就完成了整個操作。

下面為完整程式碼:

Python

from PIL import Image #要索引的字元列表 ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,"^`'. ") #獲取字元列表的長度 length = len(ascii_char) #讀取影像文件 img = Image.open('time.jpg') #對影像進行一定縮小,圖片的大小可以根據上傳圖片的大小來按需調節 (width,height) = img.size img = img.resize((int(width*0.5),int(height*0.2))) print(img.size) def convert(img): img = img.convert("L") # 轉為灰度影像 txt = "" for i in range(img.size[1]): for j in range(img.size[0]): gray = img.getpixel((j, i)) # 獲取每個坐標像素點的灰度 unit = 256.0 / length txt += ascii_char[int(gray / unit)] #獲取對應坐標的字元值 txt += 'n' return txt txt = convert(img) f = open("demo.txt","w") f.write(txt) #存儲到文件中 f.close()

1234567891011121314151617181920212223242526

from PIL import Image#要索引的字元列表ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,"^`'. ")#獲取字元列表的長度length = len(ascii_char)#讀取影像文件img = Image.open('time.jpg')#對影像進行一定縮小,圖片的大小可以根據上傳圖片的大小來按需調節(width,height) = img.sizeimg = img.resize((int(width*0.5),int(height*0.2)))  print(img.size)def convert(img):    img = img.convert("L")  # 轉為灰度影像    txt = ""    for i in range(img.size[1]):        for j in range(img.size[0]):            gray = img.getpixel((j, i))     # 獲取每個坐標像素點的灰度            unit = 256.0 / length            txt += ascii_char[int(gray / unit)] #獲取對應坐標的字元值        txt += 'n'    return  txt txt = convert(img)f = open("demo.txt","w")f.write(txt)            #存儲到文件中f.close()

pillow還有很多對圖片處理的強大作用,還沒了解完,這裡就不一一貼出來了。

https://www.jianshu.com/p/f03f7f52d465

此為總結鏈接,方便以後查看。

那麼在實現了用字元去填充圖片後,我們自然會想到,可不可以用圖片去填充圖片呢??

當然可以,這就是千圖成像技術,用非常多圖片拼成一個大圖。

程式碼非常的短,其實核心思想是差不多的,只需要將字元填充換為影像填充即可。

Python

from PIL import Image import os import random def get_img(path="./img_v2/save/"): img_file_list = os.listdir(path) tmp = path+random.choice(img_file_list) return Image.open(tmp) if __name__ == '__main__': width,height = int(458*320/10), int(537*240/10) test_im = Image.new("RGB", (width,height), "#ffffff") peiqi_img = Image.open("a.jpg").convert("L") for i in range(0,width,100): for j in range(0,height,100): tmp_i,tmp_j = int(i/32),int(j/24) gray = peiqi_img.getpixel((tmp_i,tmp_j)) if gray < 230: test_im.paste(get_img(),(i,j)) test_im.save("tmp.jpg")

12345678910111213141516171819

from PIL import Imageimport osimport randomdef get_img(path="./img_v2/save/"):    img_file_list = os.listdir(path)    tmp = path+random.choice(img_file_list)    return Image.open(tmp)if __name__ == '__main__':    width,height = int(458*320/10), int(537*240/10)    test_im = Image.new("RGB", (width,height), "#ffffff")    peiqi_img = Image.open("a.jpg").convert("L")     for i in range(0,width,100):        for j in range(0,height,100):            tmp_i,tmp_j = int(i/32),int(j/24)            gray = peiqi_img.getpixel((tmp_i,tmp_j))            if gray < 230:                test_im.paste(get_img(),(i,j))    test_im.save("tmp.jpg")

若精度不夠高,拼成的圖片效果不好,則可以對圖片進行裁剪處理:

Python

#把圖片全部剪切為100*100格式存到img_v2/save目錄下 循環時也以100為步長 這樣會調整精度 readPath='./img_v2/img/' savePath='./img_v2/save/' files=os.listdir(readPath) n=0 for file in files: n+=1 imgPath=readPath+ "\" + file img=cv2.imread(imgPath) img=cv2.resize(img,(100,100))#更改圖片的大小 cv2.imwrite(savePath+ "\"+file,img) print(n)#查看循環情況

123456789101112

#把圖片全部剪切為100*100格式存到img_v2/save目錄下 循環時也以100為步長 這樣會調整精度readPath='./img_v2/img/'savePath='./img_v2/save/'files=os.listdir(readPath)n=0for file in files:    n+=1    imgPath=readPath+ "\" + file    img=cv2.imread(imgPath)    img=cv2.resize(img,(100,100))#更改圖片的大小    cv2.imwrite(savePath+ "\"+file,img)    print(n)#查看循環情況

這裡也用到了os庫,os庫是Python標準庫,包含幾百個函數,常用路徑操作、進程管理、環境參數等幾類。os.path子庫以path為入口,用於操作和處理文件路徑。關於os庫的一些常用函數可以看這裡

https://www.jianshu.com/p/2b12a065ea22

還用到了OpenCV庫,OpenCV是一個用於影像處理、分析、機器視覺方面的開源函數庫。它的常用函數看這裡

https://www.cnblogs.com/lufengyu/p/11495148.html

總結

寫的第一篇部落格,技術乾貨真心不多,可以說是小白入門篇。在技術方面我知道了python作為超級語言的優勢,但更多的是在心理方面上的感受。在寫這些程式的時候,我完成了思維的轉變,這個意義對我來說很大。做這些小程式,雖然小,但是給我的進步卻很大。當你從知道它 ->了解它 -> 實現它 經過這三步轉變後,你會發現有些東西其實也沒有那麼的神秘。有時候越學越發現自己的弱小,從而很容易不知疲倦的去學習它(突然想到人生苦短,我學python)。可以如果說不逼自己一把去試試,真的不知道程式碼原來可以這麼精彩。。。

那是不是只有逼自己一把,才能發現世界原來那麼精彩呢?

我已經準備好了。