0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

用Inception-v3進行圖像識別的方法

Tensorflowers ? 來源:cg ? 2018-12-31 09:22 ? 次閱讀

對于我們的大腦來說,視覺識別似乎是一件特別簡單的事。人類不費吹灰之力就可以分辨獅子和美洲虎、看懂路標或識別人臉。但對計算機而言,這些實際上是很難處理的問題:這些問題只是看起來簡單,因為大腦非常擅長理解圖像。

在過去幾年內(nèi),機器學習領(lǐng)域在解決此類難題方面取得了巨大進展。尤其是,我們發(fā)現(xiàn)一種稱為深度卷積神經(jīng)網(wǎng)絡(luò)的模型可以很好地處理較難的視覺識別任務(wù) - 在某些領(lǐng)域的表現(xiàn)與人類大腦不相上下,甚至更勝一籌。

研究人員通過用ImageNet(計算機視覺的一種學術(shù)基準)驗證其工作成果,證明他們在計算機視覺方面取得了穩(wěn)步發(fā)展。他們陸續(xù)推出了以下幾個模型,每一個都比上一個有所改進,且每一次都取得了新的領(lǐng)先成果:QuocNet、AlexNet、Inception (GoogLeNet)、BN-Inception-v2。Google 內(nèi)部和外部的研究人員均發(fā)表過關(guān)于所有這些模型的論文,但這些成果仍是難以復(fù)制的?,F(xiàn)在我們將采取后續(xù)步驟,發(fā)布用于在我們的最新模型Inception-v3上進行圖像識別的代碼。

Inception-v3 使用 2012 年的數(shù)據(jù)針對ImageNet大型視覺識別挑戰(zhàn)賽訓練而成。它處理的是標準的計算機視覺任務(wù),在此類任務(wù)中,模型會嘗試將所有圖像分成1000 個類別,如 “斑馬”、“斑點狗” 和 “洗碗機”。例如,以下是AlexNet對某些圖像進行分類的結(jié)果:

為了比較各個模型,我們會檢查正確答案不在模型預(yù)測的最有可能的 5 個選項中的頻率,稱為 “top-5 錯誤率”。AlexNet在 2012 年的驗證數(shù)據(jù)集上實現(xiàn)了 15.3% 的 top-5 錯誤率;Inception (GoogLeNet)、BN-Inception-v2和Inception-v3的 top-5 錯誤率分別達到 6.67%、4.9% 和 3.46%。

人類在 ImageNet 挑戰(zhàn)賽上的表現(xiàn)如何?Andrej Karpathy 曾嘗試衡量自己的表現(xiàn),他發(fā)表了一篇博文,提到自己的 top-5 錯誤率為 5.1%。

教程將介紹如何使用Inception-v3。您將了解如何使用 PythonC++ 將圖像分成1000 個類別。此外,我們還將討論如何從該模型提取更高級別的特征,以重復(fù)用于其他視覺任務(wù)。

我們期待看到社區(qū)會用該模型完成什么任務(wù)。

使用 Python API

首次運行程序時,classify_image.py會從tensorflow.org下載經(jīng)過訓練的模型。您的硬盤上需要有約 200M 的可用空間。

首先,從 GitHub 克隆TensorFlow 模型代碼庫。運行以下命令:

cd models/tutorials/image/imagenetpython classify_image.py

以上命令會對提供的大熊貓圖像進行分類。

如果模型運行正確,腳本將生成以下輸出:

giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca (score = 0.88493)indri, indris, Indri indri, Indri brevicaudatus (score = 0.00878)lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens (score = 0.00317)custard apple (score = 0.00149)earthstar (score = 0.00127)

如果您想提供其他 JPEG 圖像,只需修改--image_file參數(shù)即可。

如果您將模型數(shù)據(jù)下載到其他目錄,則需要使--model_dir指向所使用的目錄。

使用 C++ API

您可以使用 C++ 運行同一Inception-v3模型,以在生產(chǎn)環(huán)境中使用模型。為此,您可以下載包含 GraphDef 的歸檔文件,GraphDef 會以如下方式定義模型(從 TensorFlow 代碼庫的根目錄運行):

