发布于 

OpenCV学习笔记

记录一些OpenCV的基本操作。

持续更新中。

基础知识

图像的时空域表示

像素:(x,y)被赋予一个灰度值。图像在计算机中一般以矩阵的形式存储。

位深:存储一个像素所用的位(bit)被称为位深,存储一个像素使用的位越多,色彩越丰富。

通道:图像一个颜色通道表征一个维度的信息。例如RGB颜色空间中,有RGB三个通道,每个通道都是一个矩阵,矩阵中的每一个元素保存着0-255的值,对应不同的颜色分量。

色彩空间:RGB有局限性,RGB颜色的三个分量与亮度密切相关。只要亮度改变,三个分量都需要相应地改变,没有更直观的方式来表达。RGB是一种均匀性比较差的颜色空间,对于某一种颜色,我们很难推断出较为精确地三个分量数值来表示。还有HSV、HLS、YUV、LAB等色彩空间。

HSV色彩空间:Hue(色调、色相),Saturation(饱和度、色彩纯净度),Value(明度)。

RGB转换为HSV

先将RGB转换为0-1之间

R=R/255G=G/255B=B/255R=R/255\\ G=G/255\\ B=B/255

利用以下公式计算H、S、V

V=max(R,G,B)S={Vmin(R,G,B)V,V00,V=0H={60×(GB)/(Vmin(R,G,B)),V=R120+60×(BR)/(Vmin(R,G,B)),V=G240+60×(RG)/(Vmin(R,G,B)),V=BV=\mathrm{max}(R,G,B)\\ S= \begin{cases} \frac{V-\mathrm{min}(R,G,B)}{V}, V\not=0\\ 0, V=0 \end{cases}\\ H= \begin{cases} 60\times(G-B)/(V-\mathrm{min}(R,G,B)), V=R\\ 120+60\times(B-R)/(V-\mathrm{min}(R,G,B)), V=G\\ 240+60\times(R-G)/(V-\mathrm{min}(R,G,B)), V=B \end{cases}

如果H小于零,得到的最终的H值还要加上360。

图像的频域表示

将图像的灰度分布函数经过离散傅里叶变换即可得到图像的频率分布函数。

对图像而言,图像的边缘部分是突变部分,变化较快,因此反应在频域上是高频分量。为使图像边缘更加平滑,可以滤掉高频分量,即低通滤波器。相反,若需要提取出图像的边缘部分,可以滤掉低频分量,即高通滤波器。通常进行边缘提取或图像锐化。

这种方法在实际中不可取,计算量太大,更实用的办法是将设计好的mask做idft得其时空域表示,再将其域原图像卷积,可得到滤波后的图像。(卷积定理:频域相乘=时域相卷

图像的滤波

高通滤波:允许高频通过

低通滤波:允许低频通过

带通滤波:允许一定频率通过

带阻滤波:阻止一定频率通过

全通滤波:允许所有频率通过,仅仅改变相位关系

陷波滤波:阻止一个狭窄频率范围通过

图像处理

image-20221119204133760

基本图像操作

1
Src=Mat::zeros(200, 200, CV_8UC3)

8U:8位无符号数
C3:3个通道

B=src.at<Vec3b>(5,3)[0];取出图像中五行三列的B通道。

Vec3b存储三通道图像像素时所用的数据结构。

形态学变换

腐蚀

将图像与卷积核相卷积,计算卷积覆盖的图像区域中的最小值,并将赋给锚点像素。

可以消除图像中的一些毛刺。

膨胀

将图像与卷积核相卷积,计算卷积覆盖的图像区域中的最大值,并将其赋给锚点像素。

可以用于消除图像中的缺陷。

image-20221119204924991

ROI区域
方法一:

1
imageROI=image(Rect(500,250,rec.cols,rec.rows));

利用Rect函数,返回一个矩形区域,类型为N2cv5Rect_IiEE,eg:[20 x 20 from (1, 1)]

方法二:

1
imageROI=image(Range(250,250+rec.rows),Range(200,200+rec.cols));

输入与输出

  • imread
1
Mat imread(const string& filename, intflags=1 );

flags的参数含义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
enum
{
/* 8bit, color or not */
LOAD_IMAGE_UNCHANGED =-1,
/* 8bit, gray */
LOAD_IMAGE_GRAYSCALE =0,
/* ?, color */
LOAD_IMAGE_COLOR =1,
/* any depth, ? */
LOAD_IMAGE_ANYDEPTH =2,
/* ?, any color */
LOAD_IMAGE_ANYCOLOR =4
};
  • namedWindow

用于创建一个有名字的窗口。
flags默认为WINDOW_AUTOSIZE。一般不需要调整。

  • imshow
1
void imshow(const string& winname, InputArray mat);

这里的InputArray会进行枚举,匹配到相应的类型。可以理解为通用的矩阵类。

  • imwrite
1
bool imwrite(const string& filename,InputArray img, const vector<int>& params=vector<int>() );

最后一个参数决定图像质量。

对于JPEG格式的图片,这个参数表示从0到100的图片质量(IMWRITE_JPEG_QUALITY),默认值是95.
对于PNG格式的图片,这个参数表示压缩级别(IMWRITE_PNG_COMPRESSION)从0到9。较高的值意味着更小的尺寸和更长的压缩时间,而默认值是3。
对于PPM,PGM,或PBM格式的图片,这个参数表示一个二进制格式标志(IMWRITE_PXM_BINARY),取值为0或1,而默认值是1。

具体的用法如下:

1
2
3
4
std::vector<int> compression_params;
compression_params.push_back(IMWRITE_JPEG_QUALITY); //选择jpeg
compression_params.push_back(100); //在此填入你要的图片质量
imwrite("test.jpg", destImage1, compression_params);

查找轮廓

轮廓contours的定义为vector<vector<Point>> contours是一个嵌套的向量。向量的每一个元素保存了一组由连续的Point点构成的点的向量组,每一组Point就是一个轮廓。

参数hierarchy也是一个向量,向量内有四个整数,整数代表轮廓的标号,与contours中的索引相同。从hierarchy[i][0]到hierarchy[i][3],分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果没有对应的轮廓值为-1。