精選了20個Python實戰專案(附原始碼),拿走就用!

法納斯特發表於2021-12-19

38dc7788fdde502d47da6f2f483ac530.gif

大家好,我是小F。

Python是目前最好的程式語言之一。由於其可讀性和對初學者的友好性,已被廣泛使用。

那麼要想學會並掌握Python,可以實戰的練習專案是必不可少的。

接下來,我將給大家介紹20個非常實用的Python專案,幫助大家更好的學習Python。

大家也可根據專案的需求,自己構建解決方法,提高程式設計水平。

 猜字遊戲

在這個遊戲中,你必須一個字母一個字母的猜出祕密單詞。

如果你猜錯了一個字母,你將丟掉一條命。

正如遊戲名那樣,你需要仔細選擇字母,因為你的生命數量非常有限。

import random

# 生命次數
lives = 3

# 神祕單詞, 隨機選擇
words = ['pizza', 'fairy', 'teeth', 'shirt', 'otter', 'plane']
secret_word = random.choice(words)
# print(secret_word)

clue = list('?????')
heart_symbol = u'\u2764'

guessed_word_correctly = False


def update_clue(guessed_letter, secret_word, clue):
    index = 0
    while index < len(secret_word):
        if guessed_letter == secret_word[index]:
            clue[index] = guessed_letter
        index = index + 1


while lives > 0:
    print(clue)
    print('剩餘生命次數: ' + heart_symbol * lives)
    guess = input('猜測字母或者是整個單詞: ')

    if guess == secret_word:
        guessed_word_correctly = True
        break

    if guess in secret_word:
        update_clue(guess, secret_word, clue)
    else:
        print('錯誤。你丟了一條命\n')
        lives = lives - 1


if guessed_word_correctly:
    print('你贏了! 祕密單詞是 ' + secret_word)
else:
    print('你輸了! 祕密單詞是 ' + secret_word)

下面就讓小F,來玩一下。

a7aae1f00269134e03c920b35ee5a47c.png

 鬧鐘

鬧鐘是一種具有可以在預先設定的時間被啟用以響鈴的功能的時鐘,用於喚醒打工人們。

使用Python中的DateTime模組來建立鬧鐘,並用Python中的playsound庫來播放鬧鐘聲音。

from datetime import datetime
from playsound import playsound

# 輸入
alarm_time = input("請輸入鬧鐘時間, 示例: 09:50:00 am\n")
# 時
alarm_hour = alarm_time[0:2]
# 分
alarm_minute = alarm_time[3:5]
# 秒
alarm_seconds = alarm_time[6:8]
# 上午或下午
alarm_period = alarm_time[9:11].upper()
print("完成鬧鐘設定..")

while True:
    now = datetime.now()
    current_hour = now.strftime("%I")
    current_minute = now.strftime("%M")
    current_seconds = now.strftime("%S")
    current_period = now.strftime("%p")

    # 時間判斷
    if alarm_period == current_period:
        if alarm_hour == current_hour:
            if alarm_minute == current_minute:
                if alarm_seconds == current_seconds:
                    print("起來啦!")
                    # 鬧鐘鈴聲
                    playsound('audio.mp3')
                    break

來測試一下,設定一個鬧鐘,到指定時間就會有音樂響起。

8967c218cc4c88c679338da541511591.png

 骰子模擬器

可以通過選擇1到6之間的隨機整數,來完成骰子模擬。

import random

# 設定最大值和最小值
min_val = 1
max_val = 6

# 是否繼續
roll_again = "yes"

# 迴圈
while roll_again == "yes" or roll_again == "y":
    print("開始擲骰子")
    print("骰子數值是 :")

    # 第一輪
    print(random.randint(min_val, max_val))

    # 第二輪
    print(random.randint(min_val, max_val))

    # 是否繼續
    roll_again = input("是否繼續擲骰子?(是的話, 輸入yes或者y)")

使用random.randint()函式。函式根據我們指定的開始和結束範圍返回一個隨機整數。

2959e445d78b668e483b8568cc35602c.png

 二維碼

二維碼是用於將資料編碼和解碼為機器可讀的方法。

包含一個白色背景上的黑色方塊網格,可以被任何成像裝置(如手機)讀取,並進行處理以從圖案中提取所需的資料。

import pyqrcode

# 設定二維碼資訊
s = "https://www.baidu.com"

# 生成二維碼
url = pyqrcode.create(s)

# 儲存二維碼
url.svg("baidu.svg", scale=8)

結果如下。

5b0510f7527887f81d1d2f2606f81c76.png

 語言檢測

當你需要處理包含不同語言資料,且資料非常大的時候,語言檢測就派上用場了。

