OpenCV開發筆記(四):圖片和視頻數據的讀取與存儲

歡迎技術交流和幫助,提供IT相關服務,索要源碼請聯繫博主QQ: 21497936,若該文爲原創文章,未經允許不得轉載
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/100735114

目錄

前言

OpenCV讀取圖片文件

OpenCV存儲圖片文件

圖片測試Demo

代碼

運行效果

OpenCV讀取視頻

OpenCV存儲視頻

視頻測試Demo

代碼

運行效果

Demo源碼

入坑

入坑一:讀取圖片成功,窗口顯示成功,但是圖片顯示失敗

參考引用

工程模板:對應版本號v1.2.0


 

 OpenCV開發專欄

OpenCV開發筆記(一):OpenCV介紹、編譯

OpenCV開發筆記(二):cvui交互界面

OpenCV開發筆記(三):圖像的概念和基本操作

OpenCV開發筆記(四):圖片和視頻數據的讀取與存儲

OpenCV開發筆記(五):讀取與操作攝像頭

持續補充中…

 

    OpenCV開發筆記(四):圖片和視頻數據的讀取與存儲

 

前言

       OpenCV對圖像進行操作,圖像包含圖片和視頻。

 

OpenCV讀取圖片文件

       讀取圖像文件,使用的imread()。

       imread()函數返回的是Mat對象,如果讀取函數文件失敗,會返回一個空矩陣(常量cv::Mat::data變量的值是NULL)。

Mat imread(const string& filename, int flags=1 )
  • filename:是被讀取或者保存的圖像文件名;
  • flag:參數值有三種情況:

        flag>0,該函數返回3通道圖像,如果磁盤上的圖像文件是單通道的灰度圖像,則會被強制轉爲3通道;

        flag=0,該函數返回單通道圖像,如果磁盤的圖像文件是多通道圖像,則會被強制轉爲單通道;

        flag<0,則函數不對圖像進行通道轉換。

       imread()函數支持多種文件格式,且該函數是根據圖像文件的內容來確定文

件格式,而不是根據文件的擴展名來確定。

       支持的圖像格式:bmp、dib、jpg、jpeg、jpe、png、pbm、pgm、ppm、sr、ras、tiff、tif、exr、jp2。(需要對應的庫支持,開發使用的庫要編譯時添加進去,然後編譯生成opencv庫)

 

OpenCV存儲圖片文件

       保存圖像文件,使用的imwrite()。

       imwrite()函數返回的是bool。

bool imwrite(const string& filename, 
           InputArray image,
           const vector<int>& params=vector<int>())

       filename是存成指定的文件名,注意格式是由指定的文件擴展名確定。

       PNG-是無損壓縮格式,推薦使用。

       BMP-格式是無損格式,但是一般不進行壓縮,文件尺寸非常大;

       JPEG-格式的文件嬌小,但是JPEG是有損壓縮,會丟失一些信息。

       並不是所有的 Mat 對象都可以存爲圖像文件,目前支持的格式只有8U類型的單通道和3通道(顏色順序爲 BGR)矩陣;如果需要要保存16U格式圖像, 只能使用PNG、JPEG 2000和TIFF格式。

       如果希望將其他格式的矩陣保存爲圖像文件,可以先用Mat::convertTo()函數或者cvtColor()函數將矩陣轉爲可以保存的格式。

       注意:在保存文件時,如果文件已經存在,imwrite()函數不會進行提醒,將直接覆蓋掉以前的文件。

 

圖片測試Demo

代碼

#if TEST_IMAGE
    // 讀取
    cv::Mat image = cv::imread("1.jpg");
    // 判斷是否讀取成功
    if(image.data == NULL)
    {
        QMessageBox::warning(0, "讀取圖片失敗", "1.jpg");
        return;
    }
    // 顯示
    cv::imshow("readImage", image);
    // 作一個圖像行列轉換操作,再保存
    image = image.t();
    // 保存
    if(!cv::imwrite("1 to 2.jpg", image))
    {
        QMessageBox::warning(0, "保存失敗", "1.jpg");
        return;
    }
#endif

運行效果

          

 

OpenCV讀取視頻

       圖像文件,可以根據文件擴展名得知圖像的格式。但是此經驗並不能推廣到視頻文件中。有時候會碰到奇怪的問題,都是avi視頻文件,有的能用OpenCV打開,有的不能。

       視頻的格式主要由壓縮算法決定,就是視頻編解碼器。視頻文件能讀或者寫,關鍵看是否有相應的編解碼器。

       OpenCV 2中提供了兩個類來實現視頻的讀寫。讀視頻的類是VideoCapture,寫視頻的類是VideoWriter。

       VideoCapture 既可以從視頻文件讀取圖像,也可以從攝像頭讀取圖像。可以使用該類的構造函數打開視頻文件或者攝像頭。如果 VideoCapture 對象已經創建,也可以使用VideoCapture::open()打開,VideoCapture::open()函數會自動調用VideoCapture::release()函數,先釋放已經打開的視頻,然後再打開新視頻。

OpenCV存儲視頻

       使用OpenCV創建視頻與讀視頻不同的是,需要在創建視頻時設置一系列參數,包括:文件名,編解碼器,幀率,寬度和高度等。

       編解碼器使用四個字符表示,可以是:

  • CV_FOURCC('M','J','P','G')
  • CV_FOURCC('X','V','I','D')
  • CV_FOURCC('D','I','V','X')
  • 還有其他的

如果使用某種編解碼器無法創建視頻文件,請嘗試其他的編解碼器。

       將圖像寫入視頻可以使用VideoWriter::write()函數,VideoWriter類中也重載了<<操作符,使用起來非常方便。另外需要注意:待寫入的圖像尺寸必須與創建視頻時指定的尺寸一致。

 