curl -L "https://storage.googleapis.com/download.tensorflow.org/models/inception_v3_2016_08_28_frozen.pb.tar.gz" |tar -C tensorflow/examples/label_image/data -xz

接下來,我們需要編譯包含加載和運行圖的代碼的 C++ 二進制文件。如果您按照針對您平臺的說明下載 TensorFlow 源安裝文件,則應(yīng)該能夠通過從 shell 終端運行以下命令來構(gòu)建該示例:

bazel build tensorflow/examples/label_image/...

上述命令應(yīng)該會創(chuàng)建一個可執(zhí)行的二進制文件,然后您可以運行該文件,如下所示:

bazel-bin/tensorflow/examples/label_image/label_image

這里使用的是框架附帶的默認示例圖像,輸出結(jié)果應(yīng)與以下內(nèi)容類似:

I tensorflow/examples/label_image/main.cc:206] military uniform (653): 0.834306I tensorflow/examples/label_image/main.cc:206] mortarboard (668): 0.0218692I tensorflow/examples/label_image/main.cc:206] academic gown (401): 0.0103579I tensorflow/examples/label_image/main.cc:206] pickelhaube (716): 0.00800814I tensorflow/examples/label_image/main.cc:206] bulletproof vest (466): 0.00535088

在本例中,我們使用的是默認的海軍上將格蕾絲·赫柏的圖像,您可以看到,網(wǎng)絡(luò)可正確識別她穿的是軍裝,分數(shù)高達 0.8。

接下來,您可以通過調(diào)整 --image= 參數(shù),用自己的圖像試一試,例如:

bazel-bin/tensorflow/examples/label_image/label_image --image=my_image.png

我們希望此代碼可幫助您將 TensorFlow 集成到您自己的應(yīng)用中,因此我們將逐步介紹主要函數(shù):

命令行標記可控制文件加載路徑以及輸入圖像的屬性。由于應(yīng)向模型輸入 299x299 RGB 的正方形圖像,因此標記input_width和input_height應(yīng)設(shè)成這些值。此外,我們還需要將像素值從介于 0 至 255 之間的整數(shù)縮放成浮點值,因為圖執(zhí)行運算時采用的是浮點數(shù)。我們使用input_mean和input_std標記控制縮放;先用每個像素值減去input_mean,然后除以input_std。

這些值看起來可能有點不可思議,但它們只是原模型作者根據(jù)他 / 她想要用做輸入圖像以用于訓練的內(nèi)容定義的。如果您有自行訓練的圖,只需對值做出調(diào)整,使其與您在訓練過程中使用的任何值一致即可。

您可以參閱ReadTensorFromImageFile()函數(shù),了解這些標記是如何應(yīng)用到圖像的。

首先,我們創(chuàng)建一個GraphDefBuilder對象,它可用于指定要運行或加載的模型。

string input_name = "file_reader"; string output_name = "normalized"; tensorflow::Node* file_reader = tensorflow::ops::ReadFile(tensorflow::ops::Const(file_name, b.opts()), b.opts().WithName(input_name));

然后,為要運行的小型模型創(chuàng)建節(jié)點,以加載、調(diào)整和縮放像素值,從而獲得主模型期望作為其輸入的結(jié)果。我們創(chuàng)建的第一個節(jié)點只是一個Const操作,它會存儲一個張量,其中包含要加載的圖像的文件名。然后,該張量會作為第一個輸入傳遞到ReadFile操作。您可能會注意到,我們將b.opts()作為最后一個參數(shù)傳遞到所有操作創(chuàng)建函數(shù)。該參數(shù)可確保該節(jié)點會添加到GraphDefBuilder中存儲的模型定義中。此外,我們還通過向b.opts()發(fā)起WithName()調(diào)用來命名ReadFile運算符,從而命名該節(jié)點,雖然這不是絕對必要的操作(因為如果您不執(zhí)行此操作,系統(tǒng)會自動為該節(jié)點分配名稱),但確實可簡化調(diào)試過程。