使用Python中的langdetect包,可以在幾行程式碼內檢測超過55種不同的語言。

from langdetect import detect

text = input("輸入資訊: ")
print(detect(text))

示例。

141c2ca76c868c926cc4bdac9c0d54b2.png

 加密和解密

密碼術意味著更改訊息的文字,以便不知道你祕密的人永遠不會理解你的訊息。

下面就來建立一個GUI應用程式,使用Python進行加密和解密。

在這裡,我們需要編寫使用無限迴圈的程式碼,程式碼將不斷詢問使用者是否要加密或解密訊息。

from tkinter import messagebox, simpledialog, Tk


def is_even(number):
    return number % 2 == 0


def get_even_letters(message):
    even_letters = []
    for counter in range(0, len(message)):
        if is_even(counter):
            even_letters.append(message[counter])
    return even_letters


def get_odd_letters(message):
    odd_letters = []
    for counter in range(0, len(message)):
        if not is_even(counter):
            odd_letters.append(message[counter])
    return odd_letters


def swap_letters(message):
    letter_list = []
    if not is_even(len(message)):
        message = message + 'x'
    even_letters = get_even_letters(message)
    odd_letters = get_odd_letters(message)
    for counter in range(0, int(len(message) / 2)):
        letter_list.append(odd_letters[counter])
        letter_list.append(even_letters[counter])
    new_message = ''.join(letter_list)
    return new_message


def get_task():
    task = simpledialog.askstring('任務', '你是否想要加密或解密資訊?')
    return task


def get_message():
    message = simpledialog.askstring('資訊', '輸入相關資訊: ')
    return message


root = Tk()
while True:
    task = get_task()
    if task == '加密':
        message = get_message()
        encrypted = swap_letters(message)
        messagebox.showinfo('密電的密文為:', encrypted)

    elif task == '解密':
        message = get_message()
        decrypted = swap_letters(message)
        messagebox.showinfo('密電的明文為:', decrypted)
    else:
        break

root.mainloop()

示例。

529a3386b33ecd16969f69b57c8c825a.png

c021f6e9e39b2e59d67a1ab31b7c1da1.png

5d711bd643a09ea244e429779f77ac7c.png

 URL縮短

短網址由於易於記憶和輸入,因此在數字營銷領域非常受歡迎。

這裡給大家介紹一下,如何使用Python建立URL縮短器。

from __future__ import with_statement
import contextlib
try:
    from urllib.parse import urlencode
except ImportError:
    from urllib import urlencode
try:
    from urllib.request import urlopen
except ImportError:
    from urllib2 import urlopen
import sys


def make_tiny(url):
    request_url = ('http://tinyurl.com/api-create.php?' + urlencode({'url': url}))
    # print(request_url)
    with contextlib.closing(urlopen(request_url)) as response:
        return response.read().decode('utf-8')


def main():
    for tinyurl in map(make_tiny, ['https://baijiahao.baidu.com/s?id=1719379508156841662']):
        print(tinyurl)


if __name__ == '__main__':
    main()

執行程式碼,輸出如下。

# 輸出
https://tinyurl.com/y4z6z2gq

 音樂播放器

音樂播放器,可讓你快速輕鬆地管理和收聽所有音樂檔案。

應該不少小夥伴都使用過,網易雲音樂、QQ音樂、酷狗音樂等。

這裡小F將使用Pygame和Tkinter,來建立一個音樂播放器。

import pygame
import tkinter as tkr
from tkinter.filedialog import askdirectory
import os

music_player = tkr.Tk()
music_player.title("我的音樂播放器")
music_player.geometry("450x350")
directory = askdirectory()
os.chdir(directory)
song_list = os.listdir()

play_list = tkr.Listbox(music_player, font="Helvetica 12 bold", bg='yellow', selectmode=tkr.SINGLE)
for item in song_list:
    pos = 0
    play_list.insert(pos, item)
    pos += 1
pygame.init()
pygame.mixer.init()


def play():
    """播放"""
    pygame.mixer.music.load(play_list.get(tkr.ACTIVE))
    var.set(play_list.get(tkr.ACTIVE))
    pygame.mixer.music.play()


def stop():
    """停止"""
    pygame.mixer.music.stop()


def pause():
    """暫停"""
    pygame.mixer.music.pause()


def unpause():
    """取消暫停"""
    pygame.mixer.music.unpause()


