OpenCV4,5个方法让你从小白到大佬
目录
1、简介
2、使用auto关键字,避免过长类型变量声明
3、使用std::vector,
4、学会使用字符串流
5、最后一个是学会使用map容器
关注苏州程序大白,持续更新技术分享。谢谢大家支持
目录
1、简介
我之前在群里看到好多朋友halcon转opecv的学习都很难的。今天我给大家讲讲。学习C++版本的OpenCV会很难,是否需要基础知识。其实这里大家有个很深的误解,OpenCV早期的语法都是基于C++98,这个语法比较坑,让大家学习起来感觉很难。但是后来OpenCV3之后,特别是OpenCV4以来早就支持标准的C++11语法了,很多接口跟函数都特别容易理解,C++11可以说应用最广泛的C++标准之一了,语法通俗易懂,大量智能指针加持,支持各种标准容器操作,可以说跟C#与Java这样的面向对象语言的语法基本完全类似,可以让你轻松驾驭,只要你接触过面向对象的编程语言,可以说零基础学习OpenCV C++完全不是问题,当然有几个最常用的语法跟容器可能需要提前铺垫一下,我这里也从实际项目跟代码实践总结出下面C++基础知识点,帮助大家在学习OpenCV C++的时候可以更快,更好的入门。
下面我们做代码演示如下:
// 输出与打印字符串与数字 std::cout << "Hello World, OpenCV" << cv::getVersionMajor()<<"."<<cv::getVersionMinor()<<std::endl; // 打印Mat矩阵 cv::Mat m1 = cv::Mat(3, 3, CV_8UC1); std::cout <<"m1=" <<m1 << std::endl;
运行结果如下:
2、使用auto关键字,避免过长类型变量声明
C++11支持auto关键字推导,这个可以避免很多不必要的书写,提供代码编写效率。提升代码的整洁跟优雅度,是个很好用的关键字。代码演示如下:
// 使用auto关键字,实现自动类型推导与识别 auto t1 = 3; // 推导为int类型 auto t2 = 3.0; // 推导为double // 推导为cv::Mat类型 auto m2 = cv::Mat(3, 3, CV_8UC1); // 直接用auto避免类型书写 // cv::Ptr<ORB> orb_detecto = cv::ORB::create(); auto orb_detecto = cv::ORB::create();
特别注意:auto不能作为函数参数!
3、使用std::vector,
这个在OpenCV的程序中被大量使用,特别是在二值图像分析,特征提取等模块中,所以掌握vector容器的语法跟函数操作很重要。代码演示部分比较长,涉及到vector容器的定义初始化、添加元素、排序、几种循环fectch方式,删除元素、合并多个vector为一个等。全部的代码演示如下:
// 使用数组容器 - 直接定义 std::vector<int> a; // 初始化定义 std::vector<int> b{ 3,2,1,4,6,5,9,8,7 }; // 循环fetch元素 for (auto i : b) { std::cout <<"for-loop方式"<< i << std::endl; } // 迭代器方式fetch元素 for (auto it = std::begin(b); it != std::end(b); ++it) { std::cout << "迭代器方式: " << *it << std::endl; } // for-each方式 std::for_each(std::begin(b), std::end(b), process); // 容器合并 a.push_back(22); a.push_back(11); b.insert(b.end(), a.begin(), a.end()); std::cout << "打印合并之后的数组:" << std::endl; for (auto ab : b) { std::cout << ab <<" " ; } std::cout << " " << endl; // 排序 std::sort(b.begin(), b.end()); std::cout << "打印排序之后的数组:" << std::endl; for (auto ab : b) { std::cout << ab << " "; } std::cout << " " << endl; // 保留前面N个 auto n = 5; b.erase(b.begin() + n, b.begin() + b.size()); for (auto ab : b) { std::cout <<"打印删除后的剩余元素: "<< ab << std::endl; }
运行结果如下:
4、学会使用字符串流
std::stringstream是一个非常有用的格式化输出,在OpenCV中如何什么想输出的数据类型从int\float\double\string都可以往里面扔,拼接在一起,最后只要调用一下str()方法就会全部转换为str,可以输出到图像,文本、控制台上,非常的方便。特别是通过putText输出到图像上。代码演示如下:
// 字符串流,任意拼接 std::stringstream ss; ss << "Hello World, " << "OpenCV"; auto version = 4.5; ss << version; cv::putText(image, ss.str().c_str(), cv::Point(20, 50), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0, 0, 255), 2, 8); cv::imshow("图像", image);
运行结果如下:
5、最后一个是学会使用map容器
这个在OpenCV与OpenVINO中被大量使用,OpenVINO的输入与输出信息格式就是这种map对象,代码演示了map对象的添加与循环fetch元素的方式,演示代码如下:
// map对象实现key-value操作 std::map<int, std::string> labels; labels.insert(std::pair<int, std::string>(0, "background")); labels.insert(std::pair<int, std::string>(1, "person")); labels.insert(std::pair<int, std::string>(2, "car")); labels.insert(std::pair<int, std::string>(3, "road")); // 获取map对象, for-loop方式 std::cout << "map对象循环,for-loop方式" << std::endl; for (auto item : labels) { std::cout << item.first << ","<<item.second <<std::endl; } // 获取map对象, 迭代器方式 std::cout << "map对象循环,迭代器方式" << std::endl; for (auto it = labels.begin(); it != labels.end(); ++it) { std::cout << it->first << "," << it->second << std::endl; }
运行结果如下: