RoBoard魔人的機器人日誌

2019/5/9

[Jetson Nano] 自己寫一個圖像識別程式

大家好,

今天本魔要繼續和大家分享如何自己寫一個圖像識別程式,

上一篇我們已經用官方的範例做出分類辨識的效果了,

今天要來做一個更完整的辨識程式,

首先打開 Terminal 視窗並輸入:


$ mkdir ~/my-recognition
$ cd ~/my-recognition
$ touch my-recognition.cpp
$ touch CMakeLists.txt
完成後你會看到家目錄下多了一個 my-recognition 資料夾,

並且裡面有 my-recognition.cpp 與 CMakeLists.txt,

如下圖:


接著我們下載一些官方提供的範例圖片:

$ wget https://github.com/dusty-nv/jetson-inference/raw/master/data/images/black_bear.jpg 
$ wget https://github.com/dusty-nv/jetson-inference/raw/master/data/images/brown_bear.jpg
$ wget https://github.com/dusty-nv/jetson-inference/raw/master/data/images/polar_bear.jpg 
完成後會多出三張圖:


接著可以來寫程式囉!

用 gedit 來開啟 my-recognition.cpp 編輯:
$ gedit my-recognition.cpp

接著在 貼上下面的程式:

// include imageNet header for image recognition
#include 

// include loadImage header for loading images
#include 

// main entry point
int main( int argc, char** argv )
{
 // a command line argument containing the image filename is expected,
 // so make sure we have at least 2 args (the first arg is the program)
 if( argc < 2 )
 {
  printf("my-recognition:  expected image filename as argument\n");
  printf("example usage:   ./my-recognition my_image.jpg\n");
  return 0;
 }

 // retrieve the image filename from the array of command line args
 const char* imgFilename = argv[1];

 // these variables will be used to store the image data and dimensions
 // the image data will be stored in shared CPU/GPU memory, so there are
 // pointers for the CPU and GPU (both reference the same physical memory)
 float* imgCPU    = NULL;    // CPU pointer to floating-point RGBA image data
 float* imgCUDA   = NULL;    // GPU pointer to floating-point RGBA image data
 int    imgWidth  = 0;       // width of the image (in pixels)
 int    imgHeight = 0;       // height of the image (in pixels)
  
 // load the image from disk as float4 RGBA (32 bits per channel, 128 bits per pixel)
 if( !loadImageRGBA(imgFilename, (float4**)&imgCPU, (float4**)&imgCUDA, &imgWidth, &imgHeight) )
 {
  printf("failed to load image '%s'\n", imgFilename);
  return 0;
 }

 // load the GoogleNet image recognition network with TensorRT
 // you can use imageNet::ALEXNET to load AlexNet model instead
 imageNet* net = imageNet::Create(imageNet::GOOGLENET);

 // check to make sure that the network model loaded properly
 if( !net )
 {
  printf("failed to load image recognition network\n");
  return 0;
 }

 // this variable will store the confidence of the classification (between 0 and 1)
 float confidence = 0.0;

 // classify the image with TensorRT on the GPU (hence we use the CUDA pointer)
 // this will return the index of the object class that the image was recognized as (or -1 on error)
 const int classIndex = net->Classify(imgCUDA, imgWidth, imgHeight, &confidence);


 // make sure a valid classification result was returned 
 if( classIndex >= 0 )
 {
  // retrieve the name/description of the object class index
  const char* classDescription = net->GetClassDesc(classIndex);

  // print out the classification results
  printf("image is recognized as '%s' (class #%i) with %f%% confidence\n", 
     classDescription, classIndex, confidence * 100.0f);
 }
 else
 {
  // if Classify() returned < 0, an error occurred
  printf("failed to classify image\n");
 }

 // free the network's resources before shutting down
 delete net;

 // this is the end of the example!
 return 0;
}



簡單的說明一下這段程式在做些什麼,

首先用第二個引數來讀取圖片,然後載入圖像辨識網路 (GOOGLENET),

接著會將載入的圖片做分類與看相似度,

最後將結果輸出至銀幕上。

接著我們要寫 CMakeLists.txt,一樣用 gedit 來開啟 CMakeLists.txt 編輯:
$ gedit CMakeLists.txt
接著貼上:

# require CMake 2.8 or greater
cmake_minimum_required(VERSION 2.8)

# declare my-recognition project
project(my-recognition)

# import jetson-inference and jetson-utils packages.
# note that if you didn't do "sudo make install"
# while building jetson-inference, this will error.
find_package(jetson-utils)
find_package(jetson-inference)

# CUDA and Qt4 are required
find_package(CUDA)
find_package(Qt4)

# setup Qt4 for build
include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})

# compile the my-recognition program
cuda_add_executable(my-recognition my-recognition.cpp)

# link my-recognition to jetson-inference library
target_link_libraries(my-recognition jetson-inference)



完成後就可以編譯囉!輸入:

$ cd ~/my-recognition
$ cmake .
$ make
完成後就可以執行程式來進行辨識啦!

輸入:
$ ./my-recognition polar_bear.jpg

輸出結果 ice bear、polar bear 是北極熊無誤!

輸入:
$ ./my-recognition brown_bear.jpg


結果是 brown bear 棕熊無誤。

輸入:
$ ./my-recognition black_bear.jpg


結果是 American black bear 美國黑熊,「真的假的?連國家都辨識的出來阿?」

玩到這裡同事 Vic 忽然說,該不會它只能辨識這些官方圖片吧?

所以本魔就上網找了一隻猴子,畢竟也是有毛髮的動物,到底有沒有辦法辨別呢?


結果是 guenon monkey 正確,本魔找的時候不知道牠的品種是長尾猴呢!

結果 Vic 不信邪說了:「該不會檔名會影響它的辨識吧?」

所以本魔又找了一張金剛的圖片,並將檔名存為 aaa.jpg,


結果是 gorilla 大猩猩,本魔還以為會辨識出 King kong 呢!

上網查了一下,原來金剛就是大猩猩,只是金剛是通俗的講法,

所以還是算辨識正確!



本篇的教學就到此為止啦~,

各位一樣可以嘗試用其它圖片來測試看看哦!

喜歡這個系列的話可以追蹤我的blogger哦,

本魔近期都會不定時更新此系列教學,

如果有疑問或任何指教也歡迎在下方留言提出哦!
Share:

3 則留言:

技術提供:Blogger.

追蹤者