// Now try to figure out what kind of file it is and decode it. const int wanted_channels = 3; tensorflow::Node* image_reader; if (tensorflow::StringPiece(file_name).ends_with(".png")) { image_reader = tensorflow::ops::DecodePng( file_reader, b.opts().WithAttr("channels", wanted_channels).WithName("png_reader")); } else { // Assume if it's not a PNG then it must be a JPEG. image_reader = tensorflow::ops::DecodeJpeg( file_reader, b.opts().WithAttr("channels", wanted_channels).WithName("jpeg_reader")); } // Now cast the image data to float so we can do normal math on it. tensorflow::Node* float_caster = tensorflow::ops::Cast( image_reader, tensorflow::DT_FLOAT, b.opts().WithName("float_caster")); // The convention for image ops in TensorFlow is that all images are expected // to be in batches, so that they're four-dimensional arrays with indices of // [batch, height, width, channel]. Because we only have a single image, we // have to add a batch dimension of 1 to the start with ExpandDims(). tensorflow::Node* dims_expander = tensorflow::ops::ExpandDims( float_caster, tensorflow::ops::Const(0, b.opts()), b.opts()); // Bilinearly resize the image to fit the required dimensions. tensorflow::Node* resized = tensorflow::ops::ResizeBilinear( dims_expander, tensorflow::ops::Const({input_height, input_width}, b.opts().WithName("size")), b.opts()); // Subtract the mean and divide by the scale. tensorflow::ops::Div( tensorflow::ops::Sub( resized, tensorflow::ops::Const({input_mean}, b.opts()), b.opts()), tensorflow::ops::Const({input_std}, b.opts()), b.opts().WithName(output_name));

接下來,我們繼續(xù)添加更多節(jié)點,以便將文件數(shù)據(jù)解碼為圖像、將整數(shù)轉(zhuǎn)換為浮點值、調(diào)整大小,最終對像素值運行減法和除法運算。

// This runs the GraphDef network definition that we've just constructed, and // returns the results in the output tensor. tensorflow::GraphDef graph; TF_RETURN_IF_ERROR(b.ToGraphDef(&graph));

最后,我們獲得一個存儲在變量 b 中的模型定義,并可以使用ToGraphDef()函數(shù)將其轉(zhuǎn)換成一個完整的圖定義。

std::unique_ptr session( tensorflow::NewSession(tensorflow::SessionOptions())); TF_RETURN_IF_ERROR(session->Create(graph)); TF_RETURN_IF_ERROR(session->Run({}, {output_name}, {}, out_tensors)); return Status::OK();

接下來,創(chuàng)建一個tf.Session對象(它是實際運行圖的接口)并運行它,從而指定要從哪個節(jié)點獲得輸出,以及將輸出數(shù)據(jù)存放在什么位置。

這為我們提供了一個由Tensor對象構(gòu)成的向量,在此例中,我們知道它將僅是單個對象的長度。在這種情況下,您可以將Tensor視為多維數(shù)組,它將 299 像素高、299 像素寬、3 通道的圖像存儲為浮點值。如果您的產(chǎn)品中已有自己的圖像處理框架,則應(yīng)該能夠使用該框架,只要在將圖像饋送到主圖之前對其應(yīng)用相同的轉(zhuǎn)換即可。

下面是使用 C++ 動態(tài)創(chuàng)建小型 TensorFlow 圖的簡單示例,但對于預(yù)訓練的 Inception 模型,我們需要從文件中加載更大的定義。您可以查看LoadGraph()函數(shù),了解我們?nèi)绾巫龅竭@一點。

// Reads a model graph definition from disk, and creates a session object you// can use to run it.Status LoadGraph(string graph_file_name, std::unique_ptr* session) { tensorflow::GraphDef graph_def; Status load_graph_status = ReadBinaryProto(tensorflow::Env::Default(), graph_file_name, &graph_def); if (!load_graph_status.ok()) { return tensorflow::errors::NotFound("Failed to load compute graph at '", graph_file_name, "'"); }

