http://guoming.me/opencv-config  这篇文章有讲解opencv的安装与配置

一些常用库

  1. opencv_core249d.lib
  2. opencv_imgproc249d.lib
  3. opencv_highgui249d.lib
  4. opencv_ml249d.lib
  5. opencv_video249d.lib
  6. opencv_features2d249d.lib
  7. opencv_calib3d249d.lib
  8. opencv_contrib249d.lib
  9. opencv_legacy249d.lib
  10. opencv_flann249d.lib
  11. opencv_gpu249d.lib

一个测试程序

  1. 1 #include <opencv2/core/core.hpp>
  2. 2 #include <opencv2/highgui/highgui.hpp>
  3. 3 #include <iostream>
  4. 4
  5. 5 using namespace cv;
  6. 6 using namespace std;
  7. 7
  8. 8 int main()
  9. 9 {
  10. 10 Mat image;
  11. 11 image = imread("D:\\lenargb.jpg", -1); // Read the file
  12. 12
  13. 13 if (!image.data) // Check for invalid input
  14. 14 {
  15. 15 cout << "Could not open or find the image" << std::endl;
  16. 16 return -1;
  17. 17 }
  18. 18
  19. 19 namedWindow("Display window", WINDOW_AUTOSIZE); // Create a window for display.
  20. 20 imshow("Display window", image); // Show our image inside it.
  21. 21
  22. 22 waitKey(0); // Wait for a keystroke in the window
  23. 23 return 0;
  24. 24 }

Mat 类的一些属性

//矩阵的维数,取值应该大于或等于 2

int dims;

//矩阵的行数和列数,如果矩阵超过 2 维,这两个变量的值都为-1

int rows, cols;

//指向数据的指针

uchar* data;

Mat 构造方法

Mat M(3,2, CV_8UC3, Scalar(0,0,255));

cout << "M = " << endl << " " << M << endl;

第一行代码创建一个行数(高度)为 3,列数(宽度)为 2 的图像,图像元素是 8 位无符号整数类型,且有三个通道。图像的所有像素值被初始化为(0,  0,255)。由于 OpenCV 中默认的颜色顺序为 BGR,因此这是一个全红色的图像。

第二行代码是输出 Mat 类的实例 M 的所有像素值。 Mat 重定义了<<操作符,使用这个操作符,可以方便地输出所有像素值,而不需要使用 for 循环逐个像素输出

 

opencv中图像的通道数

基本上,描述一个像素点,如果是灰度,那么只需要一个数值来描述它,就是单通道。

如果一个像素点,有RGB三种颜色来描述它,就是三通道

windows的bmp有时候是一个四通道图像,R、G、B加上一个A通道,表示透明度。

最后这个,一般叫做alpha通道,表示透明度的。

初学只要知道单通道和三通道就好;

创建图像对象

Mat常用的构造函数:

Mat(int rows,int cols,int type,const scalar &s);

其中
rows 表示行数,cols表示列数,两者可以结合为Size size;

Type 可以是 CV_8UC1, CV_16SC1, …,CV_64FC4 等。里面的 8U 表示 8 位无符号整数,16S 表示 16 位有符号整数,64F表示 64 位浮点数(即 double 类型);C 后面的数表示通道数,例如 C1 表示一个通道的图像,C4 表示 4 个通道的图像,以此类推。

如果你需要更多的通道数,需要用宏 CV_8UC(n),例如:Mat M(3,2, CV_8UC(5));//创建行数为 3,列数为 2,通道数为 5 的图像

Scalar 可以设置通道里的像素值;可有可无。可以使用 Mat 类的 create()函数创建图像。

  1. #include <opencv2/core/core.hpp>
  2. #include <opencv2/highgui/highgui.hpp>
  3. #include <iostream>
  4.  
  5. using namespace cv;
  6. using namespace std;
  7.  
  8. int _tmain(int argc, _TCHAR* argv[])
  9. {
  10. Mat img(3, 2, CV_8UC3, Scalar(100, 100, 200));
  11. cout << "M=" << endl << " " << img << endl;
  12. img.create(3, 2, CV_8UC1);
  13. cout << "M=" << endl <<" "<< img << endl;
  14.  
  15. //imshow("嘿嘿", img);
  16. //waitKey();
  17. system("pause");
  18. return 0;
  19. }

