Kears+Opencv實(shí)現(xiàn)簡單人臉識(shí)別
寫在前面:這篇文章也是借鑒了一些前輩的代碼和思路寫的,代碼有些也是復(fù)用了別人的。
先說下思路:
1.首先利用Opencv檢測出人臉的區(qū)域
2.在成功的檢測出人臉區(qū)域后,將識(shí)別出的人臉區(qū)域截取成圖片,儲(chǔ)存起來,用作后續(xù)的訓(xùn)練數(shù)據(jù)。
3.在獲取到了足夠多的數(shù)據(jù)后,搭建CNN網(wǎng)絡(luò)進(jìn)行訓(xùn)練。
5.訓(xùn)練完成后,將模型存儲(chǔ)起來。 6.在利用Opencv實(shí)時(shí)讀取視頻流,將檢測出人臉的區(qū)域變成圖片放入模型中進(jìn)行預(yù)測。
以上就是這個(gè)項(xiàng)目的一個(gè)基本的思路了。
1.利用Opencv檢測人臉的代碼如下,這個(gè)代碼在Opencv的官方文檔中也有,最重要的是加載的xml文件,因?yàn)檫@個(gè)xml文件中是保存這已經(jīng)訓(xùn)練好的人臉檢測模型。
import cv2
def identify_face(window_name, camera_idx):
cv2.namedWindow(window_name)
# 視頻來源,可以來自一段已存好的視頻,也可以直接來自USB攝像頭
cap = cv2.VideoCapture(camera_idx)
# 告訴OpenCV使用人臉識(shí)別分類器
classfier = cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")
# 識(shí)別出人臉后要畫的邊框的顏色,RGB格式
color = (0, 255, 0)
while cap.isOpened(): # 是否初始化攝像頭設(shè)備
ok, frame = cap.read() # 讀取一幀數(shù)據(jù)
if not ok:
break
# 將當(dāng)前幀轉(zhuǎn)換成灰度圖像
grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 人臉檢測,1.2和4分別為圖片縮放比例和需要檢測的有效點(diǎn)數(shù)
faceRects = classfier.detectMultiScale(grey, scaleFactor=1.2, minNeighbors=4, minSize=(32, 32))
if len(faceRects) > 0: # 大于0則檢測到人臉
for faceRect in faceRects: # 單獨(dú)框出每一張人臉
x, y, w, h = faceRect # 獲得人臉的左上角對(duì)應(yīng)坐標(biāo),及寬度和高度
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)
# 顯示圖像
cv2.imshow(window_name, frame)
c = cv2.waitKey(10)
if c & 0xFF == ord('q'):
break
# 釋放攝像頭并銷毀所有窗口
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
identify_face("identify face", 0)
2.在檢測出人臉區(qū)域后,將人臉區(qū)域截取成圖片保存下來
import cv2
from threading import Thread
def identify_face_and_store_face_image(window_name, camera_idx):
cv2.namedWindow(window_name)
# 視頻來源,可以來自一段已存好的視頻,也可以直接來自USB攝像頭
cap = cv2.VideoCapture(camera_idx)
# 告訴OpenCV使用人臉識(shí)別分類器
classfier = cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")
# 識(shí)別出人臉后要畫的邊框的顏色,RGB格式
color = (0, 255, 0)
# 保存圖片的索引
num = 0
while cap.isOpened(): # 是否初始化攝像頭設(shè)備
ok, frame = cap.read() # 讀取一幀數(shù)據(jù)
if not ok:
break
# 將當(dāng)前幀轉(zhuǎn)換成灰度圖像
grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 人臉檢測,1.2和2分別為圖片縮放比例和需要檢測的有效點(diǎn)數(shù)
faceRects = classfier.detectMultiScale(grey, scaleFactor=1.2, minNeighbors=4, minSize=(32, 32))
if len(faceRects) > 0: # 大于0則檢測到人臉
for faceRect in faceRects: # 單獨(dú)框出每一張人臉
x, y, w, h = faceRect # 獲得人臉的左上角對(duì)應(yīng)坐標(biāo),及寬度和高度
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)
# store_face_image(frame, h, num, w, x, y)
# 開啟一個(gè)線程去存儲(chǔ)人臉圖片
t = Thread(target=store_face_image, args=(frame, h, num, w, x, y, ))
t.start()
# 顯示捕捉了多少張人臉照片
font = cv2.FONT_HERSHEY_SIMPLEX # 字體
cv2.putText(frame, ('num %d' % num), (x + 30, y + 30), font, 1, (255, 0, 255), 2)
num += 1
if num <= 1000: # 保存1000張圖片后就退出
break
if num >= 1000:
break
# 顯示圖像
cv2.imshow(window_name, frame)
c = cv2.waitKey(10)
if c & 0xFF == ord('q'):
break
# 釋放攝像頭并銷毀所有窗口
cap.release()
cv2.destroyAllWindows()
def store_face_image(frame, h, num, w, x, y):
# 將當(dāng)前幀保存為圖片
img_name = '%s/%d.jpg' % (r'face_image', num)
image = frame[y - 10: y + h + 10, x - 10: x + w + 10]
cv2.imwrite(img_name, image)
if __name__ == '__main__':
identify_face_and_store_face_image("identify face", 0)
3.將保存的數(shù)據(jù)進(jìn)行處理,比如打上標(biāo)簽,進(jìn)行歸一化等等,下列代碼是load_datasets.py文件中的
import os
import sys
import numpy as np
import cv2
IMAGE_SIZE = 64
# 按照指定圖像大小調(diào)整尺寸
def resize_image(image, height=IMAGE_SIZE, width=IMAGE_SIZE):
top, bottom, left, right = (0, 0, 0, 0)
# 獲取圖像尺寸
h, w, _ = image.shape
# 對(duì)于長寬不相等的圖片,找到最長的一邊
longest_edge = max(h, w)
# 計(jì)算短邊需要增加多上像素寬度使其與長邊等長
if h < longest_edge:
dh = longest_edge - h
top = dh // 2
bottom = dh - top
elif w < longest_edge:
dw = longest_edge - w
left = dw // 2
right = dw - left
else:
pass
# RGB顏色
BLACK = [0, 0, 0]
# 給圖像增加邊界,是圖片長、寬等長,cv2.BORDER_CONSTANT指定邊界顏色由value指定
constant = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT, value=BLACK)
# 調(diào)整圖像大小并返回
return cv2.resize(constant, (height, width))
# 讀取訓(xùn)練數(shù)據(jù)
images = []
labels = []
def read_path(path_name):
for dir_item in os.listdir(path_name):
# 從初始路徑開始疊加,合并成可識(shí)別的操作路徑
full_path = os.path.abspath(os.path.join(path_name, dir_item))
if os.path.isdir(full_path): # 如果是文件夾,繼續(xù)遞歸調(diào)用
read_path(full_path)
else: # 文件
if dir_item.endswith('.jpg'):
image = cv2.imread(full_path)
image = resize_image(image, IMAGE_SIZE, IMAGE_SIZE)
# 放開這個(gè)代碼,可以看到resize_image()函數(shù)的實(shí)際調(diào)用效果
# cv2.imwrite('1.jpg', image)
images.append(image)
labels.append(path_name)
return images, labels
# 從指定路徑讀取訓(xùn)練數(shù)據(jù)
def load_dataset(path_name):
images, labels = read_path(path_name)
# 將輸入的所有圖片轉(zhuǎn)成四維數(shù)組,尺寸為(圖片數(shù)量*IMAGE_SIZE*IMAGE_SIZE*3)
# 共587張圖片,IMAGE_SIZE為64,故對(duì)我來說尺寸為587 * 64 * 64 * 3
# 圖片為64 * 64像素,一個(gè)像素3個(gè)顏色值(RGB)
images = np.array(images)
print(images.shape)
# 標(biāo)注數(shù)據(jù),'my_face_image'文件夾下都是我的臉部圖像,全部指定為0,你可以在獲取他人的臉部圖片比如說同學(xué)的,指定為1,
labels = np.array([0 if label.endswith('my_face_image') else 1 for label in labels])
return images, labels
if __name__ == '__main__':
if len(sys.argv) != 1:
print("Usage:%s path_name\r\n" % (sys.argv[0]))
else:
images, labels = load_dataset("face_image")
4.搭建模型,進(jìn)行訓(xùn)練
import random
import numpy as np
from sklearn.model_selection import train_test_split
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.optimizers import SGD
from keras.utils import np_utils
from keras.models import load_model
from keras import backend as K
from load_datasets import load_dataset, resize_image, IMAGE_SIZE
class Dataset:
def __init__(self, path_name):
# 訓(xùn)練集
self.train_images = None
self.train_labels = None
# 驗(yàn)證集
self.valid_images = None
self.valid_labels = None
# 測試集
self.test_images = None
self.test_labels = None
# 數(shù)據(jù)集加載路徑
self.path_name = path_name
# 當(dāng)前庫采用的維度順序
self.input_shape = None
# 加載數(shù)據(jù)集并按照交叉驗(yàn)證的原則劃分?jǐn)?shù)據(jù)集并進(jìn)行相關(guān)預(yù)處理工作
def load(self, img_rows=IMAGE_SIZE, img_cols=IMAGE_SIZE,
img_channels=3, nb_classes=2):
# 加載數(shù)據(jù)集到內(nèi)存
images, labels = load_dataset(self.path_name)
train_images, valid_images, train_labels, valid_labels = train_test_split(images, labels, test_size=0.3,
random_state=random.randint(0, 100))
_, test_images, _, test_labels = train_test_split(images, labels, test_size=0.5,
random_state=random.randint(0, 100))
# 當(dāng)前的維度順序如果為'th',則輸入圖片數(shù)據(jù)時(shí)的順序?yàn)椋篶hannels,rows,cols,否則:rows,cols,channels
# 這部分代碼就是根據(jù)keras庫要求的維度順序重組訓(xùn)練數(shù)據(jù)集
if K.image_dim_ordering() == 'th':
train_images = train_images.reshape(train_images.shape[0], img_channels, img_rows, img_cols)
valid_images = valid_images.reshape(valid_images.shape[0], img_channels, img_rows, img_cols)
test_images = test_images.reshape(test_images.shape[0], img_channels, img_rows, img_cols)
self.input_shape = (img_channels, img_rows, img_cols)
else:
train_images = train_images.reshape(train_images.shape[0], img_rows, img_cols, img_channels)
valid_images = valid_images.reshape(valid_images.shape[0], img_rows, img_cols, img_channels)
test_images = test_images.reshape(test_images.shape[0], img_rows, img_cols, img_channels)
self.input_shape = (img_rows, img_cols, img_channels)
# 輸出訓(xùn)練集、驗(yàn)證集、測試集的數(shù)量
print(train_images.shape[0], 'train samples')
print(valid_images.shape[0], 'valid samples')
print(test_images.shape[0], 'test samples')
# 我們的模型使用categorical_crossentropy作為損失函數(shù),因此需要根據(jù)類別數(shù)量nb_classes將
# 類別標(biāo)簽進(jìn)行one-hot編碼使其向量化,在這里我們的類別只有兩種,經(jīng)過轉(zhuǎn)化后標(biāo)簽數(shù)據(jù)變?yōu)槎S
train_labels = np_utils.to_categorical(train_labels, nb_classes)
valid_labels = np_utils.to_categorical(valid_labels, nb_classes)
test_labels = np_utils.to_categorical(test_labels, nb_classes)
# 像素?cái)?shù)據(jù)浮點(diǎn)化以便歸一化
train_images = train_images.astype('float32')
valid_images = valid_images.astype('float32')
test_images = test_images.astype('float32')
# 將其歸一化,圖像的各像素值歸一化到0~1區(qū)間
train_images /= 255
valid_images /= 255
test_images /= 255
self.train_images = train_images
self.valid_images = valid_images
self.test_images = test_images
self.train_labels = train_labels
self.valid_labels = valid_labels
self.test_labels = test_labels
# CNN網(wǎng)絡(luò)模型類
class Model:
def __init__(self):
self.model = None
# 建立模型
def build_model(self, dataset, nb_classes=2):
# 構(gòu)建一個(gè)空的網(wǎng)絡(luò)模型,它是一個(gè)線性堆疊模型,各神經(jīng)網(wǎng)絡(luò)層會(huì)被順序添加,專業(yè)名稱為序貫?zāi)P突蚓€性堆疊模型
self.model = Sequential()
# 以下代碼將順序添加CNN網(wǎng)絡(luò)需要的各層,一個(gè)add就是一個(gè)網(wǎng)絡(luò)層
self.model.add(Convolution2D(32, 3, 3, border_mode='same',
input_shape=dataset.input_shape)) # 1 2維卷積層
self.model.add(Activation('relu')) # 2 激活函數(shù)層
self.model.add(Convolution2D(32, 3, 3)) # 3 2維卷積層
self.model.add(Activation('relu')) # 4 激活函數(shù)層
self.model.add(MaxPooling2D(pool_size=(2, 2))) # 5 池化層
self.model.add(Dropout(0.25)) # 6 Dropout層
self.model.add(Convolution2D(64, 3, 3, border_mode='same')) # 7 2維卷積層
self.model.add(Activation('relu')) # 8 激活函數(shù)層
self.model.add(Convolution2D(64, 3, 3)) # 9 2維卷積層
self.model.add(Activation('relu')) # 10 激活函數(shù)層
self.model.add(MaxPooling2D(pool_size=(2, 2))) # 11 池化層
self.model.add(Dropout(0.25)) # 12 Dropout層
self.model.add(Flatten()) # 13 Flatten層
self.model.add(Dense(512)) # 14 Dense層,又被稱作全連接層
self.model.add(Activation('relu')) # 15 激活函數(shù)層
self.model.add(Dropout(0.5)) # 16 Dropout層
self.model.add(Dense(nb_classes)) # 17 Dense層
self.model.add(Activation('softmax')) # 18 分類層,輸出最終結(jié)果
# 輸出模型概況
self.model.summary()
# 訓(xùn)練模型
def train(self, dataset, batch_size=20, nb_epoch=10, data_augmentation=True):
sgd = SGD(lr=0.01, decay=1e-6,
momentum=0.9, nesterov=True) # 采用SGD+momentum的優(yōu)化器進(jìn)行訓(xùn)練,首先生成一個(gè)優(yōu)化器對(duì)象
self.model.compile(loss='categorical_crossentropy',
optimizer=sgd,
metrics=['accuracy']) # 完成實(shí)際的模型配置工作
# 不使用數(shù)據(jù)提升,所謂的提升就是從我們提供的訓(xùn)練數(shù)據(jù)中利用旋轉(zhuǎn)、翻轉(zhuǎn)、加噪聲等方法創(chuàng)造新的
# 訓(xùn)練數(shù)據(jù),有意識(shí)的提升訓(xùn)練數(shù)據(jù)規(guī)模,增加模型訓(xùn)練量
if not data_augmentation:
self.model.fit(dataset.train_images,
dataset.train_labels,
batch_size=batch_size,
nb_epoch=nb_epoch,
validation_data=(dataset.valid_images, dataset.valid_labels),
shuffle=True)
# 使用實(shí)時(shí)數(shù)據(jù)提升
else:
# 定義數(shù)據(jù)生成器用于數(shù)據(jù)提升,其返回一個(gè)生成器對(duì)象datagen,datagen每被調(diào)用一
# 次其生成一組數(shù)據(jù)(順序生成),節(jié)省內(nèi)存,其實(shí)就是python的數(shù)據(jù)生成器
datagen = ImageDataGenerator(
featurewise_center=False, # 是否使輸入數(shù)據(jù)去中心化(均值為0),
samplewise_center=False, # 是否使輸入數(shù)據(jù)的每個(gè)樣本均值為0
featurewise_std_normalization=False, # 是否數(shù)據(jù)標(biāo)準(zhǔn)化(輸入數(shù)據(jù)除以數(shù)據(jù)集的標(biāo)準(zhǔn)差)
samplewise_std_normalization=False, # 是否將每個(gè)樣本數(shù)據(jù)除以自身的標(biāo)準(zhǔn)差
zca_whitening=False, # 是否對(duì)輸入數(shù)據(jù)施以ZCA白化
rotation_range=20, # 數(shù)據(jù)提升時(shí)圖片隨機(jī)轉(zhuǎn)動(dòng)的角度(范圍為0~180)
width_shift_range=0.2, # 數(shù)據(jù)提升時(shí)圖片水平偏移的幅度(單位為圖片寬度的占比,0~1之間的浮點(diǎn)數(shù))
height_shift_range=0.2, # 同上,只不過這里是垂直
horizontal_flip=True, # 是否進(jìn)行隨機(jī)水平翻轉(zhuǎn)
vertical_flip=False) # 是否進(jìn)行隨機(jī)垂直翻轉(zhuǎn)
# 計(jì)算整個(gè)訓(xùn)練樣本集的數(shù)量以用于特征值歸一化、ZCA白化等處理
datagen.fit(dataset.train_images)
# 利用生成器開始訓(xùn)練模型
self.model.fit_generator(datagen.flow(dataset.train_images, dataset.train_labels,
batch_size=batch_size),
samples_per_epoch=dataset.train_images.shape[0],
nb_epoch=nb_epoch,
validation_data=(dataset.valid_images, dataset.valid_labels))
MODEL_PATH = 'zhuhaipeng.face.model.h5'
def save_model(self, file_path=MODEL_PATH):
self.model.save(file_path)
def load_model(self, file_path=MODEL_PATH):
self.model = load_model(file_path)
def evaluate(self, dataset):
score = self.model.evaluate(dataset.test_images, dataset.test_labels, verbose=1)
print("%s: %.2f%%" % (self.model.metrics_names[1], score[1] * 100))
# 識(shí)別人臉
def face_predict(self, image):
# 依然是根據(jù)后端系統(tǒng)確定維度順序
if K.image_dim_ordering() == 'th' and image.shape != (1, 3, IMAGE_SIZE, IMAGE_SIZE):
image = resize_image(image) # 尺寸必須與訓(xùn)練集一致都應(yīng)該是IMAGE_SIZE x IMAGE_SIZE
image = image.reshape((1, 3, IMAGE_SIZE, IMAGE_SIZE)) # 與模型訓(xùn)練不同,這次只是針對(duì)1張圖片進(jìn)行預(yù)測
elif K.image_dim_ordering() == 'tf' and image.shape != (1, IMAGE_SIZE, IMAGE_SIZE, 3):
image = resize_image(image)
image = image.reshape((1, IMAGE_SIZE, IMAGE_SIZE, 3))
# 浮點(diǎn)并歸一化
image = image.astype('float32')
image /= 255
# 給出輸入屬于各個(gè)類別的概率,我們是二值類別,則該函數(shù)會(huì)給出輸入圖像屬于0和1的概率各為多少
result = self.model.predict_proba(image)
print('result:', result)
# 給出類別預(yù)測:0或者1
result = self.model.predict_classes(image)
# 返回類別預(yù)測結(jié)果
return result[0]
if __name__ == '__main__': # 訓(xùn)練模型
dataset = Dataset('face_image')
dataset.load()
model = Model()
model.build_model(dataset)
# 測試訓(xùn)練函數(shù)的代碼
model.train(dataset)
if __name__ == '__main__': # 訓(xùn)練并保存模型
dataset = Dataset('face_image')
dataset.load()
model = Model()
model.build_model(dataset)
model.train(dataset)
model.save_model(file_path='model/zhuhaipeng.face.model.h5')
if __name__ == '__main__': # 讀取模型進(jìn)行評(píng)估
dataset = Dataset('face_image')
dataset.load()
# 評(píng)估模型
model = Model()
model.load_model(file_path='model/zhuhaipeng.face.model.h5')
model.evaluate(dataset)
5.訓(xùn)練好模型后,使用Opencv實(shí)時(shí)讀取視頻流檢測人臉位置,再將人臉放入模型中進(jìn)行預(yù)測
# -*- coding: utf-8 -*-
import cv2
import sys
from face_train import Model
if __name__ == '__main__':
if len(sys.argv) != 1:
print("Usage:%s camera_id\r\n" % (sys.argv[0]))
sys.exit(0)
# 加載模型
model = Model()
model.load_model(file_path='model/zhuhaipeng.face.model.h5')
# 框住人臉的矩形邊框顏色
color = (0, 255, 0)
# 捕獲指定攝像頭的實(shí)時(shí)視頻流
cap = cv2.VideoCapture(0)
# 人臉識(shí)別分類器本地存儲(chǔ)路徑
cascade_path = "haarcascade_frontalface_alt2.xml"
# 循環(huán)檢測識(shí)別人臉
while True:
ret, frame = cap.read() # 讀取一幀視頻
if ret is True:
# 圖像灰化,降低計(jì)算復(fù)雜度
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
else:
continue
# 使用人臉識(shí)別分類器,讀入分類器
cascade = cv2.CascadeClassifier(cascade_path)
# 利用分類器識(shí)別出哪個(gè)區(qū)域?yàn)槿四?
faceRects = cascade.detectMultiScale(frame_gray, scaleFactor=1.2, minNeighbors=3, minSize=(32, 32))
if len(faceRects) > 0:
for faceRect in faceRects:
x, y, w, h = faceRect
# 截取臉部圖像提交給模型識(shí)別這是誰
image = frame[y - 10: y + h + 10, x - 10: x + w + 10]
faceID = model.face_predict(image)
# 如果是“我”
if faceID == 0:
cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, thickness=2)
# 文字提示是誰
cv2.putText(frame, 'zhuhaipeng',
(x + 30, y + 30), # 坐標(biāo)
cv2.FONT_HERSHEY_SIMPLEX, # 字體
1, # 字號(hào)
(255, 0, 255), # 顏色
2) # 字的線寬
else: # 如果不是我
# 文字提示未知
cv2.putText(frame, 'Unknown people ',
(x + 30, y + 30), # 坐標(biāo)
cv2.FONT_HERSHEY_SIMPLEX, # 字體
1, # 字號(hào)
(255, 0, 255), # 顏色
2) # 字的線寬
cv2.imshow("identify me", frame)
# 等待10毫秒看是否有按鍵輸入
k = cv2.waitKey(10)
# 如果輸入q則退出循環(huán)
if k & 0xFF == ord('q'):
break
# 釋放攝像頭并銷毀所有窗口
cap.release()
cv2.destroyAllWindows()
到此一個(gè)簡單的人臉識(shí)別小項(xiàng)目就完成了,在這個(gè)項(xiàng)目中,只是簡單的二分類,可以在此基礎(chǔ)上進(jìn)行擴(kuò)展為多分類,如果識(shí)別的準(zhǔn)確率低的話,可以嘗試更改網(wǎng)絡(luò)架構(gòu),或者對(duì)數(shù)據(jù)進(jìn)行預(yù)處理等等,如果大家有興趣改進(jìn)的話,可以嘗試一下。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Opencv EigenFace人臉識(shí)別算法詳解
- OpenCV實(shí)現(xiàn)人臉識(shí)別簡單程序
- OpenCV + MFC實(shí)現(xiàn)簡單人臉識(shí)別
- opencv實(shí)現(xiàn)簡單人臉識(shí)別
- opencv 做人臉識(shí)別 opencv 人臉匹配分析
- 基于OpenCV的PHP圖像人臉識(shí)別技術(shù)
- OPENCV+JAVA實(shí)現(xiàn)人臉識(shí)別
- python+opencv實(shí)現(xiàn)的簡單人臉識(shí)別代碼示例
- python使用opencv進(jìn)行人臉識(shí)別
- OpenCV+face++實(shí)現(xiàn)實(shí)時(shí)人臉識(shí)別解鎖功能
相關(guān)文章
Python元類編程實(shí)現(xiàn)一個(gè)簡單的ORM
本文主要介紹了Python元類編程實(shí)現(xiàn)一個(gè)簡單的ORM,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03
python通過Matplotlib繪制常見的幾種圖形(推薦)
這篇文章主要介紹了使用matplotlib對(duì)幾種常見的圖形進(jìn)行繪制方法的相關(guān)資料,需要的朋友可以參考下2021-08-08
解決windows上安裝tensorflow時(shí)報(bào)錯(cuò),“DLL load failed: 找不到指定的模塊”的問題
這篇文章主要介紹了解決windows上安裝tensorflow時(shí)報(bào)錯(cuò),“DLL load failed: 找不到指定的模塊”的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
Python HTMLParser模塊解析html獲取url實(shí)例
這篇文章主要介紹了Python HTMLParser模塊解析html獲取url實(shí)例,HTMLParser是python用來解析html的模塊,HTMLParser采用的是一種事件驅(qū)動(dòng)的模式,需要的朋友可以參考下2015-04-04
Linux上使用Python統(tǒng)計(jì)每天的鍵盤輸入次數(shù)
這篇文章主要介紹了Linux上使用Python統(tǒng)計(jì)每天的鍵盤輸入次數(shù),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04
解決pycharm上的jupyter notebook端口被占用問題
今天小編就為大家分享一篇解決pycharm上的jupyter notebook端口被占用問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-12-12

