终于,在国庆假期结束后开始上手OpenCV,一直向往着学习图像处理,上手OpenCV后越发觉得图像处理的有趣,确实OpenCV对于培养学习图像处理的兴趣以及作为深究算法的开始无疑是适合的。
我所使用的环境是Win10+OpenCV3.4.3+VS2017
一、环境配置
关于在VS中搭建OpenCV的开发环境我就不在此详细介绍了,因为这个网上的教程一搜一大堆,而且配置也很简单,按着别人教程的步骤一步一步来就好了。
二、图像的基本操做
读取图像:imread
第一个参数:文件名称
第二个参数:图像类型 IMREAD_GRAYSCALE(0) 灰度图
IMREAD_UNCHANGED(<0)原图
IMREAD_COLOR(>0)作为RGB图像加载进来
//示例代码
Mat src;
src = imread("G:/OpenCv学习/图像文件/Lenna.jpg");
创建一个现实窗口:namedWindow
自动创建和释放无需手动销毁
名称+WINDOW_AUTOSIZE(自动调节大小)/WINDOW_NORMAL(允许修改,一般不用)
//示例代码
namedWindow("input", CV_WINDOW_AUTOSIZE);
显示图片:imshow
显示到指定窗口,名称+Mat对象
//示例代码
imshow("input", src);
转变色彩空间:cvtColor
转变色彩空间,图像处理的思路就是换到别的空间处理完然后转回RGB
源Mat对象+转换后的Mat对象+源和目标色彩空间(xx2xx)
CV里RGB 为BGR
//示例代码
cvtColor(src,dst,BGR2GRAY);
保存图片:imwrite
文件名+Mat对象
保存图像类型自己写后缀
//示例代码
imwrite("test.jpg",src);
获取像素的指针:Mat.ptr<uchar>(row)
索引i表示第几行的像素
row[i] 用来得到该行某个像素点的值
行索引指针类型为 uchar*
//示例代码
uchar* prow=Mat.ptr<uchar>(1);
像素处理范围限定:sturate_cast
小于0返回0,大于255返回255,在255之间返回原值
//示例代码
sturate_cast(100);//返回100
sturate_cast(300);//返回255
sturate_cast(-100);//返回0
读像素点的值:Mat对象.at<uchar>(row,col);或Mat对象.at<Vec3b>(row,col)[0-2];
对于灰度图,使用函数Mat对象.at<uchar>(row,col);
对于RGB图像使用函数:
Mat对象.at<Vec3b>(row,col)[0];
Mat对象.at<Vec3b>(row,col)[1];
Mat对象.at<Vec3b>(row,col)[2];
Vec3b表示读到的值为uchar类型,Vec3F表示值为Float类型,图像为8位深度的话只能读到uchar类型(0-255)的值,如果转换成32位深度,可以读到float类型的值。
//示例代码
int v=src1.at<uchar>(100,100);//读灰度图src1(100,100)处像素的值
int b=src2.at<Vec3b>(100,100)[0];//读RGB图像src2(100,100)处blue通道的像素值
int g=src2.at<Vec3b>(100,100)[1];//读RGB图像src2(100,100)处green通道的像素值
int r=src2.at<Vec3b>(100,100)[2];//读RGB图像src2(100,100)处red通道的像素值
三、Mat对象及操作
Mat对象OpenCV2.0之后引进的图像数据结构、自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分了两个部分,头部与数据部分
IplImage是从2001年OpenCV发布之后就一直存在,是C语言风格的数据结构,需要开发者自己分配与管理内存,对大的程序使用它容易导致内存泄漏问题
算法移植的时候,老代码可能使用Ipl,opencv提供了函数将Ipl转换成Mat,最好要使用Mat对象
构造函数与常用用法:
void copyTo(Mat mat) |
复制到一个Mat对象 |
void convertTo(Mat dst, int type) |
转换类型 |
Mat clone() |
克隆 |
int channels() |
得到对象的通道数 |
int depth() |
得到对象的深度(8,16,24) |
bool empty(); |
检验是否为空 |
uchar* ptr(i=0) |
得到某行的指针(dst.ptr<uchar>(0) |
Mat对象使用
部分复制:只复制头部分和指针部分 imread
完全复制:复制头部分和数据部分 clone,copyTo
四个要点:
1、输出图像的内存是自动分配的
2、使用OpenCV的C++接口,不需要考虑内存分配问题
3、赋值操作和拷贝构造函数只会复制头部分
4、使用clone与copyTo两个函数实现数据完全复制
Mat对象创建:
cv::Mat::Mat构造函数
row+col+type+Scalar
CV_8UC3 8位深度,无符号char类型三个通道
创建多维数组cv::Mat::create
creat不能自动赋值 使用Mat对象=Scalar(x,x,x);
定义小数组
Mat
类似matlab的对象创建
Mat::zeros(2,2,CV_8SC1);
Mat::zero(size,type);
eye单位矩阵