OpenCV 之 数字图像

时间:2022-11-08 22:17:06

1  数字图像

数字图像可看作一个 数值矩阵, 其中的每个 元素代表一个 像素点,如下图所示:

OpenCV 之 数字图像

2  存储方式

M 行 N 列图像的存储位数: b = M * N * k   ( L=2k, l ∈ [0, L-1], l 为灰度值 )

2.1  灰度图

OpenCV 中,灰度图的存储形式如下:

OpenCV 之 数字图像

2.2  RGB图像

OpenCV中,RGB图像以 BGR 的顺序存储,如下:

OpenCV 之 数字图像

2.3  Mat 类

Mat = 矩阵头 + 指针(指向包含像素值的矩阵),其有如下特点:

1)  矩阵头包含矩阵大小,存储函数,存储地址等信息

2)  使用 OpenCV 的接口函数,无需考虑内存管理

3)  执行赋值算子 “=” 或 拷贝构造函数时,仅仅复制矩阵头 (matrix header)

4)  图像矩阵的复制,应该使用 clone() 和 copyTo() 函数

#include <iostream>
#include "opencv2/core/core.hpp" using namespace std;
using namespace cv; int main(int,char**)
{
// 1) 构造函数
Mat M(,, CV_8UC3, Scalar(,,));
cout << "M = " << endl << " " << M << endl << endl; // 2) create 函数
M.create(,, CV_8UC());
cout << "M = "<< endl << " " << M << endl << endl; // 3) 多维矩阵
int sz[] = {,,};
Mat L(,sz, CV_8UC(), Scalar::all()); // 4) MATLAB 风格 eye, ones or zero
Mat E = Mat::eye(, , CV_64F);
cout << "E = " << endl << " " << E << endl << endl;
Mat O = Mat::ones(, , CV_32F);
cout << "O = " << endl << " " << O << endl << endl;
Mat Z = Mat::zeros(, , CV_8UC1);
cout << "Z = " << endl << " " << Z << endl << endl; // 5) 3x3 双精度
Mat C = (Mat_<double>(,) << , -, , -, , -, , -, );
cout << "C = " << endl << " " << C << endl << endl; //! [clone]
Mat RowClone = C.row().clone();
cout << "RowClone = " << endl << " " << RowClone << endl << endl; // 6) 随机值填充矩阵
Mat R = Mat(, , CV_8UC3);
randu(R, Scalar::all(), Scalar::all()); // 演示输出格式
cout << "R (default) = " << endl << R << endl << endl;
cout << "R (python) = " << endl << format(R, Formatter::FMT_PYTHON) << endl << endl;
cout << "R (numpy) = " << endl << format(R, Formatter::FMT_NUMPY ) << endl << endl;
cout << "R (csv) = " << endl << format(R, Formatter::FMT_CSV ) << endl << endl;
cout << "R (c) = " << endl << format(R, Formatter::FMT_C ) << endl << endl; vector<float> v;
v.push_back((float)CV_PI);
v.push_back();
v.push_back(3.01f);
cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;
}

3  邻域

D 定义为像素点 p(x, y) 和 q(s, t)的距离

3.1  四邻域 -  十字格

D4 = |x - s| + |y - t| = 1

$\quad \begin{bmatrix} 2 & 1 & 2 \\ 1 & 0 & 1 \\ 2 & 1 & 2 \end{bmatrix} $

3.2  八邻域 - 田字格

D8 = max(|x - s|, |y - t|) = 1

$\quad \begin{bmatrix} 1 & 1 & 1 \\ 1 & 0 & 1 \\ 1 & 1 & 1 \end{bmatrix} $

4  代码示例 

4.1  读图和显示 

OpenCV 中,图像读取和显示的函数名,和 Matlab 中的一致, 即 imread 和 imshow

#include "opencv2/highgui/highgui.hpp"
using namespace cv; int main(int argc, char ** argv) // int main()
{
Mat img = imread(argv[] - ); // Mat img = imread("E:/.../feng.jpg");
if(img.empty())
    return -;
namedWindow("Example", CV_WINDOW_AUTOSIZE);
imshow("Example", img);
waitKey();
}

4.2  遍历像素

4.2.1  efficient method

Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() == CV_8U);
int channels = I.channels();
int nRows = I.rows;
int nCols = I.cols * channels;
if (I.isContinuous())
{
nCols *= nRows;
nRows = ;
}
int i,j;
uchar* p;
for( i = ; i < nRows; ++i)
{
p = I.ptr<uchar>(i);
for ( j = ; j < nCols; ++j)
{
p[j] = table[p[j]];
}
}
return I;
}

 4.2.2  iterator method

Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() == CV_8U);
const int channels = I.channels();
switch(channels)
{
case :
{
MatIterator_<uchar> it, end;
for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
*it = table[*it];
break;
}
case :
{
MatIterator_<Vec3b> it, end;
for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
{
(*it)[] = table[(*it)[]];
(*it)[] = table[(*it)[]];
(*it)[] = table[(*it)[]];
}
}
}
return I;
}