一、引言
1.1介紹
OpenCV(Open Source Computer Vision Library)是一個功能強大的開源計算機視覺庫,廣泛應用于圖像和視頻處理、目標檢測、機器學習等領域。本文將全面解析 OpenCV 中常用的函數接口,幫助讀者快速掌握 OpenCV 的核心功能。
本文將按照功能模塊分類,詳細介紹 OpenCV 中的各類函數接口,并提供豐富的 C++ 代碼示例。內容涵蓋圖像讀取與顯示、圖像處理、特征提取、視頻處理、機器學習等多個方面。
1.2 準備
- 開發環境:
Qt5.14.2;OpenCV4.5.4
附:點擊下載本文所用例子中使用的OpenCV4.5.4版本編譯好的庫 - 引入依賴庫
INCLUDEPATH += "D:/opencv/opencv-4.5.4/build/include"
INCLUDEPATH += "D:/opencv/opencv-4.5.4/build/include/opencv2"
DEPENDPATH += "D:/opencv/opencv-4.5.4/build/x64/vc15/lib"
LIBS += "D:/opencv/opencv-4.5.4/build/x64/vc15/lib/opencv_world454d.lib"
- 引入頭文件
//引入opencv頭文件和命名空間
#include <opencv.hpp>
using namespace cv;
附帶說明:后面的特征提取如SURF算法等高階調用,要依賴帶有opencv_contrib模塊的opencv庫,并添加頭文件
//引入頭文件和命名空間,在opencv_contrib模塊里
#include <opencv2/xfeatures2d.hpp>
using namespace cv::xfeatures2d;
二、OpenCV 基礎:圖像讀取、顯示與保存
2.1 圖像讀取:imread 函數
imread函數用于從文件中讀取圖像,支持多種圖像格式,如 JPEG、PNG、BMP 等。
//圖像讀,顯示,寫
void MainWindow::on_bt1_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}imshow(QString("TestSrc").toStdString(), image);// 修改圖像(例如,轉換為灰度圖)Mat grayImage;cvtColor(image, grayImage, COLOR_BGR2GRAY);// 保存圖像bool saved = imwrite("gray_test.jpg", grayImage);imshow(QString("TestDsc").toStdString(), grayImage);if (saved) {qDebug() << QString("圖像保存成功!");} else {qDebug() << QString("圖像保存失敗!");}return;
}
imread函數的第二個參數是一個標志,指定圖像的讀取方式:
- IMREAD_COLOR:讀取彩色圖像,忽略透明度(默認值);
- IMREAD_GRAYSCALE:以灰度模式讀取圖像;
- IMREAD_UNCHANGED:讀取包含 Alpha 通道的圖像
測試結果:
2.2 圖像顯示:imshow 和 namedWindow 函數
imshow函數用于在窗口中顯示圖像,而namedWindow函數用于創建一個窗口。
QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// 創建窗口namedWindow(QString("TestSrc").toStdString(), WINDOW_AUTOSIZE); // 創建一個自動調整大小的窗口// 顯示圖像imshow(QString("TestSrc").toStdString(), image);// 等待按鍵事件waitKey(0); // 0表示無限等待,直到用戶按下任意鍵return;
}
namedWindow函數的第二個參數可以是:
- WINDOW_AUTOSIZE:窗口大小自動適應圖像大小
- WINDOW_NORMAL:窗口大小可手動調整
2.3 圖像保存:imwrite 函數
imwrite函數用于將圖像保存到文件中。
//測試寫入
void MainWindow::on_bt3_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// 修改圖像(例如,轉換為灰度圖)Mat grayImage;cvtColor(image, grayImage, COLOR_BGR2GRAY);// 保存圖像bool saved = imwrite("gray_test.jpg", grayImage);if (saved) {qDebug() << QString("圖像保存成功!");} else {qDebug() << QString("圖像保存失敗!");}return;
}
mwrite函數的第二個參數是要保存的圖像,第三個參數是一個可選的參數向量,用于指定特定格式的保存選項。
三、圖像處理:濾波、邊緣檢測與形態學操作
3.1 圖像濾波:平滑與降噪
圖像濾波是圖像處理中常用的操作,用于平滑圖像、降噪或增強特定特征。
3.1.1 均值濾波:blur 函數
均值濾波是一種簡單的線性濾波方法,它用鄰域內像素的平均值代替中心像素的值。
//均值濾波
void MainWindow::on_bt4_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// 均值濾波Mat blurredImage;blur(image, blurredImage, Size(5, 5)); // 5x5的均值濾波器// 顯示原始圖像和濾波后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), blurredImage);waitKey(0);return;
}
3.1.2 高斯濾波:GaussianBlur 函數
高斯濾波是一種常用的線性濾波方法,它用高斯核來對圖像進行卷積,能夠有效抑制高斯噪聲。
QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// 高斯濾波Mat gaussianImage;GaussianBlur(image, gaussianImage, Size(5, 5), 0, 0); // 5x5的高斯濾波器// 顯示原始圖像和濾波后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), gaussianImage);waitKey(0);return;
}
3.1.3 中值濾波:medianBlur 函數
中值濾波是一種非線性濾波方法,它用鄰域內像素的中值代替中心像素的值,能夠有效去除椒鹽噪聲。
//中值濾波
void MainWindow::on_bt6_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// 中值濾波Mat medianImage;medianBlur(image, medianImage, 5); // 5x5的中值濾波器// 顯示原始圖像和濾波后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), medianImage);waitKey(0);return;
}
}
3.2 邊緣檢測
邊緣檢測是計算機視覺中的重要任務,用于識別圖像中亮度變化明顯的區域。
3.2.1 Canny 邊緣檢測:Canny 函數
Canny 邊緣檢測是一種多階段的邊緣檢測算法,包括高斯平滑、梯度計算、非極大值抑制和雙閾值處理。
//Canny邊緣檢測
void MainWindow::on_bt7_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// Canny邊緣檢測Mat edges;Canny(image, edges, 50, 150); // 低閾值50,高閾值150// 顯示原始圖像和處理后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), edges);waitKey(0);return;
}
測試結果:
3.2.2 Sobel 邊緣檢測:Sobel 函數
Sobel 算子是一種常用的邊緣檢測算子,用于計算圖像灰度函數的近似梯度。
// Sobel邊緣檢測
void MainWindow::on_bt8_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// Sobel邊緣檢測Mat sobelx, sobely, sobel;// 計算x和y方向的梯度Sobel(image, sobelx, CV_64F, 1, 0, 3);Sobel(image, sobely, CV_64F, 0, 1, 3);// 合并梯度convertScaleAbs(sobelx, sobelx);convertScaleAbs(sobely, sobely);addWeighted(sobelx, 0.5, sobely, 0.5, 0, sobel);// 顯示原始圖像和處理后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), sobely);waitKey(0);return;
}
測試結果:
3.3 形態學操作
形態學操作是基于圖像形狀的一系列圖像處理操作,主要包括腐蝕、膨脹、開運算和閉運算。
3.3.1 腐蝕:erode 函數
腐蝕操作會減小圖像中的前景區域,常用于去除小的噪聲點。
//腐蝕
void MainWindow::on_bt9_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// 創建結構元素Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));// 腐蝕操作Mat eroded;erode(image, eroded, element);// 顯示原始圖像和處理后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), eroded);waitKey(0);return;
}
測試結果:
3.3.2 膨脹:dilate 函數
膨脹操作會增大圖像中的前景區域,常用于連接斷裂的物體。
//膨脹
void MainWindow::on_bt10_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// 創建結構元素Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));// 膨脹操作Mat dilated;dilate(image, dilated, element);// 顯示原始圖像和處理后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc").toStdString(), dilated);waitKey(0);return;
}
測試結果:
3.3.3 開運算和閉運算:morphologyEx 函數
開運算和閉運算都是復合操作,開運算先腐蝕后膨脹,閉運算先膨脹后腐蝕。
//開閉運算
void MainWindow::on_bt12_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// 創建結構元素Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));// 開運算Mat opened;morphologyEx(image, opened, MORPH_OPEN, element);// 閉運算Mat closed;morphologyEx(image, closed, MORPH_CLOSE, element);// 顯示原始圖像和處理后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Open").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Close").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc_Open").toStdString(), opened);imshow(QString("Dsc_Close").toStdString(), closed);waitKey(0);return;
}
測試結果如下:
四、顏色空間轉換與操作
4.1 顏色空間轉換:cvtColor 函數
cvtColor函數用于在不同顏色空間之間進行轉換,如 BGR 到灰度、BGR 到 HSV 等。
//顏色轉換
void MainWindow::on_bt13_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// BGR到灰度Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);// BGR到HSVMat hsv;cvtColor(image, hsv, COLOR_BGR2HSV);// 顯示原始圖像和處理后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Gray").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_HSV").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc_Gray").toStdString(), gray);imshow(QString("Dsc_HSV").toStdString(), hsv);waitKey(0);return;}
測試結果顯示:
4.2 顏色分割:inRange 函數
inRange函數用于在圖像中找到特定顏色范圍的區域,常用于顏色分割。
//顏色分割
void MainWindow::on_bt14_clicked()
{QString fileName = QFileDialog::getOpenFileName(this,QString("文件對話框"),"E:/test/QtTest/WidgetTest/TestOpencv/bin/debug64/Out/OutImg/",QString("圖片(*.jpg *.png);"));// 讀取圖像Mat image = imread(fileName.toStdString(), IMREAD_COLOR);if (image.empty()) {qDebug() << QString("無法讀取圖像!");return;}// 轉換到HSV顏色空間Mat hsv;cvtColor(image, hsv, COLOR_BGR2HSV);// 定義藍色的HSV范圍Scalar lower_blue = Scalar(100, 150, 0);Scalar upper_blue = Scalar(140, 255, 255);// 創建掩碼Mat mask;inRange(hsv, lower_blue, upper_blue, mask);// 應用掩碼Mat result;bitwise_and(image, image, result, mask);// 顯示原始圖像和處理后的圖像namedWindow(QString("Src").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Mask").toStdString(), WINDOW_AUTOSIZE);namedWindow(QString("Dsc_Result").toStdString(), WINDOW_AUTOSIZE);imshow(QString("Src").toStdString(), image);imshow(QString("Dsc_Mask").toStdString(), mask);imshow(QString("Dsc_Result").toStdString(), result);waitKey(0);return;
}
運行結果如下:
OK,以上通過十幾個示例代碼展示了OpenCV圖像讀寫及一些基本變換的應用,由于篇幅有限,下一篇,再將一些實際應用比如角點檢測,特征提取,人臉檢測等功能演示出來。