OpenCV4 C++學習 必備基礎語法知識二
點擊上方“小白學視覺”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達
本文轉(zhuǎn)自|OpenCV學堂
前言
之前我寫過一篇介紹學習OpenCV C++一些前置基礎C++11的基礎知識,主要是介紹了輸出打印、各種常見數(shù)據(jù)容器,這里又整理了一篇,主要涉及時間計算與格式化輸出、各種數(shù)據(jù)類型之間的相互轉(zhuǎn)換、簡單的定義方法與泛型方法定義使用。
01
時間計算與轉(zhuǎn)換
很久以前我寫過一篇OpenCV中如何計算程序執(zhí)行時間的文章,這個一直有效,鏈接如下:
https://mp.weixin.qq.com/s/CRzViZv8wY3PQ2uN70AtSA這里我們使用C++11,同樣可以計算,而且C++11還支持各種日期與系統(tǒng)時間的格式化輸出,主要是基于std::chrono包的各種函數(shù)應用,這部分的代碼演示如下:
std::cout << "Hello World, C++" << std::endl;// 毫秒std::chrono::milliseconds ms(3);std::cout << ms.count() << std::endl;// 轉(zhuǎn)換為微秒std::chrono::microseconds us = ms * 2;std::cout << us.count() << std::endl;// 計算執(zhí)行時間auto t1 = std::chrono::system_clock::now();cv::Mat src = cv::imread("D:/images/test.png");cv::Mat gray;cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);auto t2 = std::chrono::system_clock::now();std::cout <<"毫秒數(shù):"<<std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() <<" 微秒數(shù):"<< std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count() <<" 秒數(shù):" << std::chrono::duration_cast<std::chrono::seconds>(t2 - t1).count() << std::endl;// 計算當前時間與日期auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());std::cout << "Current Time: "<<std::put_time(std::localtime(&t), "%Y-%m-%d %H.%M.%S")<< std::endl;
運行結(jié)果如下:

支持毫秒、微秒、秒、支持獲取系統(tǒng)的當前時間等。
02
數(shù)值轉(zhuǎn)換
在OpenCV編程開發(fā)中,有時候會讀取數(shù)據(jù)文件,需要把數(shù)據(jù)從字符(string)類型轉(zhuǎn)為數(shù)值(number)類型,常見的有int、float、double、long等類型與string類型的相互轉(zhuǎn)換,這部分的轉(zhuǎn)換主要依賴函數(shù):
std::to_string 這個是萬能的,我寫出了C#與Java的既視感!
atoi 轉(zhuǎn)化為整數(shù)int類型
atof 轉(zhuǎn)換為浮點數(shù)float類型
代碼演示如下:
// 各種字符與數(shù)值轉(zhuǎn)換
double d = 1.234;
float f = 3.145;
int i = 314;
long l = 22;
std::cout << std::to_string(d) << std::endl;
std::cout << std::to_string(f) << std::endl;
std::cout << std::to_string(i) << std::endl;
std::cout << std::to_string(l) << std::endl;
// 從string到數(shù)值
const char* str1 = "3.2333";
const char* str2 = "5.321";
float f1 = std::atof(str1);
float f2 = std::atof(str2);
float f3 = f1 + f2;
std::cout << f3 << std::endl;
const char* str3 = "100";
const char* str4 = "121";
int i3 = std::atoi(str3) + std::atoi(str4);
std::cout << i3 << std::endl;運行結(jié)果如下:

此外各種數(shù)值類型相互轉(zhuǎn)化,主要依賴static_cast函數(shù),使用如下:
int a1 = 100;
float f8 = 20;
float sum = std::max(static_cast<float>(a1), f8);03
簡單的泛型應用
有時候你看到一些C++的代碼中會有template<typename T>類似的語法,很多小白都直接蒙了,其實這個是現(xiàn)代編譯器支持,各種語言都會有的泛型。說白了就是運行期識別。先定義個,到時候傳什么類型就是什么類型。OpenCV中的圖像數(shù)據(jù)常見支持uchar與float類型操作,我們以此為例定義一個泛型函數(shù),實現(xiàn)浮點數(shù)與字節(jié)類型圖像數(shù)據(jù)的遍歷與操作,方法定義與代碼實現(xiàn)如下:
template <typename T>
void pixel_visit_demo(cv::Mat& src, cv::Mat& dst) {
// 指針讀取
int height = src.rows;
int width = src.cols;
int ch = src.channels();
int blue = 0, green = 0, red = 0;
int gray;
for (int row = 0; row < height; row++) {
T *curr_row = src.ptr<T>(row);
T *result_row = dst.ptr<T>(row);
for (int col = 0; col < width; col++) {
if (ch == 3) {
blue = *curr_row++;
green = *curr_row++;
red = *curr_row++;
*result_row++ = 255 - blue;
*result_row++ = 255 - green;
*result_row++ = 255 - red;
}
else if (ch == 1) {
gray = *curr_row++;
*result_row++ = 255 - gray;
}
}
}
}調(diào)用該方法實現(xiàn)浮點數(shù)與字節(jié)類型的Mat對象操作代碼如下:
// 泛型,處理不同類型的圖像數(shù)據(jù)
imshow("輸入圖像", src);
Mat dst = Mat::zeros(src.size(), src.type());
pixel_visit_demo<uchar>(src, dst);
imshow("result-uchar", dst);
// 處理浮點數(shù)圖像數(shù)據(jù)
src.convertTo(src, CV_32F);
dst.convertTo(dst, CV_32F);
pixel_visit_demo<float>(src, dst);
imshow("result-float", dst/255.0);
waitKey(0);運行結(jié)果如下:

交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學影像、GAN、算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~

