影像讀取儲存(imread、imshow、imwrite)

這邊示範一個簡短的OpenCV的程式,用imread()讀取圖片,並將資料寫入Mat,imwrite()將Mat儲存在硬碟中,imshow()將Mat展示在螢幕上。

標頭檔

當我們使用OpenCV函式時,要先include此函式的模組,例如要用到Core模組時,我們須加入標頭檔:

#include <opencv2/core/core.hpp>

所有用到的模組都需加入,這邊為了方便,我們直接include所有模組,所以在cpp檔表頭,加入標頭檔:

#include <opencv2/opencv.hpp>

命名空間

為了使用上的安全,OpenCV有加上命名空間cv,所以我們使用此OpenCV的函式或類別時,前面需要加上cv::,為了使用上的方便,所以在cpp檔我們加上:

using namespace cv;

影像讀取

Mat imread(const string& filename, int flags=1)

  • filename:要載入的檔案名稱。
  • flags:影像標誌,flag分成三種模式,分別為彩色、灰階、原影像格式。
    flag值備註
    CV_LOAD_IMAGE_UNCHANGED<0讀入格式不變
    CV_LOAD_IMAGE_GRAYSCALE0以灰階讀入
    CV_LOAD_IMAGE_COLOR>0以BGR格式讀入

OpenCV支援的影像格式有BMP、PBM、DIB、JPEG、JPE、PNG、TIF等,常見的格式幾乎都有支援,以下的程式碼讀入"lena.jpg",並賦值給img:

Mat img = imread("lena.jpg",CV_LOAD_IMAGE_GRAYSCALE);

創建視窗

void namedWindow(const string& winname, int flags=WINDOW_AUTOSIZE)

  • winname:視窗標題。
  • flags:視窗標誌,flag常用的有兩種,分別為WINDOW_NORMAL和WINDOW_AUTOSIZE,當使用WINDOW_NORMAL時,可變更視窗的大小,當使用WINDOW_AUTOSIZE時,會產生剛好包含Mat大小的視窗,無法改變視窗大小。

秀出影像

void imshow(const string& winname, InputArray mat)

  • winname:要秀出此影像的視窗。
  • mat:要秀出的影像,當Mat為8位元時直接秀出,16位元時數值除以256後秀出,為浮點數時乘上255,使得三種格式,顯現範圍都為0~255。

我們先創建視窗,接著將Mat秀在此視窗內,當我們使用imshow這個函式時,我們需要加上waitKey(0),阻斷程式進行,這樣才可以看到視窗,以及視窗內的圖像,直到按下任一鍵後程式才繼續進行。如果流程完全不阻斷,main函式隨之進行完畢,此時視窗和影像都消失,我們會看不到想要的結果,以下為秀出影像的程式碼:

namedWindow("Display window", WINDOW_AUTOSIZE); 
imshow("Display window", img);  
waitKey(0);

等待按鍵輸入

int waitKey(int delay=0)
  • delay:等待時間,這邊主要分兩大類使用方式,當delay<=0時,程式靜止,當delay>0時,函式會等待參數時間(ms)後,返回按鍵的ASCII碼,如果這段時間沒有按鍵按下,會返回-1。
  • waitKey()只有搭配OpenCV視窗才有效果,沒有視窗的話無此暫停程式功能。
  • 可以使用這個特性搭配while迴圈,讓圖片不斷顯示,直到按下某特定按鍵後才停止。

由於esc鍵的ASCII碼為27,所以以下程式只有按下esc鍵,程式才會跳出迴圈:

while(true){ 
    imshow("Display window", img);  
    if(cvWaitKey(10)==27){  
        break; 
    } 
}

圖片儲存

bool imwrite(const string& filename, InputArray img, const vector& params=vector())

  • filename:儲存的檔案名稱。
  • img:要儲存的影像。
  • params:影像參數,以(id,value)的順序輸入,因為有些格式有參數可輸入,像JPEG壓縮品質的值從0到100,預設為95,我們可將CV_IMWRITE_JPEG_QUALITY設定值,進而改變儲存的JPEG影像品質。
  • 如果是儲存3通道彩色圖的話,要注意此時的色彩空間需為BGR,否則後續讀取強度會錯誤,B和R的強度會對調。

OpenCV支援的影像格式有BMP、PBM、DIB、JPEG、JPE、PNG、TIF等,常見的格式幾乎都有支援,以下為圖片儲存的程式碼:

imwrite ("output1.jpg ", img);
vector<int> quality;
quality.push_back(CV_IMWRITE_JPEG_QUALITY);
quality.push_back(90);
imwrite("output2.jpg", img, quality);

程式範例1

以下程式碼從硬碟讀取檔案,將影像設定成灰階圖,把影像儲存在硬碟,並將影像秀在螢幕上,當使用者按下任一鍵,或是關閉視窗後程式終止:

#include <cstdio>
#include <opencv2/opencv.hpp>
using namespace cv;

int main(){
    Mat img = imread("lena.jpg",CV_LOAD_IMAGE_GRAYSCALE);
    imwrite("output.jpg",img);  

    namedWindow("Display window", WINDOW_AUTOSIZE);  
    imshow("Display window", img);        
    waitKey(0);                          

    return 0;
}

程式範例2

以下程式碼從硬碟讀取檔案,秀在螢幕上,當使用者按下esc鍵時程式終止:

#include <cstdio>
#include <opencv2/opencv.hpp>
using namespace cv;

int main(){
    Mat img = imread("lena.jpg",CV_LOAD_IMAGE_GRAYSCALE);
    while(true){
        imshow("Display window", img);     
        if(cvWaitKey(10)==27){                      
            break;
        }
    }
    return 0;
}

imshow

回到首頁

回到OpenCV教學


  • 朝安謝

    請問一下 為什麼我在使用imshow跑出來的視窗他會一直呈現讀取狀態無法正常顯示 感恩~
    #include <opencv2/opencv.hpp>
    #include

    using namespace std;
    using namespace cv;

    int main(int argc, char** argv)
    {

    argv[1] = "c:\opencv.png";
    Mat img = imread(argv[1], CV_LOAD_IMAGE_UNCHANGED);
    if (!img.data)
    {
    cout << "error";
    return -1;
    getchar();
    }
    namedWindow("org",CV_WINDOW_AUTOSIZE);
    imshow("org", img);

    getchar();

    }

    • 李維哲(TwinkyLee)

      我猜是C:而不是C:\,或C:/

      • 朝安謝

        感謝各位~已成功

    • changson

      在imshow(“org", img);後加一行waitKey(0);試試
      imshow(“org", img);
      waitKey(0);