技术标签: 学习 c++ 笔记 计算机视觉 OpenCV学习 opencv
参考引用
说明
- 本书结合 C++ 和 OpenCV 3.2 全面讲解计算机视觉编程
- 所有代码均在 Ubuntu 系统中用 g++ 编译执行
// loadDisplaySave.cpp
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
/*** 在图像上点击(让鼠标在置于图像窗口上时运行特定的指令)***/
/*
定义一个回调函数 onMouse,回调函数不会被显式地调用,在响应特定事件时被程序调用
参数一:触发回调函数的鼠标事件的类型
参数二、三:事件发生时鼠标的位置,用像素坐标表示
参数四:表示事件发生时按下了鼠标的哪个键
参数五:指向任意对象的指针,作为附加的参数发送给函数
*/
void onMouse(int event, int x, int y, int flags, void* param) {
// reinterpret_cast 用于将任意类型的指针转换为其他类型的指针
// 将一个 void* 类型的指针转换成了一个 cv::Mat* 类型的指针
// 并将其赋值给了变量 im,这样就可以通过 im 来访问 cv::Mat 对象
cv::Mat *im = reinterpret_cast<cv::Mat*>(param);
switch (event) {
// 调度事件
case cv::EVENT_LBUTTONDOWN: // 鼠标左键按下事件
// 显示像素值(x, y)
std::cout << "at (" << x << "," << y << ") value is: "
<< static_cast<int>(im->at<uchar>(cv::Point(x,y))) << std::endl;
break;
}
}
int main(int argc, char *argv[]) {
// cv::Mat 是 OpenCV 定义的用于表示任意维度的稠密数组,OpenCV 使用它来存储和传递图像
cv::Mat image; // 创建一个尺寸为 0 × 0 空图像
std::cout << "This image is " << image.rows << " x " << image.cols << std::endl;
// 读入一个图像文件并将其转换为灰度图像
// 这样生成的图像由无符号字节构成,在 OpenCV 中用常量 CV_8U 表示
image = cv::imread("puppy.bmp", cv::IMREAD_GRAYSCALE);
/* 读取图像,并将其转换为三通道彩色图像
这样创建的图像中,每个像素有 3 字节,OpenCV 中用 CV_8UC3 表示
image = cv::imread("puppy.bmp", cv::IMREAD_COLOR);
*/
if (image.empty()) {
// 如果没有分配图像数据,empty 方法将返回 true
std::cout << "Error reading image..." << std::endl;
return 0;
}
std::cout << "This image is " << image.rows << " x " << image.cols << std::endl;
// 使用 channels 方法检查图像的通道数
std::cout << "This image has " << image.channels() << " channel(s)" << std::endl;
cv::namedWindow("Original Image"); // 定义窗口(可选)
cv::imshow("Original Image", image); // 显示图像
// 回调函数注册
// 函数 onMouse 与 Original Image 图像窗口建立关联,同时把所显示图像的地址作为附加参数传给函数
cv::setMouseCallback("Original Image", onMouse, reinterpret_cast<void*>(&image));
cv::Mat result; // 创建另一个空的图像
cv::flip(image, result, 1); // 正数 1 表示水平翻转,0 表示垂直翻转,负数表示水平和垂直翻转
// cv::flip(image, image, 1); // 对输入图片就地处理,直接写入原图像
cv::namedWindow("Output Image");
cv::imshow("Output Image", result);
cv::waitKey(0); // 0 表示永远的等待按键,键入的正数表示等待的毫秒数
cv::imwrite("output.bmp", result); // 保存结果
// 在图像上绘图(必须包含头文件 imgproc.hpp)
cv::namedWindow("Drawing on an Image");
// 目标图像,中心点坐标,半径,颜色,厚度
cv::circle(image, cv::Point(155, 110), 65, 0, 3);
// 目标图像,文本,文本位置,字体类型,字体大小,字体颜色,字体厚度
cv::putText(image, "This is a dog.", cv::Point(40, 200),
cv::FONT_HERSHEY_PLAIN, 2.0, 255, 2);
cv::imshow("Drawing on an Image", image);
cv::waitKey(0);
return 0;
}
# 编译并执行
# 若版本为 OpenCV4.x,则最后改为 opencv4
$ g++ loadDisplaySave.cpp -o test1 `pkg-config --cflags --libs opencv`
$ ./test1
# 控制台输出
This image is 0 x 0
This image is 213 x 320
This image has 1 channel(s)
// mat.cpp
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
// 测试函数,它创建一幅图像
cv::Mat function() {
cv::Mat ima(500, 500, CV_8U, 50); // 创建图像
return ima; // 返回图像
}
int main(int argc, char *argv[]) {
// 创建一个 240 行 × 320 列的新图像
// CV_8U 表示每个像素对应 1 字节(灰度图像),U 表示无符号
// cv::Size 结构包含了矩阵高度和宽度,同样可以提供图像的尺寸信息
cv::Mat image1(240, 320, CV_8U, 100);
// cv::Mat image1(cv::Size(240, 320), CV_8UC3);
cv::imshow("Image", image1);
cv::waitKey(0);
// 随时可以用 create 方法分配或重新分配图像的数据块
// 如果新的尺寸和类型与原来的相同,就不会重新分配内存
image1.create(200, 200, CV_8U);
image1 = 200;
cv::imshow("Image", image1);
cv::waitKey(0);
// 创建一个红色的图像 (通道次序为 BGR)
// 数据结构 cv::Scalar 用于在调用函数时传递像素值
cv::Mat image2(240, 320, CV_8UC3, cv::Scalar(0, 0, 255));
cv::imshow("Image", image2);
cv::waitKey(0);
// 读入一幅图像
cv::Mat image3 = cv::imread("puppy.bmp");
// 所有这些图像都指向同一个数据块,通过 cv::Mat 实现计数引用和浅复制
// 只有当图像的所有引用都将释放或赋值给另一幅图像时,内存才会被释放
cv::Mat image4(image3);
image1 = image3;
// 这些图像是源图像的副本图像
// 1. 如果要对图像内容做一个深复制,可以使用 copyTo 方法
image3.copyTo(image2);
// 2. 另一个生成图像副本的方法是 clone
cv::Mat image5 = image3.clone();
// 转换图像进行测试
cv::flip(image3, image3, 1);
// 检查哪些图像在处理过程中受到了影响
cv::imshow("Image 3", image3);
cv::imshow("Image 1", image1);
cv::imshow("Image 2", image2);
cv::imshow("Image 4", image4);
cv::imshow("Image 5", image5);
cv::waitKey(0);
// 从函数中获取一个灰度图像
// 运行这条语句后,就可用变量 gray 操作由 function 函数创建的图像,而不需要额外分配内存
cv::Mat gray = function();
cv::imshow("Image", gray);
cv::waitKey(0);
// 作为灰度图像读入
image1 = cv::imread("puppy.bmp", CV_LOAD_IMAGE_GRAYSCALE);
// 如果要把一幅图像复制到另一幅图像中,且两者的数据类型不相同,那就使用 convertTo 方法
// 转换成浮点型图像 [0,1],这两幅图像的通道数量必须相同
image1.convertTo(image2, CV_32F, 1/255.0, 0.0); // 两个可选参数:缩放比例、偏移量
cv::imshow("Image", image2);
// 3×3 双精度型矩阵
cv::Matx33d matrix(3.0, 2.0, 1.0,
2.0, 1.0, 3.0,
1.0, 2.0, 3.0);
// 3×1 矩阵(即向量)
cv::Matx31d vector(5.0, 1.0, 3.0);
cv::Matx31d result = matrix * vector;
std::cout << result;
cv::waitKey(0);
return 0;
}
# 编译并执行
# 若版本为 OpenCV4.x,则最后改为 opencv4
$ g++ mat.cpp -o test2 `pkg-config --cflags --libs opencv`
$ ./test2
# 控制台输出
[20;
20;
16]
class Test {
// 图像属性
cv::Mat ima;
public:
// 在构造函数中创建一幅灰度图像
Test() : ima(240, 320, CV_8U, cv::Scalar(100)) {
}
// 用这种方法返回一个类属性,这是一种不好的做法
cv::Mat method() {
return ima;
}
};
由于图像和 ROI 共享了同一块图像数据,因此 ROI 的任何转变都会影响原始图像的相关区域
// logo.cpp
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
int main(int argc, char *argv[]) {
cv::namedWindow("Image");
cv::Mat image = cv::imread("puppy.bmp");
cv::Mat logo = cv::imread("smalllogo.png");
// 在图像的右下角定义一个 ROI
// image 是目标图像, logo 是标志图像
cv::Mat imageROI(image, cv::Rect(image.cols - logo.cols, // ROI 坐标
image.rows - logo.rows,
logo.cols, logo.rows)); // ROI 大小
/*imageROI = image(cv::Range(image.rows-logo.rows,image.rows),
cv::Range(image.cols-logo.cols,image.cols));*/
logo.copyTo(imageROI); // 插入标志
cv::imshow("Image", image);
cv::waitKey(0);
image = cv::imread("puppy.bmp");
// 在图像的右下角定义一个 ROI
imageROI = image(cv::Rect(image.cols - logo.cols,
image.rows - logo.rows,
logo.cols, logo.rows));
// 把标志作为掩码(必须是灰度图像)
cv::Mat mask(logo);
logo.copyTo(imageROI, mask); // 插入标志,只复制掩码不为 0 的位置
cv::imshow("Image", image);
cv::waitKey(0);
return 0;
}
# 编译并执行
# 若版本为 OpenCV4.x,则最后改为 opencv4
$ g++ logo.cpp -o test3 `pkg-config --cflags --libs opencv`
$ ./test3
文章浏览阅读1.8k次。摘自: [ORACLE EBS 入门及供应链核心系统详解教程] (书籍)EBS基础功能架构(13个核心模块,业财一体化)业务运营管理,价值增值财务会计管理,价值实现应用架构Finance财务,资金流Accounting财务管理Bisuness业务,实物流核心业务,与财务高度集成;PUR、INV、制造、订单履行等间接业务,or专业业务,为核心业务提供支持;HR..._ebs r12
文章浏览阅读838次。转载:https://blog.csdn.net/ccecwg/article/details/39546307_java date timestamp区别
文章浏览阅读1.4k次。1、我们先了解一下原生js中的选择器ID选择器(在整个文档中获取id为xxx的元素)document.getElementId([ID]);类名选择器(在整个文档中或者在指定上下文中获取类名为xxx的元素)document.getElementsByClassName(' ');[context].getElementsByClassName(' ');标签名选择器(在整个文档中或者..._原声js实现jq元素选择器
文章浏览阅读1.2k次,点赞3次,收藏4次。通常查询时会对整个数据库查询,而这带来了大量的开销,因此引入了partition的概念,在建表的时候通过设置partition的字段, 会根据该字段对数据分区存放,更具体的说是存放在不同的文件夹,这样通过指定设置Partition的字段条件查询时可以减少大量的开销。1)partition by [key..] order by [key..]只能在窗口函数中使用,而distribute by [key...] sort by [key...]在窗口函数和select中都可以使用。_partition by distribute by
文章浏览阅读7.3k次。Private SQL Area A private SQL area holds information about a parsed SQLstatement and other session-specific information for processing. When a serverprocess executes SQL or PL/SQL code, the process_c# cursor
文章浏览阅读616次。近日在用ListView中的一些注意点,和公用代码,整理如下1.ListView.Items.Clear而不是ListView.Clear一般如果ListView是动态填充的,我们在填充之前都会先进行清理。但需要注意一下,我们是清理Items,如果去直接Clear整个ListView,就连原先定义好的列都没有了2.给ListView绑定数据ListView并不能直接_listview的使用——购物商城实验心得
文章浏览阅读110次。如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。注解处理器类库(java.lang.reflect.AnnotatedElement):Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口..._java注解处理器作用
文章浏览阅读1.8k次,点赞27次,收藏28次。全国职业技能大赛高职组(最新职业院校技能大赛_大数据应用开发样题解析-模块B:数据采集-任务一:离线数据采集-程序员宅基地。_大数据 国赛 样题
文章浏览阅读926次。本系统分为管理员和注册用户两个角色,主要有疫情新闻、疫情案例介绍、健康信息申报、行程信息申报、就医流程介绍、举报、在线留言、用户管理、信息统计等模块。用户需要先注册成为会员,成功登录后,可以查看网站发布的疫情新闻,可以查看疫情相关病例介绍,有助于疫情防范,还可以查看网站发布的重大疫情案例,了解疫情的发展状况,出行时候好做好防护,同时通过网站可以上报健康信息,以及上报行程信息,方便社区了解自己的出行情况;网站还发布了疫情状态下的就医流程,方便大家就医时候做好准备;同时网站还提供了举报功能,如果发现外来人员或_ssm+微信小程序
文章浏览阅读296次,点赞3次,收藏9次。本节关键字:Linux、centos、串口、U盘、共享文件夹本节相关指令:echo、cat、mkdir、mount
文章浏览阅读1.3k次,点赞45次,收藏29次。本篇主题为: 解密C++新特性:内联函数、auto关键字和基于范围的for循环。
文章浏览阅读774次,点赞4次,收藏11次。1、浏览器常见的报错信息与含义2、304与204的区别,http缓存,强缓存,协商缓存3、浏览器从输入地址到渲染,经历了什么状态?4、vue的界面渲染,经过哪些过程(生命周期)5、三次握手,四次挥手6、重排与重绘7、用css实现一个三角形8、常见的flex布局,有哪些功能9、用css实现一个水平垂直居中10、null与undefined的区别11、虚拟dom12、深拷贝与浅拷贝13、es6新增的功能15、async await 与promise。_今年的前端面试难不难