如果您已經(jīng)瀏覽圖像加載代碼,則應(yīng)該對許多術(shù)語都比較熟悉了。我們會加載直接包含GraphDef的 protobuf 文件,而不是使用GraphDefBuilder生成GraphDef對象。

session->reset(tensorflow::NewSession(tensorflow::SessionOptions())); Status session_create_status = (*session)->Create(graph_def); if (!session_create_status.ok()) { return session_create_status; } return Status::OK();}

然后,我們從該GraphDef創(chuàng)建一個 Session 對象,并將其傳遞回調(diào)用程序,以便調(diào)用程序稍后可以運行它。

GetTopLabels()函數(shù)很像圖像加載,只是在本例中,我們想要獲取運行主圖得到的結(jié)果,并將其轉(zhuǎn)換成得分最高的標簽的排序列表。與圖像加載器類似,該函數(shù)可創(chuàng)建一個GraphDefBuilder,向其添加幾個節(jié)點,然后運行較短的圖,從而獲取一對輸出張量。在本例中,它們分別表示最高結(jié)果的經(jīng)過排序的得分和索引位置。

// Analyzes the output of the Inception graph to retrieve the highest scores and// their positions in the tensor, which correspond to categories.Status GetTopLabels(const std::vector& outputs, int how_many_labels, Tensor* indices, Tensor* scores) { tensorflow::GraphDefBuilder b; string output_name = "top_k"; tensorflow::ops::TopK(tensorflow::ops::Const(outputs[0], b.opts()), how_many_labels, b.opts().WithName(output_name)); // This runs the GraphDef network definition that we've just constructed, and // returns the results in the output tensors. tensorflow::GraphDef graph; TF_RETURN_IF_ERROR(b.ToGraphDef(&graph)); std::unique_ptr session( tensorflow::NewSession(tensorflow::SessionOptions())); TF_RETURN_IF_ERROR(session->Create(graph)); // The TopK node returns two outputs, the scores and their original indices, // so we have to append :0 and :1 to specify them both. std::vector out_tensors; TF_RETURN_IF_ERROR(session->Run({}, {output_name + ":0", output_name + ":1"}, {}, &out_tensors)); *scores = out_tensors[0]; *indices = out_tensors[1]; return Status::OK();

PrintTopLabels()函數(shù)會采用這些經(jīng)過排序的結(jié)果,并以友好的方式輸出這些結(jié)果。CheckTopLabel()函數(shù)與其極為相似,但出于調(diào)試目的,需確保最有可能的標簽是我們預(yù)期的值。

最后,main()將所有這些調(diào)用綁定在一起。