运行结果

这里我们发现create函数只有Mat类构造函数的前三个参数,故不能设置像素初始值,我们上面设置单通道是看到不管构造时是什么值,经过create后都变成了205;当设置成三通道时,如果图像的尺寸和通道数相同,则并不会重新设置像素值,因为如果create的参数和初始值(如果有的话)是一样的话,那么就不会重新分配内存;

遍历像素

(1)    at()函数  是个模版函数;需要指明元素类型

  1. #include <time.h>
  2. #include <iostream>
  3. #include "opencv2/opencv.hpp"
  4. //一般用这个头文件就可以,只不过可能会把大部分用不到的头文件引入进来;
  5. using namespace std;
  6. using namespace cv;
  7. int main(int argc, char* argv[])
  8. {
  9. srand(time(NULL));
  10. Mat grayim(600, 800, CV_8UC1);//600*800的灰度图;
  11. Mat colorim(600, 800, CV_8UC3);//600*800的彩色图;
  12. //遍历所有像素,并设置像素值;
  13. for (int i = 0; i < grayim.rows; ++i)//Mat的rows和cols属性是public的;
  14. for (int j = 0; j < grayim.cols; ++j)
  15. grayim.at<uchar>(i, j) = (i + j) % 255;
  16. //遍历所有像素,并设置像素值;
  17. for (int i = 0; i < colorim.rows; ++i)
  18. for (int j = 0; j < colorim.cols; ++j)
  19. {
  20. Vec3b pixel;//
  21. pixel[0] = i % 255; //Blue
  22. pixel[1] = j % 255; //Green
  23. pixel[2] = 0; //Red
  24. colorim.at<Vec3b>(i, j) = pixel;
  25. }
  26. //显示结果
  27. imshow("grayim", grayim);
  28. imshow("colorim", colorim);
  29.  
  30. waitKey(0);
  31. return 0;
  32. }

OpenCV 中有模板类 Vec,可以表示一个向量,用来表示彩色图像的一个像素;例如 8U 类型的 RGB 彩色图像可以使用 Vec3b,3 通道 float 类型的矩阵可以使用 Vec3f

  1. Vec3b color; //用 color 变量描述一种 RGB 颜色
  2.  
  3. color[0]=255; //B 分量
  4.  
  5. color[1]=0; //G 分量
  6.  
  7. color[2]=0; //R 分量

2)    使用STL库里的迭代器,

  1. #include <time.h>
  2. #include <iostream>
  3. #include "opencv2/opencv.hpp"
  4. //一般用这个头文件就可以,只不过可能会把大部分用不到的头文件引入进来;
  5. using namespace std;
  6. using namespace cv;
  7. int main(int argc, char* argv[])
  8. {
  9. srand(time(NULL));
  10. Mat grayim(600, 800, CV_8UC1);//600*800的灰度图;
  11. Mat colorim(600, 800, CV_8UC3);//600*800的彩色图;
  12. //遍历所有像素,并设置像素值;
  13. MatIterator_<uchar> graim_it, graim_end;
  14. MatIterator_<Vec3b> color_it, color_end;
  15. for (graim_it=grayim.begin<uchar>(),graim_end=grayim.end<uchar>(); graim_it!=graim_end; ++graim_it)
  16. {
  17. *graim_it = rand() % 255;
  18. }
  19. for (color_it = colorim.begin<Vec3b>(), color_end = colorim.end<Vec3b>(); color_it != color_end; color_it++)
  20. {
  21. (*color_it)[0] = rand() % 255;
  22. (*color_it)[1] = rand() % 255;
  23. (*color_it)[2] = 0;
  24.  
  25. }
  26. //显示结果
  27. imshow("grayim", grayim);
  28. imshow("colorim", colorim);
  29. waitKey(0);
  30. return 0;
  31. }

使用迭代器一定要注意原来的元素的类型哦;

Mat_类的必要性

Mat_ 类 是个模版类

  1. #include <iostream>
  2. #include <opencv2/core/core.hpp>
  3. #include <opencv2/highgui/highgui.hpp>
  4. using namespace cv;
  5. using namespace std;
  6.  
  7. int _tmain(int argc, _TCHAR* argv[])
  8. {
  9.  
  10. #pragma region Mat在调用一些函数时必须指明类型;除了at还有beginend
  11. Mat mtx1(6, 8, CV_8UC1);
  12. // for (int i = 0; i < mtx1.rows; i++)
  13. // {
  14. // for (int j = 0; j < mtx1.cols; j++)
  15. // {
  16. // double d1 = (i + j) % 255;
  17. // mtx1.at<uchar>(i, j) = d1;
  18. // double d2 = mtx1.at<uchar>(i, j);
  19. // if (d1 == d2)
  20. // {
  21. // mtx1.at<uchar>(i, j) = 255;
  22. // }
  23. // else
  24. // mtx1.at<uchar>(i, j) = 0;
  25. // }
  26. // }
  27. // cout << "mtx1=" << endl << " " << mtx1 << endl;
  28. #pragma endregion
  29.  
  30. Mat_<uchar> mtx2=(Mat_<uchar> &)mtx1;
  31. randu(mtx2, Scalar::all(0), Scalar::all(255));
  32. cout << "mtx2=\n " << mtx2 << endl;
  33. for (int i = 0; i < mtx2.rows; i++)
  34. {
  35. for (int j = 0; j < mtx2.cols; j++)
  36. {
  37. double d3 = (i + j) % 255;
  38. mtx2(i,j) = d3; // 这里把at函数包装成操作符();
  39. double d4 = mtx2(i, j);
  40. MatIterator_<uchar> it = mtx2.begin();
  41. MatIterator_<uchar> it2 = mtx1.begin<uchar>();
  42. }
  43. }
  44.  
  45. system("pause");
  46. return 0;
  47. }

Mat类对象调用的很多方法都要指明类型,Mat_类是个模版类 对Mat进行了包装,只用在声明的时候指明类型,需要注意几点:

(1)      声明的时候指定类型

(2)      访问一个元素的时候可以直接使用重载的()操作符

(3)      调用其它方法时不用指定类型

这样的好处是

(1)      方便编程,不用写类型了

(2)      如果使用的时候类型标错了,那么在使用的时候会因为内存越界而出现运行时错误,因为c++是弱类型的,所以编译阶段不报错;比如声明的时候存的是uchar类型的,每个元素占一个字节,当访问的时候如果指定成double型的话,就会查8个字节,很容易越界。

图像的读取和存储

imread()函数返回的是 Mat 对象,如果读取文件失败,则会返回一个空矩阵,即 Mat::data 的值是 NULL。执行 imread()之后,需要检查文件是否成功读入,可以使用 Mat::empty()函数进行检查。Mat imread(const string& filename, int flags=1 )

参数flags>0是,返回一个三通道彩色图像,如果图像是灰度图,强制转换为彩色图像

flag=0 返回一个灰度图,单通道,如果图像是彩色图,则强制转换为灰度图;

flag<0 对图像不进行通道转换;

bool imwrite(const string& filename, InputArray image, const vector<int>& params=vector<int>())

BMP 格式是无损格式,但是一般不进行压缩,文件尺寸非常大;JPEG 格式的文件娇小,但是 JPEG 是有损压缩,会丢失一些信息。PNG 是无损压缩格式,推荐使用。

params 可以指定文件格式的一些细节信息

JPEG:表示图像的质量,取值范围从 0 到 100。数值越大表示图像质量越高,当然文件也越大。默认值是 95。

PNG:表示压缩级别,取值范围是从 0 到 9。数值越大表示文件越小,但是压缩花费的时间也越长。默认值是 3。

PPM, PGM 或 PBM:表示文件是以二进制还是纯文本方式存储,取值为0 或 1。如果取值为 1,则表示以二进制方式存储。默认值是 1。

只有 8U 类型的单通道和 3 通道(颜色顺序为 BGR)矩阵才能保存为全格式,其它类型可以通过Mat::convertTo()函数或者 cvtColor()函数将矩阵转为可以保存的格式。

Imshow  如果不加那个waitkey的话有时候只会显示一个灰色窗口;