Button1 = tkr.Button(music_player, width=5, height=3, font="Helvetica 12 bold", text="播放", command=play, bg="blue", fg="white")
Button2 = tkr.Button(music_player, width=5, height=3, font="Helvetica 12 bold", text="停止", command=stop, bg="red", fg="white")
Button3 = tkr.Button(music_player, width=5, height=3, font="Helvetica 12 bold", text="暫停", command=pause, bg="purple", fg="white")
Button4 = tkr.Button(music_player, width=5, height=3, font="Helvetica 12 bold", text="取消暫停", command=unpause, bg="orange", fg="white")

var = tkr.StringVar()
song_title = tkr.Label(music_player, font="Helvetica 12 bold", textvariable=var)

song_title.pack()
Button1.pack(fill="x")
Button2.pack(fill="x")
Button3.pack(fill="x")
Button4.pack(fill="x")
play_list.pack(fill="both", expand="yes")
music_player.mainloop()

選擇音樂檔案所在的資料夾,點選播放,即可聽見音樂。

7828467e666417e31ebeaa6e04b42800.png

 生命遊戲

生命遊戲由英國數學家約翰·H·康威設計的,是一種類似於生物社會的興衰和交替的遊戲。

61ae016a6e9adbbf1ec31b77c1a1bc23.gif

遊戲使用無限大小的矩形網格,其中每個網格都是空的或被有機體佔據。被佔用的細胞是活的,而空的細胞是死的。

遊戲在特定時期內進行,每一輪都會根據當前配置中生物體的排列建立一個新的世代。

下一代網格的狀態,是通過將以下四個基本規則應用於當前配置的每個網格來確定的:

  • 如果一個細胞還活著並且有兩個或三個活著的鄰居,那麼該細胞在下一代中仍然活著;

  • 一個沒有活鄰居或只有一個活鄰居的活細胞會在下一代死於孤立;

  • 有四個或更多活鄰居的活細胞會因下一代人口過剩而死亡;

  • 一個只有三個活著的鄰居的死細胞會導致出生並在下一代中存活;

board = [[1, 0, 0], [1, 0, 0], [1, 0, 0]]

# 鄰居陣列為給定的單元格找到8個相鄰的單元格
neighbors = [(1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1), (0, 1), (1, 1)]

rows = len(board)
cols = len(board[0])

# 建立一個原始板的副本
copy_board = [[board[row][col] for col in range(cols)] for row in range(rows)]

# 逐個單元地迭代
for row in range(rows):
    for col in range(cols):

        # 對於每個單元計算鄰居的數量
        live_neighbors = 0
        for neighbor in neighbors:

            r = (row + neighbor[0])
            c = (col + neighbor[1])

            # 檢查相鄰細胞的有效性,以及它是否原來是一個活細胞
            # 評估是針對副本進行的,因為它永遠不會更新。
            if (r < rows and r >= 0) and (c < cols and c >= 0) and (copy_board[r][c] == 1):
                live_neighbors += 1

        # 規則1或規則3
        if copy_board[row][col] == 1 and (live_neighbors < 2 or live_neighbors > 3):
            board[row][col] = 0
        # 規則4
        if copy_board[row][col] == 0 and live_neighbors == 3:
            board[row][col] = 1

print(board)

結果如下。

# 輸入
board = [[1, 0, 0], [1, 0, 0], [1, 0, 0]]

# 輸出
board = [[0, 0, 0], [1, 1, 0], [0, 0, 0]]

 Turtle繪圖

Turtle模組提供了在二維平面上移動的環境。

Turtle可以實現位置、航向和各種可能的狀態和動作。

import turtle as tu

roo = tu.Turtle()  # 建立物件
wn = tu.Screen()  # 螢幕物件
wn.bgcolor("black")  # 螢幕背景
wn.title("分形樹")
roo.left(90)  # 移動
roo.speed(20)  # 速度


def draw(l):  # 以長度'l'作為引數的遞迴函式
    if l < 10:
        return
    else:
        roo.pensize(2)  # 設定畫筆大小
        roo.pencolor("yellow")  # 畫筆顏色
        roo.forward(l)  # 朝向
        roo.left(30)  # 移動
        draw(3 * l / 4)  # 繪製
        roo.right(60)  # 移動
        draw(3 * l / 4)  # 繪製
        roo.left(30)  # 移動
        roo.pensize(2)
        roo.backward(l)  # 返回初始位置


draw(20)  # 繪製20次

roo.right(90)
roo.speed(2000)


# recursion
def draw(l):
    if (l < 10):
        return
    else:
        roo.pensize(2)
        roo.pencolor("magenta")  # magenta
        roo.forward(l)
        roo.left(30)
        draw(3 * l / 4)
        roo.right(60)
        draw(3 * l / 4)
        roo.left(30)
        roo.pensize(2)
        roo.backward(l)


draw(20)