int main(int argc, char* argv[]) { // We need to call this to set up global state for TensorFlow. tensorflow::port::InitMain(argv[0], &argc, &argv); Status s = tensorflow::ParseCommandLineFlags(&argc, argv); if (!s.ok()) { LOG(ERROR) << "Error parsing command line flags: " << s.ToString();? ? return -1;? }? // First we load and initialize the model.? std::unique_ptr session;? string graph_path = tensorflow::io::JoinPath(FLAGS_root_dir, FLAGS_graph);? Status load_graph_status = LoadGraph(graph_path, &session);? if (!load_graph_status.ok()) {? ? LOG(ERROR) << load_graph_status;? ? return -1;? }

加載主圖

// Get the image from disk as a float array of numbers, resized and normalized // to the specifications the main graph expects. std::vector resized_tensors; string image_path = tensorflow::io::JoinPath(FLAGS_root_dir, FLAGS_image); Status read_tensor_status = ReadTensorFromImageFile( image_path, FLAGS_input_height, FLAGS_input_width, FLAGS_input_mean, FLAGS_input_std, &resized_tensors); if (!read_tensor_status.ok()) { LOG(ERROR) << read_tensor_status;? ? return -1;? }? const Tensor& resized_tensor = resized_tensors[0];

加載、處理輸入圖像并調(diào)整其大小

// Actually run the image through the model. std::vector outputs; Status run_status = session->Run({ {FLAGS_input_layer, resized_tensor}}, {FLAGS_output_layer}, {}, &outputs); if (!run_status.ok()) { LOG(ERROR) << "Running model failed: " << run_status;? ? return -1;? }

在本示例中,我們將圖像作為輸入,運行已加載的圖

// This is for automated testing to make sure we get the expected result with // the default settings. We know that label 866 (military uniform) should be // the top label for the Admiral Hopper image. if (FLAGS_self_test) { bool expected_matches; Status check_status = CheckTopLabel(outputs, 866, &expected_matches); if (!check_status.ok()) { LOG(ERROR) << "Running check failed: " << check_status;? ? ? return -1;? ? }? ? if (!expected_matches) {? ? ? LOG(ERROR) << "Self-test failed!";? ? ? return -1;? ? }? }

出于測試目的,我們可以在下方檢查以確保獲得了預(yù)期的輸出

// Do something interesting with the results we've generated. Status print_status = PrintTopLabels(outputs, FLAGS_labels);

最后,輸出我們找到的標簽

if (!print_status.ok()) { LOG(ERROR) << "Running print failed: " << print_status;? ? return -1;? }

在本示例中,我們使用 TensorFlow 的Status對象處理錯誤,它非常方便,因為通過它,您可以使用ok()檢查工具了解是否發(fā)生了任何錯誤,如果有錯誤,則可以輸出可以讀懂的錯誤消息。

在本示例中,我們演示的是對象識別,但您應(yīng)該能夠?qū)δ诟鞣N領(lǐng)域找到的或自行訓練的其他模型使用非常相似的代碼。我們希望這一小示例可就如何在自己的產(chǎn)品中使用 TensorFlow 為您帶來一些啟發(fā)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 圖像識別
    +關(guān)注

    關(guān)注

    9

    文章

    514

    瀏覽量

    38150
  • 機器學習
    +關(guān)注

    關(guān)注

    66

    文章

    8306

    瀏覽量

    131846

原文標題:如何使用 Inception-v3,進行圖像識別