視頻測試Demo

代碼

#if TEST_VIDEO
    cv::VideoCapture videoCapture;
    // 打開視頻
    if(!videoCapture.open("1.mp4"))
    {
        QMessageBox::warning(0, "讀取視頻失敗", "1.mp4");
        return;
    }
    int width = 0;
    int height = 0;
    for(;;)
    {
        cv::Mat frame;
        videoCapture >> frame;
        // 第一次進入,記錄視頻尺寸
        if(width == 0)
        {
            width = frame.cols;
            height = frame.rows;
        }
        // 最後一幀之後爲空,退出
        if(frame.empty())
        {
            break;
        }
        // 顯示
        cv::imshow("readVideo", frame);
        // 等待1s,有按鍵輸入立即結束本次
        if(cv::waitKey(1) >= 0)
            break;

    }
    // 將視頻輸入流返回到第0幀
    videoCapture.set(cv::CAP_PROP_POS_FRAMES, 0);
    cv::VideoWriter videoWrite;
    // 翻轉操作了
    width = width + height;
    height = width - height;
    width = width - height;
    if(!videoWrite.open("1 to 1.avi", CV_FOURCC('M','J','P','G'), 25, cv::Size(width, height)))
    {
        QMessageBox::warning(0, "保存視頻失敗", "1 to 1.avi");
        return;
    }
    QString version = "v1.3.0";
    QString text = QString("OpenCVDemo %1 QQ21497936 blog.csdn.net/qq21497936").arg(version);
    for(;;)
    {
        cv::Mat frame;
        videoCapture >> frame;
        if(frame.empty())
        {
            break;
        }
        // 沿對角線行列翻轉
        frame = frame.t();
        cv::putText(frame,
                    cv::String(text.toUtf8().data()),
                    cv::Point(0, height / 2),
                    cv::FONT_HERSHEY_SCRIPT_SIMPLEX,
                    0.8,
                    cv::Scalar(0,0,255),
                    3,
                    8,
                    false);
        cv::imshow("readVideo", frame);
        videoWrite << frame;
        if(cv::waitKey(1) >= 0)
            break;
    }
#endif

 

運行效果

然後

 

Demo源碼

void OpenCVManager::testImageAndVideo()
{
#define TEST_IMAGE (0)
#define TEST_VIDEO (1)

#if TEST_IMAGE
    // 讀取
    cv::Mat image = cv::imread("1.jpg");
    // 判斷是否讀取成功
    if(image.data == NULL)
    {
        QMessageBox::warning(0, "讀取圖片失敗", "1.jpg");
        return;
    }
    // 顯示
    cv::imshow("readImage", image);
    // 作一個圖像行列轉換操作,再保存
    image = image.t();
    // 保存
    if(!cv::imwrite("1 to 2.jpg", image))
    {
        QMessageBox::warning(0, "保存失敗", "1.jpg");
        return;
    }
#endif

#if TEST_VIDEO
    cv::VideoCapture videoCapture;
    // 打開視頻
    if(!videoCapture.open("1.mp4"))
    {
        QMessageBox::warning(0, "讀取視頻失敗", "1.mp4");
        return;
    }
    int width = 0;
    int height = 0;
    for(;;)
    {
        cv::Mat frame;
        videoCapture >> frame;
        // 第一次進入,記錄視頻尺寸
        if(width == 0)
        {
            width = frame.cols;
            height = frame.rows;
        }
        // 最後一幀之後爲空,退出
        if(frame.empty())
        {
            break;
        }
        // 顯示
        cv::imshow("readVideo", frame);
        // 等待1s,有按鍵輸入立即結束本次
        if(cv::waitKey(1) >= 0)
            break;

    }
    // 將視頻輸入流返回到第0幀
    videoCapture.set(cv::CAP_PROP_POS_FRAMES, 0);
    cv::VideoWriter videoWrite;
    // 翻轉操作了
    width = width + height;
    height = width - height;
    width = width - height;
    if(!videoWrite.open("1 to 1.avi", CV_FOURCC('M','J','P','G'), 25, cv::Size(width, height)))
    {
        QMessageBox::warning(0, "保存視頻失敗", "1 to 1.avi");
        return;
    }
    QString version = "v1.2.0";
    QString text = QString("OpenCVDemo %1 QQ21497936 blog.csdn.net/qq21497936").arg(version);
    for(;;)
    {
        cv::Mat frame;
        videoCapture >> frame;
        if(frame.empty())
        {
            break;
        }
        // 沿對角線行列翻轉
        frame = frame.t();
        cv::putText(frame,
                    cv::String(text.toUtf8().data()),
                    cv::Point(0, height / 2),
                    cv::FONT_HERSHEY_SCRIPT_SIMPLEX,
                    0.8,
                    cv::Scalar(0,0,255),
                    3,
                    8,
                    false);
        cv::imshow("readVideo", frame);
        videoWrite << frame;
        if(cv::waitKey(1) >= 0)
            break;
    }
#endif
}

 

入坑

入坑一:讀取圖片成功,窗口顯示成功,但是圖片顯示失敗     

     

解決方法:使用了中文作爲窗口標題要改爲英文標題

      

 

參考引用

       《OpenCV入門教程》

 

工程模板:對應版本號v1.2.0

       對應版本號v1.2.0

 

歡迎技術交流和幫助,提供IT相關服務,索要源碼請聯繫博主QQ: 21497936,若該文爲原創文章,未經允許不得轉載
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/100735114

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章