roo.left(270)
roo.speed(2000)


# recursion
def draw(l):
    if (l < 10):
        return
    else:
        roo.pensize(2)
        roo.pencolor("red")  # red
        roo.forward(l)
        roo.left(30)
        draw(3 * l / 4)
        roo.right(60)
        draw(3 * l / 4)
        roo.left(30)
        roo.pensize(2)
        roo.backward(l)


draw(20)

roo.right(90)
roo.speed(2000)


# recursion
def draw(l):
    if (l < 10):
        return
    else:
        roo.pensize(2)
        roo.pencolor('#FFF8DC')  # white
        roo.forward(l)
        roo.left(30)
        draw(3 * l / 4)
        roo.right(60)
        draw(3 * l / 4)
        roo.left(30)
        roo.pensize(2)
        roo.backward(l)


draw(20)


########################################################

def draw(l):
    if (l < 10):
        return
    else:

        roo.pensize(3)
        roo.pencolor("lightgreen")  # lightgreen
        roo.forward(l)
        roo.left(30)
        draw(4 * l / 5)
        roo.right(60)
        draw(4 * l / 5)
        roo.left(30)
        roo.pensize(3)
        roo.backward(l)


draw(40)

roo.right(90)
roo.speed(2000)


# recursion
def draw(l):
    if (l < 10):
        return
    else:
        roo.pensize(3)
        roo.pencolor("red")  # red
        roo.forward(l)
        roo.left(30)
        draw(4 * l / 5)
        roo.right(60)
        draw(4 * l / 5)
        roo.left(30)
        roo.pensize(3)
        roo.backward(l)


draw(40)

roo.left(270)
roo.speed(2000)


# recursion
def draw(l):
    if (l < 10):
        return
    else:
        roo.pensize(3)
        roo.pencolor("yellow")  # yellow
        roo.forward(l)
        roo.left(30)
        draw(4 * l / 5)
        roo.right(60)
        draw(4 * l / 5)
        roo.left(30)
        roo.pensize(3)
        roo.backward(l)


draw(40)

roo.right(90)
roo.speed(2000)


# recursion
def draw(l):
    if (l < 10):
        return
    else:
        roo.pensize(3)
        roo.pencolor('#FFF8DC')  # white
        roo.forward(l)
        roo.left(30)
        draw(4 * l / 5)
        roo.right(60)
        draw(4 * l / 5)
        roo.left(30)
        roo.pensize(3)
        roo.backward(l)


draw(40)


########################################################
def draw(l):
    if (l < 10):
        return
    else:

        roo.pensize(2)
        roo.pencolor("cyan")  # cyan
        roo.forward(l)
        roo.left(30)
        draw(6 * l / 7)
        roo.right(60)
        draw(6 * l / 7)
        roo.left(30)
        roo.pensize(2)
        roo.backward(l)


draw(60)

roo.right(90)
roo.speed(2000)


# recursion
def draw(l):
    if (l < 10):
        return
    else:
        roo.pensize(2)
        roo.pencolor("yellow")  # yellow
        roo.forward(l)
        roo.left(30)
        draw(6 * l / 7)
        roo.right(60)
        draw(6 * l / 7)
        roo.left(30)
        roo.pensize(2)
        roo.backward(l)


draw(60)

roo.left(270)
roo.speed(2000)


# recursion
def draw(l):
    if (l < 10):
        return
    else:
        roo.pensize(2)
        roo.pencolor("magenta")  # magenta
        roo.forward(l)
        roo.left(30)
        draw(6 * l / 7)
        roo.right(60)
        draw(6 * l / 7)
        roo.left(30)
        roo.pensize(2)
        roo.backward(l)


draw(60)

roo.right(90)
roo.speed(2000)


# recursion
def draw(l):
    if (l < 10):
        return
    else:
        roo.pensize(2)
        roo.pencolor('#FFF8DC')  # white
        roo.forward(l)
        roo.left(30)
        draw(6 * l / 7)
        roo.right(60)
        draw(6 * l / 7)
        roo.left(30)
        roo.pensize(2)
        roo.backward(l)


draw(60)
wn.exitonclick()

繪製時間較長,結果如下,挺好看的。

b5d865f3f82a9f805b1c6e2239d7289a.png

 計算器

Kivy是一個免費的開源Python庫,可以快速輕鬆地開發高度互動的跨平臺應用程式。

這裡我將使用Python中的Kivy包來構建一個計算器GUI。

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label