默认参数为0,意思是等待forever,返回按下键的值,返回有两种可能1是在指定时间内用户按键盘,返回按的键值,要么是时间到返回0;ESC返回的是27;

  1. #include <opencv2/opencv.hpp>
  2. #include <iostream>
  3. using namespace std;
  4. using namespace cv;
  5. int _tmain(int argc, _TCHAR* argv[])
  6. {
  7. Mat img = imread("D:\\lenargb.jpg", 0);
  8. #pragma region 下面判断是否为空
  9. if (img.empty())
  10. {
  11. cout << "无法加载图片" << endl;
  12. system("pause");
  13. return -1;
  14. }
  15. #pragma endregion
  16. Mat result;
  17. Canny(img, result, 50, 150);
  18. imshow("原图", img);
  19. imshow("边缘检测后", result);
  20. imwrite("D://result.png", result);
  21. waitKey();
  22. system("pause");
  23.  
  24. return 0;
  25. }

1. opencv的初体验的更多相关文章

  1. opencv的初体验

    http://guoming.me/opencv-config  这篇文章有讲解opencv的安装与配置 一些常用库 opencv_core249d.lib opencv_imgproc249d.li ...

  2. Swift与C++混编 OpenCV初体验 图片打码~

    OpenCV初体验,给图片打码 提到OpenCV,相信大多数人都听说过,应用领域非常广泛,使用C++开发,天生具有跨平台的优势,我们学习一次,就可以在各个平台使用,这个还是很具有诱惑力的.本文主要记录 ...

  3. 痞子衡嵌入式:走进二维码(QR Code)的世界(2)- 初体验(PyQt5.11+MyQR2.3+ZXing+OpenCV4.2.0)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是走进二维码(QR Code)的世界专题之初体验. 接上篇 <走进二维码(QR Code)的世界(1)- 引言> 继续更文,在 ...

  4. .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验

    不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...

  5. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

  6. Spring之初体验

                                     Spring之初体验 Spring是一个轻量级的Java Web开发框架,以IoC(Inverse of Control 控制反转)和 ...

  7. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  8. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

  9. 【Knockout.js 学习体验之旅】(1)ko初体验

    前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...

随机推荐

  1. 【Shell脚本学习12】Shell字符串

    字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号.单双引号的区别跟PHP类似. 单引号 str='this ...

  2. spring mvc 重新定向到一个新的Url

    在写项目的时候要求根据请求的参数的不同重新将请求分发,在查阅了spring mvc的一些资料无果后(想使用拦截器去做)就没办法使用重定向的方式去写了 /** * 通过访问API的方式分发请求 * * ...

  3. linux初学 :简易的shell脚本

    什么是shell Shell本身是一个用C语言编写的程序,它是用户使用Unix/Linux的桥梁,用户的大部分工作都是通过Shell完成的 Shell有两种执行命令的方式: 交互式(Interacti ...

  4. oracle PL/SQL(procedure language/SQL)程序设计之异常(exception)

    什么是异常?在PL/SQL中的一个标识.在程序运行期间被触发的错误.异常是怎样被触发的?产生一个Oracle错误.用户显示触发.怎样处理异常?用异常处理句柄捕获异常.传播异常到调用环境. 捕获异常 E ...

  5. BI跟报表一样吗?

    一.报表≠BI很多的人认为,报表就是BI.实际上,报表只是BI的一部分,虽然BI应用的结果通常需要通过报表来展示,但是,BI绝对不仅仅是报表.其实,大家对这些概念的理解,如同15年前的ERP一样.19 ...

  6. 剑指Offer15 合并两个已排序链表

    /************************************************************************* > File Name: 15_MergeT ...

  7. GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树

    GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...

  8. 两种局部刷新UITableView的方法的使用条件

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ //1.取消选 ...

  9. sql语句使用游标修改表中数据

    declare @a varchar(),@b varchar() declare user_cursor cursor for select a,b from tableA tab open use ...

  10. SVN Server导项目到本地库时提示"方法OPTIONS失败与无法连接到服务器"

    方法 OPTIONS 失败于 “https://xxxx/svn/xxxx”: 无法连接到服务器 (https://xxxx) 要留意  https 使用了443 端口,检查防火墙是否开放了该端口. ...