iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 14
0
Software Development

Emacs 來寫程式系列 第 14

[Emacs-14] 用 Emacs 來寫 C/C++ 的 OpenCV 程式

使用 Emacs 的 C/C++ 套件來寫 OpenCV

我們前ㄧ篇已經設定好了 Emacs 編輯 C/C++ 的程式,這裏我們用一個例子來看如何使用 irony, rtags, clang-format 套件來支援 C/C++ 程式的編輯。

我們用一個現成的函式庫 OpenCV 來做一個小小的程式,這個簡化的程式會讀進一個影像,判別影像中人臉的位置,並用框框標示出來。完成如圖 Imgur

安裝 OpenCV 的部分,請參考我的部落格,或者簡報

irony 補全 C/C++ 標頭檔資訊

  • 啟動 Emacs,建立一個新的目錄,用 Ctrl-x Ctrl-f 開啟一個新的檔案 detectface.cpp
  • 開始 C/C++ 的 #inc,這時會啟動 Emacs 的 company-irony 程式自動補全 Imgur,檢查一下 Meta-x company-diag Imgur,Emacs 使用 company 套件來做程式補全,詳情請看前面 company的介紹
  • 選擇 #include ""enter,打入 #include "ope"irony會把相關的函式庫列出 Imgur
  • 選擇 #include "opencv2/" 在打入 opencv2/o irony 會把相關的標頭檔列出 Imgur

irony 補全 C/C++ 類別,語法檢查,程式自動美化編排

  • 先使用 yasnippet 的 main snippet 展開 Imgur
  • 使用 Meta-x yas-describe-table 可以看 C++ 模式下定義的程式片段 (snippets) Imgur 這些程式片段可以在打完關鍵字後按 Tab 鍵展開,詳情請看前面的文章 yasnippet
  • 接著我們來產生一些 OpenCV 的物件,當打入 cv::Ca 時, company-irony 會帶出 cv相關的類別跟類別方法,Imgur
  • 可以使用前面設定的 rtags,來跳到類別的定義,將游標移動到 cv::CascadeClassifier,按 Meta .,即可跳到它的定義檔 Imgur,按一次 Meta , 顯示有多少目前的函式使用到這個類別,選擇後跳回
  • 一般的類別當然也支援,打入 std::stri ,相關的函式跟類別都會展出 Imgur
  • 如果有語法錯誤,緩衝區會顯示明顯顏色來標示,我們使用 flycheck 做語法檢查,按 Ctrl-x ! l 來顯示錯誤跟警示 Imgur
  • 顯示 flycheck 的設定,按 Ctrl-x ! vImgur ,現在的 C++ 模式下,會使用 flycheck-irony 因為前一篇的設定 之前的文章已經介紹過如何使用 flycheck
  • 當編輯的檔案格式混亂時,如圖 Imgur
  • 在按 Ctrl-x Ctrl-s 儲存後,格式自動排定 Imgur 因為使用了 clang-format 設定在儲存時會自動編排美化程式
  • company-irony 也會自動完成物件的方法,例如 Imgur

完整程式

完成的程式如下

#include "opencv2/opencv.hpp"

int main(int argc, char *argv[]) {
  cv::CascadeClassifier cascade;
  std::string imageName, cascadeName;
  cv::Mat image, gray;
  std::vector<cv::Rect> faces;
  cv::Scalar color = cv::Scalar(0, 255, 0);

  cascadeName = "./haarcascade_frontalface_default.xml";
  imageName = argv[1];

  // load image and classifier
  if (!cascade.load(cascadeName)) {
    std::cerr << "Could not load classifier cascade" << std::endl;
  } else if (imageName.empty()) {
    std::cout << "Could not read " << imageName << std::endl;
  } else {
    image = cv::imread(imageName, 1);
    if (image.empty()) {
      std::cout << "Could not imread image " << std::endl;
    }
  }

  // convert to grey
  cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

  // run face detector
  cascade.detectMultiScale(image, faces, 1.1, 2, 0, cv::Size(30, 30));

  // output rectangle
  for (size_t i = 0; i < faces.size(); ++i) {
    cv::Rect r = faces[i];
    cv::rectangle(
        image, cv::Point(cvRound(r.x), cvRound(r.y)),
        cv::Point(cvRound(r.x + r.width - 1), cvRound(r.y + r.height - 1)),
        color, 3, 8, 0);
  }
  // show image
  cv::imshow("result", image);
  cv::waitKey(0);
  cv::destroyAllWindows();
  return 0;
}

建立 CMakeLists.txt

我們使用 cmake 來編譯程式,因為已經設定了 cmake-mode 使用 company-cmake,Emacs 有最簡單的補全支援 Imgur

CMakeLists.txt 如下

#cmake need this
cmake_minimum_required(VERSION 3.1)

#Enable C++ 11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

#Define project name
project(detectface)

#find OpenCV
find_package(OpenCV REQUIRED)

#If package found, several variable will be set
message(STATUS "OpenCV libray status: ")
message(STATUS "   config: ${OpenCV_DIR}")
message(STATUS "   version: ${OenCV_VERSION}")
message(STATUS "   libraries: ${OpenCV_LIBS}")
message(STATUS "   include path: ${OpenCV_INCLUDE_DIRS}")

#declare executable target build from sources
add_executable(facedetect facedetect.cpp)

#link app to OpenCV lib
target_link_libraries(facedetect ${OpenCV_LIBS})

編譯程式

使用之前介紹過的 Projectile 來編譯專案,按 Ctrl-c p c 來做編譯,請事先先用 之前介紹的 Emacs Git 介面 Magit 建立專案

  • 先建立一個子目錄 build
  • 使用 Ctrl-c p c 打入 cd ~/xxx/build && cmake .. mgur
  • 完成指令Imgur
  • 建立 Makefile 及相關檔案 Imgur
  • 需要事先將 haarcascade_frontalface_default.xml 跟影像檔 harry-meghan-15.jpg 放入這個子目錄下
  • 實際編譯,再按一次 Ctrl-c p c 打入 cmake --build ~/xxx/build
  • 編譯成功 Imgur
  • command line 或者 Meta-x shell 下執行 ./facedetect harry-meghan-15.jpg
  • 成功如圖 Imgur

我們介紹了如何使用 Emacs 編輯 C/C++ 的程式,其中使用了之前介紹過的 company, yasnippet, flycheck, Magit, Projectile 等工具,如果不熟悉的話,建議可以再看一次,因為之後其他模式也會一直使用這些套件

如果要跟著影片的話,請看

相關簡報
相關程式,請看 Github
請參考我的部落格


上一篇
[Emacs-13] 用 Emacs 寫 C/C++ 設定篇
下一篇
[Emacs-15] 用 Emacs 來寫 Python 設定篇
系列文
Emacs 來寫程式30

尚未有邦友留言

立即登入留言