class myApp(App):
    def build(self):
        root_widget = BoxLayout(orientation='vertical')
        output_label = Label(size_hint_y=0.75, font_size=50)
        button_symbols = ('1', '2', '3', '+',
                          '4', '5', '6', '-',
                          '7', '8', '9', '.',
                          '0', '*', '/', '=')
        button_grid = GridLayout(cols=4, size_hint_y=2)
        for symbol in button_symbols:
            button_grid.add_widget(Button(text=symbol))

        clear_button = Button(text='Clear', size_hint_y=None, height=100)
        def print_button_text(instance):
            output_label.text += instance.text
        for button in button_grid.children[1:]:
            button.bind(on_press=print_button_text)
        def resize_label_text(label, new_height):
            label.fontsize = 0.5*label.height
        output_label.bind(height=resize_label_text)

        def evaluate_result(instance):
            try:
                output_label.text = str(eval(output_label.text))
            except SyntaxError:
                output_label.text = 'Python Syntax error!'
        button_grid.children[0].bind(on_press=evaluate_result)

        def clear_label(instance):
            output_label.text = " "
        clear_button.bind(on_press=clear_label)

        root_widget.add_widget(output_label)
        root_widget.add_widget(button_grid)
        root_widget.add_widget(clear_button)
        return root_widget


myApp().run()

執行程式碼,出現一個計算器,非常好用!

46fde328590dc8d6563119f3e777ee2a.png

 猜數遊戲

猜數字遊戲目的是猜測出程式想出的數字,基本邏輯:

  • 程式隨機選擇1到100之間的一個數字或任何其他數字組合;

  • 然後它會要求玩家輸入它的建議;

  • 然後它會檢查這個數字是否與計算機隨機生成的數字相同;如果是,則玩家獲勝;

  • 如果玩家的猜測不一樣,那麼它會檢查數字是否高於或低於猜測並告訴玩家;

import random

# 建立隨機數
n = random.randrange(1,100)
# 獲取輸入
guess = int(input("輸入任意數值: "))

while n != guess: # 判斷是否正確
    # 小於
    if guess < n:
        print("太小了")
        guess = int(input("再次輸入數值: "))
    # 大於
    elif guess > n:
        print("太大了!")
        guess = int(input("再次輸入數值: "))
    else:
        break
print("真棒,你猜對了!!")

執行程式碼,小F來猜一猜。

92bfe61b04193a727a0ff1a7f684e3aa.png

 影像轉換器

我們知道有大量的影像檔案格式可用於儲存圖形資料,最流行的便是JPG和PNG。

使用Python中的Tkinter庫和PIL庫,建立一個將PNG影像轉換為JPG的應用程式。

import tkinter as tk
from tkinter import filedialog
from PIL import Image

root = tk.Tk()
canvas1 = tk.Canvas(root, width=300, height=250, bg='azure3', relief='raised')
canvas1.pack()

label1 = tk.Label(root, text="影像轉換器", bg='azure3')
label1.config(font=('helvetica', 20))
canvas1.create_window(150, 60, window=label1)


def getPNG():
    global im1
    import_file_path = filedialog.askopenfilename()
    im1 = Image.open(import_file_path)


browse_png = tk.Button(text="選擇PNG檔案", command=getPNG, bg="royalblue", fg='white', font=('helvetica', 12, 'bold'))
canvas1.create_window(150, 130, window=browse_png)


def convert():
    global im1
    export_file_path = filedialog.asksaveasfilename(defaultextension='.jpg')
    im1.save(export_file_path)


saveasbutton = tk.Button(text="轉換PNG成JPG", command=convert, bg='royalblue', fg='white', font=('helvetica', 12, 'bold'))
canvas1.create_window(150, 180, window=saveasbutton)
root.mainloop()

執行程式碼,選擇圖片,點選轉換按鈕,即可完成影像格式變換。

ab662d970cf3c007969e286d699ddf0c.png

 重量轉換器

重量換算是指單位值乘以標準換算值。

使用Python中的Tkinter庫建立一個重量轉換器應用程式。

from tkinter import *

# 建立一個GUI視窗
window = Tk()


def from_kg():
    gram = float(e2_value.get())*1000
    pound = float(e2_value.get())*2.20462
    ounce = float(e2_value.get())*35.274
    t1.delete("1.0", END)
    t1.insert(END, gram)
    t2.delete("1.0", END)
    t2.insert(END, pound)
    t3.delete("1.0", END)
    t3.insert(END, ounce)


e1 = Label(window, text="輸入重量(單位KG)")
e2_value = StringVar()
e2 = Entry(window, textvariable=e2_value)
e3 = Label(window, text="Gram")
e4 = Label(window, text="Pound")
e5 = Label(window, text="Ounce")

t1 = Text(window, height=5, width=30)
t2 = Text(window, height=5, width=30)
t3 = Text(window, height=5, width=30)

