1图像处理基础
Posted 郭润
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1图像处理基础相关的知识,希望对你有一定的参考价值。
大纲
1、图像处理基础
2、图像的特征提取
3、机器视觉中的几何学
1)坐标变换与视觉测量
2)3D计算机视觉
4、机器视觉中的机器学习方法与数据处理
1)图像识别
2)图像搜索
推荐书:计算机视觉---算法与应用。
Fundamental of Computer Vision(计算机视觉基础)
1、什么是计算机视觉?
计算机视觉的目的就是写计算机程序来解释图像。
图像处理(image processing)输入的是图像输出的还是图像。
计算机视觉(computer vision)输入的是图像输出的是对图像的理解。
应用:
目标跟踪和识别、人脸识别、增强现实(AR-Augmented reality)(,以前叫virtual reality,虚拟现实,其实就是是否引入真实场景,AR就是在我们看到的基础之后,增加一些三维的场景,比如对物体的解释等等)、机器人学(识别物体、估计运动和位姿)、工业检测、字符设别等等
2、open libraries/projects(开源库或者工程)
opencv官网:http://opencv.org/
语言:c++,c,python和java接口
平台:windows,linux,Mac OS,ios和android
库用得比较多的:CxImage,CImage,FreeImage
HALCON:http://www.halcon.com
,它是商用的图像处理的库,收费的
开源项目
项目一:人脸识别
项目二:车牌识别
mobileye公司的产品可以关注一下!!
这种发布的版本只能看源代码不能调试源代码!!!
2015为VC14
3、opencv安装配置
环境变量配置好之后,接下来在工程中进行配置,在属性管理器中进行一次配置,以后就不用再配置了:
先新建一个空的工程,然后再进行下面的配置!!!
对于依赖项部分,在3.0之前要添加很多依赖项,但是在3.0之后只添加如上的两个库文件。
下面环境安装完成!!!!!!!!!!
介绍一个插件
Image Watch,这个插件也是2.4之后才有的,它是非常有用的东西
程序模版
认识图像
图像数据在内存中的存储
opencv是从元素[0,0]开始且按行存储,而matlab是从[1,1]开始表示第一个元素且按列存储。
在opencv里面最常用的就是Mat类型,它既可以表示数据data,也可以表示图像类。
Mat定义一个矩阵,如下解释
Mat M(3,2,CV_8UC3,Scalar(0,0,255));
cout<<"M="<<endl<<" "<<M<<endl;
上面创建了一个高为3,宽为2的矩阵,且是3通道(C3)的8位无符号整数(8U),初始值为(0,0,255)
由于上面的符号"<<"被重构了,所以把这个矩阵打印出来,如上面所示。
我们定义了3行2列的矩阵,由于channel是3,2乘3是六列,但其实矩阵的维度还是3*2,在内存中占了6个字节.???
Scalar是从Vector类衍生出来的类,他可以存储4个元素,一次性最多可以赋值4个值,除了RGB三个通道之外,还有一个表示透明度的α参数。
上图中的变量refcount表示引用计数,表示有多少个指针指向了同一个data区域,它在内存中占数据区域的最后4位。
Mat常用的构造函数
举个例子:
//定义一个变量,通过函数Imread来读取图片lena.jpg,1是指的它是彩色就读取彩色图像,是灰度图像就读取灰度图像。
cv::Mat pImag = imread("lena.jpg",1);
//定义了一个矩形区域,左上角坐标(180,200),后面两个数是矩阵的宽、高度(200,200),图像坐标
cv::Rect rect(180, 200, 200, 200);
也是先x坐标后y坐标。
//定义了一个roi的变量,如前面的构造函数Mat::Mat(const Mat& m,const Rect& roi),这时候只是使roi指向了rect这个地址,不是深拷贝
cv::Mat roi = cv::Mat(pImag,rect);
//又定义了一个变量pImgRect,它把原来的图像进行深层拷贝clone(),赋值给该变量,且带有矩形框。还有一个copyto函数也是深拷贝
cv::Mat pImgRect = pImag.clone();
//在原始图形上勾勒出对应的矩形框void rectangle(Mat& img, Rect rec, const Scalar& color, int thickness=1, int lineType=8, int shift=0 );img图像.pt1矩形的一个顶点。pt2矩形对角线上的另一个顶点color线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)。thickness组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。line_type线条的类型。见cvLine的描述shift坐标点的小数点位数。
cv::rectangle(pImgRect,rect,cv::Scalar(0,255,0),2);
cv::imshow("original image with rectangle",pImgRect);
imshow("roi",roi);
cv:waitkey();
注意,深拷贝与浅拷贝(注意上面的构造函数都是浅拷贝)
上面左边是浅拷贝,上面的构造函数都是浅拷贝;右边是深拷贝
测试
eye表示对角矩阵,默认都是单通道!
像素值的读写-1
grayim.at<uchar>(i,j),这里的at表示在那个位置,表示对一个灰度图像在i行j列拿到这个元素的灰度值。
上面是一个单通道的图像,下面是一个三通道的图像,
先处理行再处理列。
有一个Vec3b类,表示是3个元素,b是unchar型,
typedef Vec3b vec<uchar,3>
上面的具体实现以及结果
for (int i = 0; i < grayim.rows; ++i)
for (int j = 0; j < grayim.cols; ++j)
grayim.at<uchar>(i, j) = (i + j) % 255;
imshow("grayim",grayim);
for (int i = 0; i < colorim.rows; ++i)
for (int j = 0; j < colorim.cols; ++j)
{
Vec3b pixel;
pixel[0] = i % 255;//blue
pixel[1] = j % 255;//green
pixel[2] = 0;//Red
colorim.at<Vec3b>(i, j) = pixel;
}
imshow("colorim", colorim);
像素值的读写2
Iterator迭代器可以方便遍历所有的元素,以便于对矩阵元素进行遍历
具体实现
cv::MatIterator_<uchar> grayit, grayend; for (grayit = grayim.begin<uchar>(), grayend = grayim.end<uchar>(); grayit != grayend; ++grayit) *grayit = rand() % 255; imshow("grayim", grayim); MatIterator_<Vec3b> colorit, colorend; for (colorit = colorim.begin<Vec3b>(), colorend = colorim.end<Vec3b>(); colorit != colorend; ++colorit) { (*colorit)[0] = rand() % 255;//Blue (*colorit)[1] = rand() % 255;//green (*colorit)[2] = rand() % 255;//red } imshow("colorim", colorim);
上面用的是ptr的模板函数,用于选中一行的首元素地址。
具体代码:
for (int i = 0; i < grayim.rows; ++i) { //获取第i行首像素指针 uchar *p = grayim.ptr<uchar>(i); //对第i行的每个像素操作 for (int j = 0; j < grayim.cols; ++j) p[j] = (i + j+5) % 255; } imshow("grayim1", grayim); for (int i = 0; i < colorim.rows; ++i) { Vec3b *p = colorim.ptr<Vec3b>(i); //对第i行的每个像素操作 for (int j = 0; j < colorim.cols; ++j) { p[0] = i % 255;//blue p[1] = j % 255;//green p[2] = 0;//Red colorim.at<Vec3b>(i, j) = *p; } } imshow("colorim1", colorim);
以上是关于1图像处理基础的主要内容,如果未能解决你的问题,请参考以下文章
[Go] 通过 17 个简短代码片段,切底弄懂 channel 基础