構(gòu)建一個計算機(jī)視覺項(xiàng)目
你想創(chuàng)建一個應(yīng)用程序來檢測一些東西嗎?貓和狗,檢測水果的成熟程度,在圖片中找到品牌?
如果你的答案是需要,那么這篇文章就是為你準(zhǔn)備的!
將向你展示如何為你的探測器創(chuàng)建一個應(yīng)用程序,并把它放到互聯(lián)網(wǎng)上,讓每個人都能看到。
你將能夠上傳一個測試圖像,模型將返回預(yù)測框和標(biāo)簽。
免責(zé)聲明:你需要在你的電腦中安裝git才能將文件上傳到HuggingFace Spaces。如果你沒有,不要擔(dān)心!安裝起來很容易。
這將是項(xiàng)目的工作流程:
首先,你必須為你的項(xiàng)目收集圖像。你想從長頸鹿中發(fā)現(xiàn)斑馬嗎?首先需要獲取這兩種動物的圖像。無論你想檢測什么,你都需要它的圖像。這個點(diǎn)在工作流程中是白色的,這意味著你必須在你的計算機(jī)中完成工作。
標(biāo)簽圖像在工作流中顯示為藍(lán)色,這是因?yàn)槟銓⑹褂肈atature的標(biāo)簽工具。Datature是一家專門為數(shù)據(jù)標(biāo)簽和模型訓(xùn)練構(gòu)建用戶友好工具的公司。
你還將使用Datature來訓(xùn)練模型。
一旦模型訓(xùn)練好了,你就把它下載到你的電腦上,把所有的文件放在一起(這些文件我會提供給你)
當(dāng)所有文件放在一起時,你將把它們上傳到HuggingFace Spaces,你的模型就可以使用了!
1.找到圖片
在計算機(jī)視覺項(xiàng)目中,我們需要做的第一件事是收集圖像。如果我們想要訓(xùn)練一個深度神經(jīng)網(wǎng)絡(luò),我們需要成千上萬張圖像。
幸運(yùn)的是,Datature使用非常先進(jìn)的模型,而且可能是預(yù)訓(xùn)練的,這意味著如果我們從頭開始訓(xùn)練模型,我們只需要需要的一小部分圖像。
每個類大約有100個圖像就足夠了。例如,如果你想要檢測t恤和褲子,你將需要100個t恤和100個褲子的圖像。當(dāng)然,這個例子也適用于其他情況。例如,你可以有100張貓和狗的圖片,所以你可以有100張貓的例子,也可以有100張狗的例子。
如果有類不平衡是可以的,例如如果你的項(xiàng)目檢測晴天和陰天,你可以有120張晴天的圖片和100張陰天的圖片。大約100張就足夠了。
收集所有的圖像并存儲在你的計算機(jī)的一個文件夾中。
2.標(biāo)記圖像
在Datature中創(chuàng)建一個帳戶,并為你的用例創(chuàng)建一個項(xiàng)目。
這篇博文詳細(xì)介紹了如何:
創(chuàng)建Datature Nexus賬戶(免費(fèi)試用)
創(chuàng)建一個項(xiàng)目
上傳圖片
創(chuàng)建類
注釋圖片
在圖像中創(chuàng)建矩形框
為每個框分配一個類
對于每個圖像,你將注釋一個框(對象在哪里?)和一個類(對象是什么?)
只閱讀標(biāo)簽部分,之后,在項(xiàng)目概述中,你應(yīng)該看到你的圖像統(tǒng)計,標(biāo)簽分布等。例如,項(xiàng)目概述應(yīng)該是這樣的:
在這個例子中,我有一個名為香蕉的項(xiàng)目,我標(biāo)記了16張圖片,我有3類:成熟的、可食用的和無效的。這只是一個示例,所以請確保每個類至少有100個示例!
3.訓(xùn)練模型
一旦我們有了圖像,我們就可以訓(xùn)練我們的模型了!我們將不得不在Nexus中創(chuàng)建一個“工作流”。
構(gòu)建訓(xùn)練工作流程:選擇訓(xùn)練-測試分割比,選擇增強(qiáng),選擇模型設(shè)置
訓(xùn)練模型
監(jiān)控模型:損失、精度、召回
導(dǎo)出模型
模型將需要大約1小時來訓(xùn)練,之后你應(yīng)該看到這個
進(jìn)入Artifacts并下載TensorFlow模型
當(dāng)計算機(jī)中導(dǎo)出了一個.zip文件時,這一部分就完成了。
4.創(chuàng)建一個HuggingFace帳戶
模型是經(jīng)過訓(xùn)練的,我們把它以.zip的形式下載到我們的電腦上。但我們?nèi)绾闻c它交互呢?
我們可以通過上傳照片到HuggingFace Spaces與它交互。我們還需要一些網(wǎng)站前端的代碼。
Huggingface Spaces是Huggingface旗下的一個網(wǎng)站,人們可以在這里展示自己的模型,并與他們交互。
這些是創(chuàng)建步驟
1.創(chuàng)建Huggingface帳戶
2.創(chuàng)建一個Space
3.為Space寫一個名字。記住,這個網(wǎng)站將是公開的,所以選擇一個與應(yīng)用程序相匹配的名字!例如:香蕉分析或類似的東西
4.選擇Streamlit作為空間SDK
5.選擇public
6.Space使用完成后,將存儲庫克隆到本地計算機(jī)中的一個文件夾中
7.可選的README.md
5.收集所有文件并上傳至HuggingFace空間
現(xiàn)在,我們的計算機(jī)中有了屬于Space的文件夾。我們必須復(fù)制所有文件,并使用git將所有文件上傳到Space。
首先,復(fù)制模型文件(saved_model/ folder, label_map.pbtxt)到文件夾
然后,在這個https://gist.github.com/anebz/2f62caeab1f24aabb9f5d1a60a4c2d25文件夾中創(chuàng)建3個文件
app.py
此文件包含用于上傳圖像、加載模型、進(jìn)行預(yù)處理和從模型獲得預(yù)測的代碼。
注意那些帶有#TODO的行,你必須修改它們!
特別是color_map,它們是每個類的方框的顏色。打開文件label_map.pbtxt查看給每個類分配了什么label_id,并使用這個label_id為顏色分配RGB值。
在這個例子中,我只有2個類,因此只有2種顏色。如果你有更多的類,按照示例的格式添加更多行:
1: [255, 0, 0],
記住,除了最后一行以外,每一行的末尾都應(yīng)該有一個逗號!
import cv2
import numpy as np
from PIL import Image
import streamlit as st
import tensorflow as tf
from tensorflow.keras.models import load_model
# most of this code has been obtained from Datature's prediction script
# https://github.com/datature/resources/blob/main/scripts/bounding_box/prediction.py
st.set_option('deprecation.showfileUploaderEncoding', False)
@st.cache(allow_output_mutation=True)
def load_model():
return tf.saved_model.load('./saved_model')
def load_label_map(label_map_path):
"""
Reads label map in the format of .pbtxt and parse into dictionary
Args:
label_map_path: the file path to the label_map
Returns:
dictionary with the format of {label_index: {'id': label_index, 'name': label_name}}
"""
label_map = {}
with open(label_map_path, "r") as label_file:
for line in label_file:
if "id" in line:
label_index = int(line.split(":")[-1])
label_name = next(label_file).split(":")[-1].strip().strip('"')
label_map[label_index] = {"id": label_index, "name": label_name}
return label_map
def predict_class(image, model):
image = tf.cast(image, tf.float32)
image = tf.image.resize(image, [150, 150])
image = np.expand_dims(image, axis = 0)
return model.predict(image)
def plot_boxes_on_img(color_map, classes, bboxes, image_origi, origi_shape):
for idx, each_bbox in enumerate(bboxes):
color = color_map[classes[idx]]
## Draw bounding box
cv2.rectangle(
image_origi,
(int(each_bbox[1] * origi_shape[1]),
int(each_bbox[0] * origi_shape[0]),),
(int(each_bbox[3] * origi_shape[1]),
int(each_bbox[2] * origi_shape[0]),),
color,
2,
)
## Draw label background
cv2.rectangle(
image_origi,
(int(each_bbox[1] * origi_shape[1]),
int(each_bbox[2] * origi_shape[0]),),
(int(each_bbox[3] * origi_shape[1]),
int(each_bbox[2] * origi_shape[0] + 15),),
color,
-1,
)
## Insert label class & score
cv2.putText(
image_origi,
"Class: {}, Score: {}".format(
str(category_index[classes[idx]]["name"]),
str(round(scores[idx], 2)),
),
(int(each_bbox[1] * origi_shape[1]),
int(each_bbox[2] * origi_shape[0] + 10),),
cv2.FONT_HERSHEY_SIMPLEX,
0.3,
(0, 0, 0),
1,
cv2.LINE_AA,
)
return image_origi
# Webpage code starts here
#TODO change this
st.title('YOUR PROJECT NAME')
st.text('made by XXX')
st.markdown('## Description about your project')
with st.spinner('Model is being loaded...'):
model = load_model()
# ask user to upload an image
file = st.file_uploader("Upload image", type=["jpg", "png"])
if file is None:
st.text('Waiting for upload...')
else:
st.text('Running inference...')
# open image
test_image = Image.open(file).convert("RGB")
origi_shape = np.a(chǎn)sarray(test_image).shape
# resize image to default shape
default_shape = 320
image_resized = np.a(chǎn)rray(test_image.resize((default_shape, default_shape)))
## Load color map
category_index = load_label_map("./label_map.pbtxt")
# TODO Add more colors if there are more classes
# color of each label. check label_map.pbtxt to check the index for each class
color_map = {
1: [255, 0, 0], # bad -> red
2: [0, 255, 0] # good -> green
}
## The model input needs to be a tensor
input_tensor = tf.convert_to_tensor(image_resized)
## The model expects a batch of images, so add an axis with `tf.newaxis`.
input_tensor = input_tensor[tf.newaxis, ...]
## Feed image into model and obtain output
detections_output = model(input_tensor)
num_detections = int(detections_output.pop("num_detections"))
detections = {key: value[0, :num_detections].numpy() for key, value in detections_output.items()}
detections["num_detections"] = num_detections
## Filter out predictions below threshold
# if threshold is higher, there will be fewer predictions
# TODO change this number to see how the predictions change
confidence_threshold = 0.8
indexes = np.where(detections["detection_scores"] > confidence_threshold)
## Extract predicted bounding boxes
bboxes = detections["detection_boxes"][indexes]
# there are no predicted boxes
if len(bboxes) == 0:
st.error('No boxes predicted')
# there are predicted boxes
else:
st.success('Boxes predicted')
classes = detections["detection_classes"][indexes].a(chǎn)stype(np.int64)
scores = detections["detection_scores"][indexes]
# plot boxes and labels on image
image_origi = np.a(chǎn)rray(Image.fromarray(image_resized).resize((origi_shape[1], origi_shape[0])))
image_origi = plot_boxes_on_img(color_map, classes, bboxes, image_origi, origi_shape)
# show image in web page
st.image(Image.fromarray(image_origi), caption="Image with predictions", width=400)
st.markdown("### Predicted boxes")
for idx in range(len((bboxes))):
st.markdown(f"* Class: {str(category_index[classes[idx]]['name'])}, confidence score: {str(round(scores[idx], 2))}")
packages.txt:
ffmpeg
libsm6
libxext6
requirements.txt:
numpy==1.18.5
opencv-python-h(huán)eadless
Pillow==7.2.0
streamlit
tensorflow==2.3.0
packages.txt和requirements.txt是將安裝在Space中的庫。這些文件非常重要,沒有它們,代碼將無法運(yùn)行。
最后,文件夾應(yīng)該像這樣
saved_model/是你先前從Datature下載的.zip文件中的文件夾
label_map.pbtxt存在于.zip文件
.gitattributes
README.md
app.py是用我在本文前面編寫的代碼創(chuàng)建的文件
requirements.txt在前面的代碼中提供
packages.txt在前面的代碼中提供
一旦我們需要的所有文件都在文件夾中,我們可以將其推送到Space。打開Git Bash,依次粘貼以下命令:
git add .
git commit -m “Added files”
git push
app上傳文件需要一些時間,尤其是模型文件。git推送完成后,Space將花費(fèi)幾分鐘來構(gòu)建應(yīng)用程序,并在Space中顯示我們的應(yīng)用程序。
最后,你的應(yīng)用會顯示如下:https://huggingface.co/spaces/anebz/test
你可以上傳一張圖片,模型需要幾秒鐘來加載,然后你就可以看到預(yù)測結(jié)果了。項(xiàng)目完成了!
結(jié)論
你的項(xiàng)目完成了,祝賀你!你可以從零開始快速創(chuàng)建一個應(yīng)用程序。你只需要在你的電腦上安裝Git,不需要Python或者不需要編寫任何代碼。
原文標(biāo)題 : 構(gòu)建一個計算機(jī)視覺項(xiàng)目
請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
推薦專題
- 1 Intel宣布40年來最重大轉(zhuǎn)型:年底前裁員15000人、拋掉2/3房產(chǎn)
- 2 因美封殺TikTok,字節(jié)股價骨折!估值僅Meta1/5
- 3 宏山激光重磅發(fā)布行業(yè)解決方案,助力智能制造產(chǎn)業(yè)新飛躍
- 4 國產(chǎn)AI芯片公司破產(chǎn)!白菜價拍賣
- 5 具身智能火了,但規(guī)模落地還需時間
- 6 國產(chǎn)英偉達(dá)們,抓緊沖刺A股
- 7 三次錯失風(fēng)口!OpenAI前員工殺回AI編程賽道,老東家捧金相助
- 8 英特爾賦能智慧醫(yī)療,共創(chuàng)數(shù)字化未來
- 9 英偉達(dá)的麻煩在后頭?
- 10 將“網(wǎng)紅”變成“商品”,AI“爆改”實(shí)力拉滿
- 高級軟件工程師 廣東省/深圳市
- 自動化高級工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術(shù)專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結(jié)構(gòu)工程師 廣東省/深圳市