日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

OpenCV 笔记(02)— 图像显示、保存、腐蚀、模糊、canny 边缘检测(imread、imshow、namedWindow、imwrite)

發布時間:2023/11/28 生活经验 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV 笔记(02)— 图像显示、保存、腐蚀、模糊、canny 边缘检测(imread、imshow、namedWindow、imwrite) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OpenCV 提供兩種用戶界面選項:

  • 基于原生用戶界面的基本界面,適用于 Mac OS Xcocoacarbon,以及適用于 LinuxWindows 用戶界面的 GTK ,這些界面在編譯 OpenCV 時被默認選擇。
  • 基于 Qt 庫的略微更高級的界面,這是跨平臺的界面。必須在編譯 OpenCV 之前,在 CMake 中手動啟用 Qt 選項。

1. 圖像顯示

OpenCV 中,圖像顯示過程非常簡單,只需用 imread 函數載入到新版本的圖像存儲數據結構 Mat 類中,然后用 imshow 函數顯示即可。

#include <iostream>
#include "opencv2/opencv.hpp"using namespace cv;	
// 使用 cv 命名空間,否則后面需要使用 cv::Mat, cv::imread 等帶cv前綴int main()
{Mat image;image = imread("./image/dog.jpg");	// 載入圖像if (image.empty())	// 或者 if(!image.data) 判斷圖片是否加載成功{std::cout << "image not exist";return -1;}namedWindow("demo 圖片");imshow("demo 圖片", image);	// 顯示圖像imwrite("save.jpg", image);waitKey(0);	// 等待任意按鍵按下,退出圖片顯示return 0;
}

顯示結果

代碼分析:

1.1 Mat 類

Mat 類是用于保存圖像以及其他矩陣數據的數據結構, 默認情況下其尺寸為 0。我們也可以指定其初始尺寸, 比如定義一個 Mat 類對象, 就要寫 cv::Mat pic( 320, 640, cv::Scalar(100))

1.2 imread 載入圖像函數

首先來看 imread 函數, 其用于讀取文件中的圖片到 OpenCV 中。可以在 OpenCV 官方文檔中查到它的原型, 如下。

Mat imread( const String& filename, int flags = IMREAD_COLOR )
  • 第一個參數, const string& 類型的 filename , 填我們需要載入的圖片路徑名。
  • 第二個參數, int 類型的 flags , 為載入標識,它指定一個加載圖像的顏色類型。默認值為 1 這個參數可以在 OpenCV 中標識圖像格式的枚舉體中取值,詳情如下:
enum ImreadModes {IMREAD_UNCHANGED            = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).IMREAD_GRAYSCALE            = 0,  //!< If set, always convert image to the single channel grayscale image (codec internal conversion).IMREAD_COLOR                = 1,  //!< If set, always convert image to the 3 channel BGR color image.IMREAD_ANYDEPTH             = 2,  //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.IMREAD_ANYCOLOR             = 4,  //!< If set, the image is read in any possible color format.IMREAD_LOAD_GDAL            = 8,  //!< If set, use the gdal driver for loading the image.IMREAD_REDUCED_GRAYSCALE_2  = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2.IMREAD_REDUCED_COLOR_2      = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.IMREAD_REDUCED_GRAYSCALE_4  = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.IMREAD_REDUCED_COLOR_4      = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.IMREAD_REDUCED_GRAYSCALE_8  = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.IMREAD_REDUCED_COLOR_8      = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.IMREAD_IGNORE_ORIENTATION   = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.};

所以有時候這個參數在調用時可以忽略,就表示載入三通道的彩色圖像。

因為 flagsint 型的變量,若我們不在這個枚舉體中取固定的值, 可以這樣進行:

  • flags>0 返回一個3 通道的彩色圖像;
  • flags=0 返回灰度圖像;
  • flags<0 返回包含 Alpha 通道的加載圖像;

注意:若以彩色模式載入圖像,解碼后的圖像會以 BGR 的通道順序進行存儲,即藍、綠、紅的順序,而不是通常的 RGB 的順序。

1.3 imshow 顯示圖像函數

imshow() 函數用于在指定的窗口中顯示一幅圖像, 函數原型如下。

void imshow(const String& winname, InputArray mat);
  • 第一個參數: const string& 類型的 winname ,填需要顯示的窗口標識名稱。
  • 第二個參數: InputArray 類型的 mat , 填需要顯示的圖像。

imshow 函數用于在指定的窗口中顯示圖像。如果窗口是用 CV_WINDOW_AUTOSIZE (默認值)標志創建的,那么顯示圖像原始大小。否則,將圖像進行縮放以適合窗口。

