本期將帶大家帶來一期可以稱作番外篇的一期:暫且稱為OpenCV實戰篇,將介紹OpenCV的一些基礎使用方法,以及在MCU上實際運行起來的效果。
首先是OpenCV的簡單介紹,前面的文章已經介紹過,OpenCV具有模塊化的結構,這意味著其中包含了多種共享/靜態庫,概括如下:
-
Image Processing:包含了多種線性/非線性的圖像濾波器,幾何圖像變換等
-
Video:視頻處理模塊,包括運動估計,背景減除等
-
Calib3d:單目/雙目相機支持,3D重建等
-
Features2D:特征檢測
-
Objdetect:目標檢測等,例如人臉、眼睛等
-
Highgui:簡單的UI功能
-
Video I/O:視頻編解碼接口
所有的OpenCV類/函數都被歸在cv命名空間下。因此,應用層想要訪問任何代碼都需要使用cv::限定符或是直接使用using namespace cv,例如:
cv::Mat H = cv::findHomography(points1, points2, CV_RANSAC, 5);
或是:
using namespace cv;
Mat H = findHomography(points1, points2, CV_RANSAC, 5 );
同時,由于當前或是之后的OpenCV源碼中導出的外部符號,可能會和STL或是其他庫中的名字沖突。這就建議用戶在使用時,要顯示指定已避免沖突,例如:
Mat a(100, 100, CV_32F);
randu(a, Scalar::all(1), Scalar::rand()));
cv::log(a, a);
a /= std::log(2.);
接下來要講的是一個OpenCV中的重要結構Mat。
如果你想要使用OpenCV的話,Mat是你無論如何躲不過的一步。通俗點講,這個結構體代表了一種n維數組,并且能夠抽象表達成矩陣/圖像/光流圖等。
其公共屬性如下:
attribute
|
description
|
MatAllocator* allocator
|
Custom allocator
|
int cols
|
The image’s width
|
int rows
|
The image’s height, the cols & rows will be (-1, -1) when the matrix has more than 2 dimensions
|
uchar* data
|
Pointer to the data
|
uchar* dataend
|
-
|
uchar* datalimit
|
-
|
uchar* datastart
|
-
|
int dims
|
The matrix dimensionality, >=2
|
int flags
|
-
|
int* refcount
|
Pointer to the reference counter
|
MSize size
|
-
|
MSize step
|
-
|
作為一個名副其實的C++類,OpenCV為其編寫了多種構造函數,這也使得有多種方式能夠創建一個cv::Mat對象,用的比較多的幾種方式如下:
1.使用cv::Create(nrows, ncols, type) 或是 cv::Mat(nrows, ncols, type[, fill,_vale])如有雷同,那必然不是巧合。
// make 7x7 complex matrix filled with 1+3j.
cv::Mat M(7,7,CV_32FC2,Scalar(1,3));
// and now turn M to 100x60 15-channel 8-bit matrix.
// The old content will be deallocated
M.create(100,60,CV_8UC(15));
2.使用拷貝構造函數,時間復雜度為O(1),因為這種方式將只拷貝header并增加引用計數,數據部分將公用,也稱作淺拷貝。當然也可以使用深拷貝,cv::clone()可以做到這一點。
3.僅構造頭部,并使用用戶預分配數據:
void init_mat_with_ptr(const unsigned char* pixels,
int width, int height, int step)
{
cv::Mat img(height, width, CV_8UC3, pixels, step);
cv::GaussianBlur(img, img, cv::Size(7,7), 1.5, 1.5);
}
4.使用MATLAB格式的矩陣初始化法,cv::zeros(), cv::ones(), cv::eye()
5.對象與數據空間的釋放:cv::release()
了解了OpenCV的基礎知識,下面是基于MCUXPresso的代碼實測部分。這里我們基于SDK中的“Hello World”工程搭建我們的第一個OpenCV代碼。小編先賣個關子,詳細的工程配置方法將在下期為大家揭秘。
首先,要選取測試圖,小編隨便在手機里找了一張圖片并裁成500*500的jpg圖像,之后會對其進行解碼隨后將其放縮成(320, 240)。
為了方便我們在沒有文件系統的MCU平臺使用測試圖像,需要借助一條匯編指令.incbin, 并且聲明兩個全局符號告訴代碼數據位置:
.global img_start
.global img_end
img_start:
.incbin "data/picture.jpg"
img_end:
接下來是main函數:
// decode the image
std::vector data(img_start, img_start + IMG_LEN);
cv::Mat img_encode(data);
cv::Mat img = cv::imdecode(img_encode, cv::IMREAD_UNCHANGED);
// resize the decoded imagecv::Mat resizeImg;
cv::resize(img, resizeImg, cv::Size(320, 240), cv::INTER_LINEAR);
編譯下載后,讓我們看看轉出的數據是不是正確,我們就需要將數據傳輸到PC上進行驗證:
1.在MCUXpresso IDE中添加一個memory窗口并且鍵入resizeImage.data:
2. 點擊Export,輸入起止地址,IDE會自動計算長度。選擇保存類型為RAW Binary, 并選擇本地保存位置
3.點擊OK下載數據
4. 為了驗證數據的準確性,我們直接編寫一個簡單的上位機OpenCV的基于Python的預覽程序,代碼中的文件名對應第2步保存的文件:
import numpy as np
import cv2 as cv
img_raw_data = np.fromfile(“your_path/your_file_name.bin”, dtype=”uint8”)
img = np.reshape(img_raw_data, (240, 320, 3)) # the new shape
cv.imshow(“img”, img)
cv.waitKey(0)
注意:這里假設電腦上已經安裝了Python,并且安裝了numpy以及opencv代碼庫
5. 程序執行之后,讓我們看看最終結果:
至此,我們就用了一個簡單的代碼驗證了我們所編譯的OpenCV庫的正確性。下期小編將為大家揭秘,如何從0開始構建一個完整的OpenCV測試例程。
審核編輯:郭婷
-
C++
+關注
關注
22文章
2110瀏覽量
73685 -
OpenCV
+關注
關注
31文章
635瀏覽量
41373
原文標題:這個秋天,OpenCV和MCU更配喲(實戰篇)
文章出處:【微信號:NXP_SMART_HARDWARE,微信公眾號:恩智浦MCU加油站】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論