b1 = Button(window, text="Convert", command=from_kg)

e1.grid(row=0, column=0)
e2.grid(row=0, column=1)
e3.grid(row=1, column=0)
e4.grid(row=1, column=1)
e5.grid(row=1, column=2)
t1.grid(row=2, column=0)
t2.grid(row=2, column=1)
t3.grid(row=2, column=2)
b1.grid(row=0, column=2)

window.mainloop()

執行程式碼,出現介面,輸入數值,點選轉換。

518d9b8f2ab6174d96aacabbe1875364.png

 年齡和性別檢測

使用Python程式語言帶你完成使用機器學習進行年齡和性別檢測的任務。

首先需要編寫用於檢測人臉的程式碼,因為如果沒有人臉檢測,我們將無法進一步完成年齡和性別預測的任務。

下一步是預測影像中人的性別。在這裡,我將性別網路載入到記憶體中,並將檢測到的人臉通過網路傳輸,用於性別檢測任務。

下一個任務是預測影像中人類的年齡。這裡我將載入網路並使用前向傳遞來獲取輸出。由於網路架構與性別網路相似,我們可以充分利用所有輸出來獲得任務的預期年齡組來檢測年齡。

import cv2 as cv


def getFaceBox(net, frame, conf_threshold=0.7):
    # 獲取位置
    frameOpencvDnn = frame.copy()
    frameHeight = frameOpencvDnn.shape[0]
    frameWidth = frameOpencvDnn.shape[1]
    blob = cv.dnn.blobFromImage(frameOpencvDnn, 1.0, (300, 300), [104, 117, 123], True, False)

    net.setInput(blob)
    detections = net.forward()
    bboxes = []
    for i in range(detections.shape[2]):
        confidence = detections[0, 0, i, 2]
        if confidence > conf_threshold:
            x1 = int(detections[0, 0, i, 3] * frameWidth)
            y1 = int(detections[0, 0, i, 4] * frameHeight)
            x2 = int(detections[0, 0, i, 5] * frameWidth)
            y2 = int(detections[0, 0, i, 6] * frameHeight)
            bboxes.append([x1, y1, x2, y2])
            cv.rectangle(frameOpencvDnn, (x1, y1), (x2, y2), (0, 255, 0), int(round(frameHeight/150)), 8)
    return frameOpencvDnn, bboxes


# 性別
genderProto = "gender_deploy.prototxt"
genderModel = "gender_net.caffemodel"
genderNet = cv.dnn.readNet(genderModel, genderProto)
# 性別引數
genderList = ['Male', 'Female']

# 年齡
ageProto = "age_deploy.prototxt"
ageModel = "age_net.caffemodel"
ageNet = cv.dnn.readNet(ageModel, ageProto)
# 年齡引數
ageList = ['(0 - 2)', '(4 - 6)', '(8 - 12)', '(15 - 20)', '(25 - 32)', '(38 - 43)', '(48 - 53)', '(60 - 100)']

MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
padding = 20

# 人臉
faceProto = 'opencv_face_detector.pbtxt'
faceModel = 'opencv_face_detector_uint8.pb'
faceNet = cv.dnn.readNet(faceModel, faceProto)

# 讀取圖片
frame = cv.imread('image1.jpg')
frameFace, bboxes = getFaceBox(faceNet, frame)