文章出處:【微信號:tensorflowers,微信公眾號:Tensorflowers】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    使用Python卷積神經(jīng)網(wǎng)絡(luò)(CNN)進行圖像識別的基本步驟

    Python 卷積神經(jīng)網(wǎng)絡(luò)(CNN)在圖像識別領(lǐng)域具有廣泛的應(yīng)用。通過使用卷積神經(jīng)網(wǎng)絡(luò),我們可以讓計算機從圖像中學習特征,從而實現(xiàn)對圖像的分類、識別和分析等任務(wù)。以下是使用 Pytho
    的頭像 發(fā)表于 11-20 11:20 ?4137次閱讀

    基于vuforia的圖像識別Jar的使用

    ,然后上傳需要識別的圖像。點擊Add。圖片上傳過后,服務(wù)器會對圖片的可辨識度進行打分,這個過程需要等候幾分鐘。處理好了以后封面會顯示出剛才上傳的圖像。以及系統(tǒng)對
    發(fā)表于 09-20 11:58

    如何構(gòu)建基于圖像識別的印制線路板精密測試系統(tǒng)?

    如何構(gòu)建基于圖像識別的印制線路板精密測試系統(tǒng)?圖像識別技術(shù)在印刷線路板精密測試中的應(yīng)用
    發(fā)表于 04-27 06:25

    對于圖像識別的引入、原理、過程、應(yīng)用前景的深度剖析

    圖像識別技術(shù)是信息時代的一門重要的技術(shù),其產(chǎn)生目的是為了讓計算機代替人類去處理大量的物理信息。隨著計算機技術(shù)的發(fā)展,人類對圖像識別技術(shù)的認識越來越深刻。圖像識別技術(shù)的過程分為信息的獲取、預(yù)處理、特征
    的頭像 發(fā)表于 12-21 15:01 ?6350次閱讀

    實驗python進行圖像識別的示例代碼資料免費下載

    本文檔的主要內(nèi)容詳細介紹的是實驗python進行圖像識別的示例代碼資料免費下載。
    發(fā)表于 06-14 08:00 ?3次下載

    使用FPGA平臺實現(xiàn)遺傳算法的圖像識別的研究設(shè)計說明

    利用模板匹配方法,采用基于遺傳算法的圖像識別技術(shù),完成了對圖像目標識別的算法驗證。在此基礎(chǔ)上進行了基于該算法的
    發(fā)表于 01-26 15:02 ?13次下載
    使用FPGA平臺實現(xiàn)遺傳算法的<b class='flag-5'>圖像識別的</b>研究設(shè)計說明

    模擬矩陣在圖像識別中的應(yīng)用

    訊維模擬矩陣在圖像識別中的應(yīng)用主要是通過構(gòu)建一個包含多種圖像數(shù)據(jù)的模擬矩陣,來訓練和測試深度學習模型,從而提高圖像識別的準確性和效率。 在圖像識別中,訊維模擬矩陣可以用來做以下幾方面的
    的頭像 發(fā)表于 09-04 14:17 ?477次閱讀
    模擬矩陣在<b class='flag-5'>圖像識別</b>中的應(yīng)用

    一種基于圖像識別的第五版人民幣成色檢測方法

    電子發(fā)燒友網(wǎng)站提供《一種基于圖像識別的第五版人民幣成色檢測方法.pdf》資料免費下載
    發(fā)表于 10-13 11:19 ?0次下載
    一種基于<b class='flag-5'>圖像識別的</b>第五版人民幣成色檢測<b class='flag-5'>方法</b>

    如何使用Python進行圖像識別的自動學習自動訓練?

    如何使用Python進行圖像識別的自動學習自動訓練? 使用Python進行圖像識別的自動學習和自動訓練需要掌握一些重要的概念和技術(shù)。在本文中,我們將介紹如何使用Python中的一些常用
    的頭像 發(fā)表于 01-12 16:06 ?446次閱讀

    圖像識別技術(shù)原理 圖像識別技術(shù)的應(yīng)用領(lǐng)域

    圖像識別技術(shù)是一種通過計算機對圖像進行分析和理解的技術(shù)。它借助計算機視覺、模式識別、人工智能等相關(guān)技術(shù),通過對圖像
    的頭像 發(fā)表于 02-02 11:01 ?1781次閱讀

    圖像檢測和圖像識別的區(qū)別是什么

    圖像檢測和圖像識別是計算機視覺領(lǐng)域的兩個重要研究方向,它們在許多應(yīng)用場景中都有著廣泛的應(yīng)用。盡管它們在某些方面有相似之處,但它們之間還是存在一些明顯的區(qū)別。本文將從多個角度對圖像檢測和圖像識別
    的頭像 發(fā)表于 07-03 14:41 ?483次閱讀

    圖像識別屬于人工智能嗎

    屬于。圖像識別是人工智能(Artificial Intelligence, AI)領(lǐng)域的一個重要分支。 一、圖像識別概述 1.1 定義 圖像識別是指利用計算機技術(shù)對圖像中的內(nèi)容
    的頭像 發(fā)表于 07-16 10:44 ?499次閱讀

    圖像識別技術(shù)的原理是什么

    圖像識別技術(shù)是一種利用計算機視覺和機器學習技術(shù)對圖像進行分析和理解的技術(shù)。它可以幫助計算機識別和理解圖像中的對象、場景和活動。
    的頭像 發(fā)表于 07-16 10:46 ?593次閱讀

    圖像識別算法都有哪些方法

    圖像識別算法是計算機視覺領(lǐng)域的核心任務(wù)之一,它涉及到從圖像中提取特征并進行分類、識別和分析的過程。隨著深度學習技術(shù)的不斷發(fā)展,圖像識別算法已
    的頭像 發(fā)表于 07-16 11:14 ?3859次閱讀

    圖像檢測和圖像識別的原理、方法及應(yīng)用場景

    圖像檢測和圖像識別是計算機視覺領(lǐng)域的兩個重要概念,它們在許多應(yīng)用場景中發(fā)揮著關(guān)鍵作用。 1. 定義 1.1 圖像檢測 圖像檢測(Object Detection)是指在
    的頭像 發(fā)表于 07-16 11:19 ?1384次閱讀