imshow 函數縮放圖像,取決于圖像的深度,具體如下。

  • 如果載入的圖像是 8 位無符號類型(8-bit unsigned),就顯示圖像本來的樣子。
  • 如果圖像是 16 位無符號類型(16-bit unsigned)或 32 位整型( 32-bit integer),便用像素值除以 256。也就是說,值的范圍是[0,255 x 256]映射到[0,255]。
  • 如果圖像是 32 位浮點型(32-bit floating-point), 像素值便要乘以 255。也就是說, 該值的范圍是[0,1]映射到[0,255]。

1.4 namedWindow 創建窗口函數

namedWindow 函數用于創建一個窗口。若是簡單地進行圖片顯示,可以略去namedWindow 函數的調用,即先調用 imread 讀入圖片,然后用 imshow 直接指定出窗口名進行顯示即可。

但需要在顯示窗口之前就用到窗口名時, 比如我們后面會馬上講到滑動條的使用, 要指定滑動條依附到某個窗口上, 就需要 namedWindow 函數先創建出窗口, 顯式地規定窗口名稱了。

namedWindow 的函數原型如下:

void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
  1. 第一個參數, const string& 型的 name , 填寫被用作窗口的標識符的窗口名稱;
  2. 第二個參數, int 類型的 flags , 窗口的標識, 可以填如下幾種值;
