OpenCV 之 數字圖像 -开发者知识库

1  數字圖像

數字圖像可看作一個數值矩陣, 其中的每個元素代表一個像素點，如下圖所示：

2  存儲

M 行 N 列圖像的存儲位數: b = M * N * k   ( L=2k, l ∈ [0, L-1], l 為灰度值 )

2.1  灰度圖

OpenCV 中，灰度圖的存儲形式如下：

2.2  RGB圖像

OpenCV中，RGB圖像以 BGR 的順序存儲，如下：

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(2,2, CV_8UC3, Scalar(0,0,255));    cout << "M = " << endl << " " << M << endl << endl;    // 2) create 函數    M.create(4,4, CV_8UC(2));    cout << "M = "<< endl << " "  << M << endl << endl;    // 3) 多維矩陣    int sz[3] = {2,2,2};    Mat L(3,sz, CV_8UC(1), Scalar::all(0));    // 4) MATLAB 風格 eye, ones or zero    Mat E = Mat::eye(4, 4, CV_64F);    cout << "E = " << endl << " " << E << endl << endl;    Mat O = Mat::ones(2, 2, CV_32F);    cout << "O = " << endl << " " << O << endl << endl;    Mat Z = Mat::zeros(3, 3, CV_8UC1);    cout << "Z = " << endl << " " << Z << endl << endl;    // 5) 3x3 雙精度    Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);    cout << "C = " << endl << " " << C << endl << endl;    //! [clone]    Mat RowClone = C.row(1).clone();    cout << "RowClone = " << endl << " " << RowClone << endl << endl;    // 6) 隨機值填充矩陣    Mat R = Mat(3, 2, CV_8UC3);    randu(R, Scalar::all(0), Scalar::all(255));    // 演示輸出格式    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;    Point2f P(5, 1);    cout << "Point (2D) = " << P << endl << endl;    Point3f P3f(2, 6, 7);    cout << "Point (3D) = " << P3f << endl << endl;    vector<float> v;    v.push_back((float)CV_PI);       v.push_back(2);        v.push_back(3.01f);    cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;    vector<Point2f> vPoints(20);    for (size_t i = 0; i < vPoints.size();   i)        vPoints[i] = Point2f((float)(i * 5), (float)(i % 7));    cout << "A vector of 2D Points = " << vPoints << 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[1] - 1);  // Mat img = imread("E:/.../feng.jpg");    if(img.empty()) 　　　　return -1;    namedWindow("Example", CV_WINDOW_AUTOSIZE);    imshow("Example", img);    waitKey(0);}

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 = 1;    }    int i,j;    uchar* p;    for( i = 0; i < nRows;   i)    {        p = I.ptr<uchar>(i);        for ( j = 0; 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 1:        {            MatIterator_<uchar> it, end;            for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end;   it)                *it = table[*it];            break;        }    case 3:        {            MatIterator_<Vec3b> it, end;            for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end;   it)            {                (*it)[0] = table[(*it)[0]];                (*it)[1] = table[(*it)[1]];                (*it)[2] = table[(*it)[2]];            }        }    }    return I;}

0条回复