[openCV2.1]經常使用功能

0:必用頭文件

#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#define WINDOW_AUTOSIZE 1
//CV_WINDOW_AUTOSIZE 這個宏是存在的
using namespace cv;

1:讀取圖片,顯示圖片,保存圖片

//read
Mat image;
image =imread("1.png",1);
if (image.data==0) //讀數據失敗

//write
 imwrite( "../../images/Gray_Image.jpg", gray_image );

//show
 namedWindow( "color image", CV_WINDOW_AUTOSIZE );
 imshow( "color image", image );

//convert BGR to Gray
//顏色轉換函數 :從源image,到目gray_image, 宏CV_BGR2GRAY規定了顏色變換方法
 cvtColor( image, gray_image, CV_BGR2GRAY );

2:圖片對象之間的reference and copy

//reference
Mat A, C;                                 // creates just the header parts
A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // here we'll know the method used (allocate matrix)
Mat B(A);                                 // Use the copy constructor
C = A;                                    // Assignment operator
//如上A,B,C都是指向同一個數據matrix,操做其中一個,同時會影響其它的數據
//可是A,B,C有不一樣的header,因此 這些不一樣的header能夠指向matrix中的一個子數據集
//ROI:region of interest
//以下,截取一張圖片中的一部分數據 的方法
Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries

//copy
Mat F = A.clone();
Mat G;
A.copyTo(G);

/*
注意:圖片的容器使用了Mat對象,Mat對象由header和data組成
header是圖片的信息:size and address pointer部分
data是圖片的顏色信息 
*/

3:老式函數cvLoadImage打開圖片的方法

//加載顯示    
IplImage* img = cvLoadImage("13.png", 1);
Mat mtx(img); // convert IplImage* -> Mat
namedWindow("Display Image", WINDOW_AUTOSIZE );

//將image圖片在Display Image這個窗口中顯示
imshow("Display Image", mtx);
cvWaitKey(0);//wait for ur enter press on the picture

4:圖像顏色數據在內存中的存儲方式

圖片就是一個平面矩陣,因此只要知道了行列座標,就能夠讀 寫對應位置的像素值了,
若是是灰度圖像,每一個位置座標上就只有一個值(用來表示灰度顏色)
若是是多通道的圖像,每一個位置上,就有BGR三個值(用來表示彩色圖像的三個份量)函數

當在圖像數據加載到內存中時:因爲內存地址是線性連續的,因此圖像的存儲方式也變成了線性的,線性存儲也有利於快速的訪問顏色數據(一個接一個的訪問,確實會快點)優化

面使用image.isContinuous();這個函數來肯定圖像數據的存儲在內存中是否是連續的。

    Mat image=imread(argv[1],1);
    if (image.data==0)
    {
        cerr<<"invalid image file to read!"<<endl;
        return 0;
    }
    //獲得顏色數據在內存空間中存放時,是否 線性是連續的 
   image.isContinuous(); // 1:連續  0:不連續

4:Mat::depth()函數

if(image.depth()==CV_8U) //查看圖像中,每一個通道的顏色數據 的深度,
//如咱們經常使用的 BGR三通道,每一個通道的值的範圍爲0-255,那麼就說顏色深度爲8位

顏色深度就是表示 每一個通道顏色的數據用了多少位,用以下幾個宏表示:
CV_8U  CV_16U
CV_8S  CV_16S  CV_32S
               CV_32F  CV_64F
               
 CV_Assert(image.depth() == CV_8U);//保證傳入數據爲true才能進行下面操做,不然會退出程序,並且會有下面的報錯,而且顯示在源程序中哪一行出錯!很是好的debug函數
OpenCV Error: Assertion failed

下面的方法中,5,6,7,都是能夠靈活的操做每一個通道的數據,用的比較多的是方法5,效率也高點!

5:遍歷圖像中每一個像素的方法

//方法1:
    Mat image=imread("1.png",1);
   CV_Assert(image.depth() == CV_8U); //0==0 
    int channels=image.channels(); //獲得圖像有多少個顏色通道
    int rows=image.rows;           //獲得圖像有多少行
    int cols=image.cols;           //獲得圖像有多少列
    cols=cols*channels;            //列數xchannel數,纔是更底層的圖像的真實列數
    unsigned char *pt;             //用來指向 每一個顏色通道的 指針,用這個指針來讀到每一個像素的顏色值,固然改變像素值也是寫這個指針指向的數值
    for (int i=0;i<rows;i++)
    {
        pt=image.ptr<unsigned char>(i);
        for (int j=0;j<cols;j++)
        {
          pt[j]=tables[pt[j]];
        }
    }
    
//小技巧:加快程序讀寫數據的速度
if (image.isContinuous())//若是顏色數據在內存中存放時,是連續存放的
{
rows=1;   //row=0
cols=cols*rows; //cols=0 ...一直到最後一個像素的顏色數據位置
}

//注意 :必定不要把  cols=cols*channels;這一條忘記了,很是重要。

//方法2:
if (image.isContinuous())
{
    uchar* p = image.data;//獲得data數據的首地址,
    for( unsigned int i =0; i < ncol*nrows; ++i)
    {
        *p= table[*p];
        p++;
    }
}

6:使用iterator(迭代器訪問圖片中的每個像素)

// 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]];
            }
        }
    }

7:on the fly(在運行過程當中實時地址計算,最慢的方法)的訪問像素的方法

// accept only char type matrices
    CV_Assert(I.depth() == CV_8U);

    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:
        {
         Mat_<Vec3b> _I = I; //注意這裏的新對象爲 Mat_  (有下劃線哦)

         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;
        }
    }

8:使用core function中的lookuptable,最快的方法改變圖像中的每一個像素

Mat lookUpTable(1, 256, CV_8U);
    uchar* p = lookUpTable.data;
    for( int i = 0; i < 256; ++i)
        p[i] = table[i];  //把咱們以前的tables寫到 Mat類型的對象中
  LUT(I, lookUpTable, J); //I是輸入的圖像,J是改變後的圖像,
//不能地每一個通道作靈活的操做
//LUT的操做過程就是使用 原始圖像的 顏色值做爲 index,在lookuptable中查到新的顏色值,
//注意 :這種方法OpenCV,作過優化,因此是最快的方法。
相關文章
相關標籤/搜索