for bbox in bboxes:
    face = frame[max(0, bbox[1] - padding):min(bbox[3] + padding, frame.shape[0] - 1),
           max(0, bbox[0] - padding):min(bbox[2] + padding, frame.shape[1] - 1)]
    blob = cv.dnn.blobFromImage(face, 1, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
    genderNet.setInput(blob)
    genderPreds = genderNet.forward()
    gender = genderList[genderPreds[0].argmax()]
    print("Gender Output : {}".format(genderPreds))
    print("Gender : {}".format(gender))

    ageNet.setInput(blob)
    agePreds = ageNet.forward()
    age = ageList[agePreds[0].argmax()]
    print("Gender Output : {}".format(agePreds))
    print("Gender : {}".format(age))

    label = "{}, {}".format(gender, age)
    cv.namedWindow("Age Gender Demo", 0)
    cv.resizeWindow("Age Gender Demo", 900, 500)
    cv.putText(frameFace, label, (bbox[0], bbox[1] - 20), cv.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 3, cv.LINE_AA)
    cv.imshow("Age Gender Demo", frameFace)
    cv.waitKey(0)

執行程式碼,結果如下。

b1acc5df32c29f81a345133a11d024e9.png

性別是OK的,就是年齡差了點意思。

 人臉檢測

構建一個檢測人臉的程式是開始機器學習計算機視覺任務的好方法。

使用Python的OpenCV庫進行人臉檢測的任務。

import cv2

face_cascade = cv2.CascadeClassifier('face_detector.xml')
img = cv2.imread('image.jpg')
faces = face_cascade.detectMultiScale(img, 1.1, 10)

for (x, y, w, h) in faces:
  cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imwrite("face_detected.png", img)
print('Successfully saved')

原圖如下。

ed082126890d07ed70bc685848d34738.png

檢測結果。

a8fdced6dc17b597e8164b6e8bd96ded.png

 鉛筆素描

使用不到20行的Python程式碼將影像轉換為鉛筆素描。

import cv2

image = cv2.imread("dog.jpg")
cv2.imshow("Dog", image)
cv2.waitKey(0)

gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("New Dog", gray_image)
cv2.waitKey(0)

inverted_image = 255 - gray_image
cv2.imshow("Inverted", inverted_image)
cv2.waitKey()

blurred = cv2.GaussianBlur(inverted_image, (21, 21), 0)

inverted_blurred = 255 - blurred
pencil_sketch = cv2.divide(gray_image, inverted_blurred, scale=256.0)
cv2.imshow("Sketch", pencil_sketch)
cv2.waitKey(0)

cv2.imshow("original image", image)
cv2.imshow("pencil sketch", pencil_sketch)
cv2.waitKey(0)

結果如下。

93848ec541b871eacd7b3f7075653aea.png

 文字編輯器

使用Python建立一個文字編輯器GUI,它可以建立、開啟、編輯和儲存文字檔案。

所有小部件的排列方式應使按鈕小部件位於視窗布局的左側,而文字框小部件位於右側。

import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename

def open_file():
    """開啟"""
    filepath = askopenfilename(
        filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")]
    )
    if not filepath:
        return
    txt_edit.delete(1.0, tk.END)
    with open(filepath, "r") as input_file:
        text = input_file.read()
        txt_edit.insert(tk.END, text)
    window.title(f"文字編輯器 - {filepath}")

def save_file():
    """儲存"""
    filepath = asksaveasfilename(
        defaultextension="txt",
        filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
    )
    if not filepath:
        return
    with open(filepath, "w") as output_file:
        text = txt_edit.get(1.0, tk.END)
        output_file.write(text)
    window.title(f"文字編輯器 - {filepath}")

window = tk.Tk()
window.title("文字編輯器")
window.rowconfigure(0, minsize=800, weight=1)
window.columnconfigure(1, minsize=800, weight=1)

txt_edit = tk.Text(window)
fr_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)
btn_open = tk.Button(fr_buttons, text="開啟", command=open_file)
btn_save = tk.Button(fr_buttons, text="儲存", command=save_file)

btn_open.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
btn_save.grid(row=1, column=0, sticky="ew", padx=5)

fr_buttons.grid(row=0, column=0, sticky="ns")
txt_edit.grid(row=0, column=1, sticky="nsew")

window.mainloop()

結果如下。

dfae1531a6293ff97b1dd83418d114bf.png

 影像分割

影像分割是機器視覺應用中將數字影像劃分為一組畫素的關鍵過程之一。

看看下面的圖片,糖果按特定順序排列形成一個詞。

56f222ff7178b7ba6166e9d3d2b2a532.png

如果具有視覺的機器人是按顏色來計算糖果的數量,那麼瞭解糖果之間的界限對它來說就很重要。

from skimage.io import imread
from skimage import color
import numpy as np
import matplotlib.pyplot as plt

# 讀取圖片
cimage = imread('photo.jpg')
fig, ax = plt.subplots(figsize=(20, 20))
ax.imshow(cimage)
ax.axis('off')

# RGB轉為LAB
lab_img = color.rgb2lab(cimage)
x, y, z = lab_img.shape

# 顯示顏色
to_plot = cimage.reshape(x * y, 3)
colors_map = to_plot.astype(np.float) / 256

# 建立資料
scatter_x = []
scatter_y = []
for xi in range(x):
    for yi in range(y):
        L_val = lab_img[xi, yi][0]
        A_val = lab_img[xi, yi][1]
        B_val = lab_img[xi, yi][2]
        scatter_x.append(A_val)
        scatter_y.append(B_val)

plt.figure(figsize=(20, 20))
plt.xlabel("a* from green to red")
plt.ylabel("b* from blue to yellow")
plt.scatter(scatter_x, scatter_y, c=colors_map)
# 顯示
plt.show()

我們可以使用散點圖,根據糖果的顏色對影像進行分割。

1317c793a82687ae93d0163b60f66a6f.png

