Opencv學習——圖像及視頻讀取

Opencv的圖像讀取有CC++接口的,由於C接口涉及到指針操作,需要對指針進行管理。而C++接口就比較簡單了,本文也主要以C++接口來進行圖像操作。Opencv2.0版本後新增了Mat操作,相比之前的版本簡單了很多。讀取一張圖片的函數類似於matlab的方式。

//圖像讀取
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat img = imread("lena.jpg",1);
    if(img.empty())
    {
        cout<<"Cannot open the image!"<<endl;
    }

    namedWindow("lena",CV_WINDOW_AUTOSIZE);    //可以不用此句
    imshow("lena",img);
    waitKey(100);

    imwrite("lenaCopy.jpg",img);
    return 0;
}

在opencv中圖像通道的順序爲BGR。圖像像素操作一般有三種方法,考慮到效率的問題還是C風格的指針操作比較高效,函數isContinuous()將圖像轉化爲單行形式,這樣能夠加速瀏覽過程。

Mat& ScanImageAndReduceC(Mat &I, const uchar* const table)
{
    //accept only char type matrices
    CV_ASSERT(I.depth()!=sizeof(uchar));
 
    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<nRow;i++)
    {
        p = I.ptr<uchar>(i);
        for(j=0;j<nCols;j++)
        {
            p[j] = table[p[j]];
        }
    }
    Return I;
}
迭代方法是比較安全的方法:

Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
{
    //accept only char type matrices
    CV_ASSERT(I.depth()!=sizeof(uchar));
    
    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: //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]];
            }
            break;
        }
    }
    return I;
}
 最後是不太推薦的圖像掃描方式,只適合獲取或更改圖像中的隨機像素,使用的是at()函數:

Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table)
{
//accept only char type matrices
    CV_ASSERT(I.depth()!=sizeof(uchar));
    
    Const int channels = I.channels();
    Switch(channels)
    {
        case 1: //單通道
        {
            for(int i=0;i<I.rows;i++)
                for(int j=0;j<I.cols;j++)
                    I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];
            break;
        }
        case 3: //3通道
        {
            Mat_<Vec3b> _I = I;
            for(int i=0;i<I.rows;i++)
                for(int j=0;j<I.cols;j++)
                {
                    _I(i,j)[0] = table[I(i,j)[0]];
                    _I(i,j)[1] = table[I(i,j)[1]];
                    _I(i,j)[2] = table[I(i,j)[2]];
                }
            
            I = _I;
            break;
        }
    }
    return I;
}
讀取圖片比較簡單,從攝像機讀取視頻則稍微複雜一點://讀取視頻
//讀取視頻
int main(int,char**)
{
    VideoCapture cap(0);
    if(!cap.isOpened())
    {
        cout<<"Cannot Open the camera!"<<endl;
        return -1;
    }
    
    double dwidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);   //獲取圖像尺寸
    double dheight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
    
    Mat frame;
    while(1)
    {
        bool bSuccess = cap.read(frame);
        if(!bSuccess)
        {
            cout<<"Cannot read a frame from video stream!"<<endl;
            break;
        }
        imshow("video",frame);
        if(waitKey(30)==27)
        {
            cout<<"ESC key is pressed by user"<<endl;
            break;
        }
    }
    
    return 0;
}
將VideoCapture cap(0)改爲VideoCapture cap("camera.avi"),即可讀取本地視頻。以上是opencv讀寫圖像及視頻的簡介。





發佈了23 篇原創文章 · 獲贊 39 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章