enum WindowFlags {WINDOW_NORMAL     = 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size.WINDOW_AUTOSIZE   = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed.WINDOW_OPENGL     = 0x00001000, //!< window with opengl support.WINDOW_FULLSCREEN = 1,          //!< change the window to fullscreen.WINDOW_FREERATIO  = 0x00000100, //!< the image expends as much as it can (no ratio constraint).WINDOW_KEEPRATIO  = 0x00000000, //!< the ratio of the image is respected.WINDOW_GUI_EXPANDED=0x00000000, //!< status bar and tool barWINDOW_GUI_NORMAL = 0x00000010, //!< old fashious way};

namedWindow 函數的作用是通過指定的名字, 創建一個可以作為圖像和進度條的容器窗口。如果具有相同名稱的窗口已經存在, 則函數不做任何事情。
我們可以調用 destroyWindow() 或者 destroyAllWindows() 函數來關閉窗口, 并取消之前分配的與窗口相關的所有內存空間。

但是事實上, 對于代碼量不大的簡單程序來說, 我們完全沒有必要手動調用上述的 destroyWindow() 或者 destroyAllWindows() 函數, 因為在退出時, 所有的資源和應用程序的窗口會被操作系統自動關閉。

1.5 imwrite 保存圖像函數

OpenCV 中, 輸出圖像到文件一般采用 imwrite 函數, 它的聲明如下。

bool imwrite( const String& filename, InputArray img,const std::vector<int>& params = std::vector<int>());
  1. 第一個參數,const string& 類型的 filename,填需要寫入的文件名。注意要帶上后綴,如“save.jpg ”。
  2. 第二個參數, InputArray 類型的 img , 一般填一個 Mat 類型的圖像數據。
  3. 第三個參數, const vector<int>& 類型的 params , 表示為特定格式保存的參數編碼。它有默認值 vector<int>() , 所以一般情況下不需要填寫。而如果要填寫的話,有下面這些需要了解的地方:
  • 對于 JPEG 格式的圖片, 這個參數表示從 0 到100 的圖片質量 ( CV _IMWRITE_JPEG_ QUALITY ), 默認值是 95。
  • 對于 PNG 格式的圖片, 這個參數表示壓縮級別( CV_IMWRITE_PNG_COMPRESSION ) 從 0 到 9。較高的值意味著更小的尺寸和更長的壓縮時間,默認值是 3。
  • 對于 PPMPGM 、或 PBM 格式的圖片, 這個參數表示一個二進制格式標志( CV _IMWRITE_PXM_ BINARY ),取值為 0 或1 , 默認值是 1 。

注意: imwrite 函數用于將圖像保存到指定的文件。圖像格式是基于文件擴展名的,可保存的擴展名和 imread 中可以讀取的圖像擴展名一致。

2. 圖像腐蝕

再來看如何用 OpenCV 實現最基本的形態學運算之腐蝕, 即用圖像中的暗色部分“腐蝕”掉圖像中的高亮部分。

#include <iostream>
#include "opencv2/highgui.hpp"  // OpenCV highgui 模塊頭文件
#include "opencv2/imgproc.hpp"  // OpenCV 圖像處理頭文件using namespace cv;int main()
{Mat src = imread("./image/dog.jpg");	// 載入圖像if (src.empty())	// 或者 if(!image.data) 判斷圖片是否加載成功{std::cout << "image not exist";return -1;}imshow("原始圖片", src);	// 顯示圖像// 進行腐蝕操作Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));Mat dst;erode(src, dst, element);imshow("腐蝕圖片", dst);// waitKey(30)等待30毫秒,以此檢查用戶是否使用任何鍵停止應用程序的執行。waitKey(0);	// 等待任意按鍵按下,退出圖片顯示,return 0;
}

程序首先依然是載入和顯示一幅圖像,然后定義一個 Mat 類型的變量來獲得 getStructuringElement 函數的返回值,而 getStructuringElement 函數的返回值為指定形狀和尺寸的結構元素(內核矩陣)。參數準備完畢,接著便可以調用 erode 函數進行圖像腐蝕操作,最后調用 imshow 函數進行顯示,用 waitKey 函數等待按鍵按下,以便能讓窗口一直顯示。

顯示結果:

3. 圖像模糊

接著讓我們看看用 OpenCV 對圖像進行均值濾波操作,模糊一幅圖像的代碼如何書寫。主要使用進行均值濾波操作的 blur 函數,代碼如下:

#include <iostream>
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"using namespace cv;int main()
{Mat src = imread("./image/dog.jpg");	// 載入圖像if (src.empty())	// 或者 if(!image.data) 判斷圖片是否加載成功{std::cout << "image not exist";return -1;}imshow("原始圖片", src);	// 顯示圖像// 進行均值濾波模糊操作Mat dst;blur(src, dst, Size(15, 15));imshow("模糊圖片", dst);waitKey(0);	// 等待任意按鍵按下,退出圖片顯示return 0;
}

顯示結果

4. 邊緣檢測

接著我們來看看如何用 OpenCV 進行 canny 邊緣檢測。載入圖像,并將其轉成灰度圖,再用 blur 函數進行圖像模糊以降噪,然后用 canny 函數進行邊緣檢測,最后進行顯示。

#include <iostream>
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"using namespace cv;int main()
{Mat src = imread("./image/dog.jpg");	// 載入圖像if (src.empty())	// 或者 if(!image.data) 判斷圖片是否加載成功{std::cout << "image not exist";return -1;}imshow("原始圖片", src);	// 顯示圖像Mat dst, edge, gray;// 創建與原圖片同類型和大小的矩陣( dst )dst.create(src.size(), src.type());// 將原圖像轉換為灰度圖像 OpenCV2 版本// cvtColor(src, gray, CV_BGR2GRAY)// OpenCV3 或者 OpenCV4 版本cvtColor(src, gray, COLOR_BGR2GRAY);// 先使用5 x 5 內核來降噪blur(gray, edge, Size(5, 5));// 運行Canny 算子Canny(edge, edge, 1, 3, 3);imshow("Canny 邊緣檢測", edge);waitKey(0);	// 等待任意按鍵按下,退出圖片顯示return 0;
}

顯示結果:

5. 其它示例

#include <iostream>
#include <string>
#include <sstream>
using namespace std;// OpenCV includes
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;const int CV_GUI_NORMAL= 0x10;int main( int argc, const char** argv )
{// Read imagesMat lena= imread("../lena.jpg");Mat photo= imread("../photo.jpg");// Create windowsnamedWindow("Lena", WINDOW_NORMAL);// Checking if Lena image has been loadedif (!lena.data) {cout << "Lena image missing!" << endl;return -1;}namedWindow("Photo", WINDOW_AUTOSIZE);if (!photo.data) {cout << "Lena image missing!" << endl;return -1;}// Move window// moveWindow函數將窗口移動到桌面的任何區域moveWindow("Lena", 10, 10);moveWindow("Photo", 520, 10);// show imagesimshow("Lena", lena);imshow("Photo", photo); // Resize window, only non autosize// resizeWindow函數將Lena窗口的大小調整為512像素,該函數有三個參// 數:window name、width和height。resizeWindow("Lena", 512, 512); // wait for any key presswaitKey(0);// Destroy the windowsdestroyWindow("Lena");destroyWindow("Photo");// Create 10 windowsfor(int i =0; i< 10; i++){ostringstream ss;ss << "Photo " << i;namedWindow(ss.str());moveWindow(ss.str(), 20*i, 20*i);imshow(ss.str(), photo);}waitKey(0);// Destroy all windowsdestroyAllWindows();return 0;
}

以上都是原生 OpenCV 的一些基本圖像處理過濾器,但也有新的開源替代品,它們能夠添加更多功能,比如 cvui (https://dovyski.github.io/cvui/) 或 OpenCVGUI (https://damiles.github.io/OpenCVGUI/)。

總結

以上是生活随笔為你收集整理的OpenCV 笔记(02)— 图像显示、保存、腐蚀、模糊、canny 边缘检测(imread、imshow、namedWindow、imwrite)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。