最後我們可以根據顏色,正確地分割影像中的糖果。

def filter_color(L_val_min, A_val_min, A_val_max, B_val_min, B_val_max):
    filtered_image = np.copy(cimage)
    for xi in range(x):
        for yi in range(y):
            L_val = lab_img[xi, yi][0]
            A_val = lab_img[xi, yi][1]
            B_val = lab_img[xi, yi][2]
            if L_val > L_val_min and A_val > A_val_min and A_val < A_val_max  and B_val > B_val_min and B_val < B_val_max:
                pass
            else:
                filtered_image[xi, yi] = [255,255,255]
    return filtered_image


lab_img = color.rgb2lab(cimage)
yellow = filter_color(70, -50, 0, 30, 100)
red = filter_color(30, 25, 100, 0, 100)
green = filter_color(50, -128, -20, 0, 50)
blue = filter_color(50, -40, 30, -128, -20)
white = filter_color(93, -25, 25, -25, 25)
pink = filter_color(50, 20, 128, -50, 0)

fig, ax = plt.subplots(nrows=3, ncols=2, figsize=(20,20))
ax[0][0].imshow(pink)
ax[0][0].set_title("pink Candies")
ax[0][0].axis('off')

ax[0][1].imshow(yellow)
ax[0][1].set_title("yellow Candies")
ax[0][1].axis('off')

ax[1][0].imshow(red)
ax[1][0].set_title("red Candies")
ax[1][0].axis('off')

ax[1][1].imshow(green)
ax[1][1].set_title("green Candies")
ax[1][1].axis('off')

ax[2][0].imshow(white)
ax[2][0].set_title("white Candies")
ax[2][0].axis('off')

ax[2][1].imshow(blue)
ax[2][1].set_title("blue Candies")
ax[2][1].axis('off')
plt.show()

結果如下。

72b3b1f3f51db5356326061e1477f897.png

 模擬時鐘

使用Tkinter製作一個簡單的模擬時鐘GUI應用程式。

try:
    import Tkinter
except:
    import tkinter as Tkinter

import math
import time


class main(Tkinter.Tk):
    def __init__(self):
        Tkinter.Tk.__init__(self)
        self.x = 150  # 中心點x座標
        self.y = 150  # 中心點y座標
        self.length = 50
        self.creating_all_function_trigger()

    # 觸發器
    def creating_all_function_trigger(self):
        self.create_canvas_for_shapes()
        self.creating_background_()
        self.creating_sticks()
        return

    # 建立背景
    def creating_background_(self):
        self.image = Tkinter.PhotoImage(file='clock.gif')
        self.canvas.create_image(150, 150, image=self.image)
        return

    # 建立畫布
    def create_canvas_for_shapes(self):
        self.canvas = Tkinter.Canvas(self, bg='black')
        self.canvas.pack(expand='yes', fill='both')
        return

    # 建立移動的線條
    def creating_sticks(self):
        self.sticks = []
        for i in range(3):
            store = self.canvas.create_line(self.x, self.y, self.x+self.length, self.y+self.length, width=2, fill='red')
            self.sticks.append(store)
        return

    # 定期重新整理
    def update_class(self):
        now = time.localtime()
        t = time.strptime(str(now.tm_hour), "%H")
        hour = int(time.strftime("%I", t))*5
        now = (hour, now.tm_min, now.tm_sec)
        # 改變座標
        for n, i in enumerate(now):
            x, y = self.canvas.coords(self.sticks[n])[0:2]
            cr = [x, y]
            cr.append(self.length*math.cos(math.radians(i*6)-math.radians(90))+self.x)
            cr.append(self.length*math.sin(math.radians(i*6)-math.radians(90))+self.y)
            self.canvas.coords(self.sticks[n], tuple(cr))
        return


if __name__ == '__main__':
    root = main()

    while True:
        root.update()
        root.update_idletasks()
        root.update_class()

結果如下。

da9acda559f7c912e27b6b5fb63e7d77.png

好了,以上就是今天分享的內容,大家可以自行去動手練習。

這裡小F用到了不少的Python庫,大家直接pip安裝即可,下面是示例。

# pip安裝
pip install opencv-python -i https://simple.baidu.com/pypi/simple

相關的檔案及程式碼都已上傳,公眾號回覆【實戰】即可獲取。

萬水千山總是情,點個 ? 行不行

推薦閱讀

5c30d58c9eb05d1646c0592cbeafd265.png

fc6ed7cdaf902112f0064a5e63760987.png

ac0d4f53de4d63a59a93fe184594a5b2.png

···  END  ···

49b6d572c368b67579923275b869670c.png

相關文章