1. 程式人生 > >opencv 影象讀取顯示和畫素操作

opencv 影象讀取顯示和畫素操作

從今天起,開始從頭系統學習下opencv,下面記錄下影象的基本操作:

1. 影象的讀取和顯示

Mat image = imread(imagePath, 1);
第二個引數表示圖片讀入的方式(flags可以預設,預設時flags=1,表示以彩色圖片方式讀入圖片)
flags>0時表示以彩色方式讀入圖片
flags=0時表示以灰度圖方式讀入圖片
flags<0時表示以圖片的本來的格式讀入圖片。

char *f = "E:\\opencv\\sources\\samples\\wp8\\OpenCVXaml\\OpenCVXaml\\Assets\\Lena.png";
    Mat lena;
    lena = imread(f);
    imshow("lena", lena);
    IplImage * lena2;
    //lena2 = cvLoadImage(f, CV_LOAD_IMAGE_GRAYSCALE); // 載入灰度圖
    lena2 = cvLoadImage(f, CV_LOAD_IMAGE_UNCHANGED);//載入原始影象
    cvNamedWindow("lena2", CV_WINDOW_AUTOSIZE);//建立視窗
    cvShowImage("lena2", lena2);
    -

畫素讀取和操作

1. 利用cv::Mat的at函式,直接訪問具體地址

void get_setImagePixel(char *imagePath
, int x , int y) { // Mat image = imread(imagePath , 0); Mat image = imread(imagePath, 1); //得寬高 int w = image.cols; int h = image.rows; int channels = image.channels(); if (x < w && y < h) { //灰度圖,畫素為單通道 if (channels == 1) { int
pixel = image.at<uchar>(x, y); cout << "灰度影象,處的灰度值為" << pixel << endl; } else { //通過實驗,彩色影象的預設儲存是bgr, 且儲存的格式如下 //讀取 int b = image.at<Vec3b>(x, y)[0]; // b = image.at<uchar>(x,y*3); cout << b << endl; int g = image.at<Vec3b>(x, y)[1]; //g = image.at<uchar>(x, y * 3 + 1); cout << g << endl; int r = image.at<Vec3b>(x, y)[2]; //r = image.at<uchar>(x, y * 3 + 1); cout << r << endl; //設定畫素值 image.at<Vec3b>(x, y)[0] = 255; image.at<Vec3b>(x, y)[1] = 255; image.at<Vec3b>(x, y)[2] = 255; } } imshow("cc", image); }

2. 利用Mat 的prt 函式:行首地址訪問

void get_setImagePixel2(char *imagePath, int x, int y)
{
    Mat image = imread(imagePath, 1);
    //得寬高
    int w = image.cols;
    int h = image.rows;
    int channels = image.channels();
    //如果影象連續 ,可以將資料轉化為1維陣列,提高訪問效率,但對少量畫素訪問就沒必要
    //if (image.isContinuous())
    //{
    //  //reshape函式用於改變矩陣維度  
    //  //影象行數為1,列數為原先的行數乘上列數  
    //  image.reshape(1, image.cols*image.rows);
    //}

    //獲得第y行的首地址
    uchar *data = image.ptr<uchar>(y);
    int position = x*channels;
    if (channels == 1)
    {
        int pixel = data[position];
        cout << "灰度影象,處的灰度值為" << pixel << endl;
    }
    else
    {
        //通過實驗,彩色影象的預設儲存是bgr, 且儲存的格式如下

        //讀取
        int b = data[position];
        cout << b << endl;
        int g = data[position+1];
        cout << g << endl;
        int r = data[position+2];
        cout << r << endl;

        //設定畫素值
        data[position] = 255;
        data[position+1] = 255;
        data[position+2] = 255;
    }
    imshow("cc", image);
}

3. 利用迭代器遍歷影象

void get_setImagePixel3(char *imagePath, int x, int y)
{
    Mat image = imread(imagePath, 1);
    //得寬高
    int w = image.cols;
    int h = image.rows;
    int channels = image.channels();


    if (channels == 1)
    {
        //得到初始位置的迭代器  
        Mat_<uchar>::iterator it = image.begin<uchar>();
        //得到終止位置的迭代器  
        Mat_<uchar>::iterator itend = image.end<uchar>();
        int pixel = *(it + y * w + x);
        cout << "灰度影象,處的灰度值為" << pixel << endl;
    }
    else
    {
        //得到初始位置的迭代器  
        Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
        //得到終止位置的迭代器  
        Mat_<Vec3b>::iterator itend = image.end<Vec3b>();
        //讀取
        it = it + y * w + x;
        int b = (*it)[0];
        cout << b << endl;
        int g = (*it)[1];
        cout << g << endl;
        int r = (*it)[2];
        cout << r << endl;


        //設定畫素值
            (*it)[0] = 255;
            (*it)[1] = 255;
            (*it)[2] = 255;

    }
    imshow("cc", image);

}

若是大量訪問資料和更改資料時用第二種方式效率高。

Node: 在修改畫素時候,最好先用變數儲存,設定好了再賦值給Mat成員物件,如data,因為如果直接進行操作時,當一個分量值大於255時,向前進1的原則,則會修改前面畫素的值,如下:

void colorReduce(cv::Mat&image, int div)
{
    int nl = image.rows; //影象的行數  
    //影象每行的畫素數  
    int nc = image.cols * image.channels();
    for (int j = 0; j<nl; j++)
    {
        //得到第j行的首地址  
        uchar* data = image.ptr<uchar>(j);
        //遍歷每行的畫素  
        for (int i = 0; i<nc; i++)
        {
            //printf("%d    ", data[i]);
            //data[i] = data[i] / div*div + 6;// 這裡需要用c來儲存,因為如果大於255時會向前進1,則影響前面的畫素,data[i] 會自己變得小255
            int c = data[i] / div*div + 100;        
            data[i] =  c > 255 ? 255 : c;    //將每個畫素值都變為div的倍數,即將顏色數縮減了div倍                         

        }
    }
}