OpenCV 4.12.0
開源計算機視覺
載入中...
搜尋中...
無匹配項
影像操作

上一個教程: 矩陣的掩膜操作
下一個教程: 使用 OpenCV 新增(混合)兩張影像

相容性OpenCV >= 3.0

輸入/輸出

影像

從檔案載入影像

如果讀取 JPG 檔案,預設會建立一個三通道影像。如果需要灰度影像,請使用

注意
檔案的格式由其內容(前幾個位元組)決定。要將影像儲存到檔案,請使用
注意
檔案的格式由其副檔名決定。
使用 cv::imdecodecv::imencode 從/向記憶體而非檔案讀寫影像。

影像基本操作

訪問畫素強度值

為了獲取畫素強度值,您需要知道影像的型別和通道數。以下是一個單通道灰度影像(型別 8UC1)以及畫素座標 x 和 y 的示例:

僅限 C++ 版本:`intensity.val[0]` 包含一個 0 到 255 之間的值。請注意 x 和 y 的順序。由於在 OpenCV 中影像與矩陣由相同的結構表示,我們對這兩種情況使用相同的約定——0-based 行索引(或 y 座標)在前,0-based 列索引(或 x 座標)在後。此外,您也可以使用以下表示法(僅限 C++):

Scalar intensity = img.at<uchar>(Point(x, y));

現在讓我們考慮一個具有 BGR 顏色順序的三通道影像(imread 返回的預設格式):

C++ 程式碼

Vec3b intensity = img.at<Vec3b>(y, x);
uchar blue = intensity.val[0];
uchar green = intensity.val[1];
uchar red = intensity.val[2];

Python

_blue = img[y,x,0]
_green = img[y,x,1]
_red = img[y,x,2]

對於浮點影像(例如,透過對三通道影像執行 Sobel 演算法可以得到此類影像),您可以使用相同的方法(僅限 C++):

Vec3f intensity = img.at<Vec3f>(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];

同樣的方法也可以用來改變畫素強度:

OpenCV 中有一些函式,特別是 `calib3d` 模組中的函式,例如 `cv::projectPoints`,它們接受 `Mat` 形式的 2D 或 3D 點陣列。矩陣應只包含一列,每行對應一個點,矩陣型別應分別為 `32FC2` 或 `32FC3`。這樣的矩陣可以很容易地從 std::vector 構造(僅限 C++):

vector<Point2f> points;
//... 填充陣列
Mat pointsMat = Mat(points);

可以使用相同的 Mat::at 方法訪問此矩陣中的一個點(僅限 C++):

Point2f point = pointsMat.at<Point2f>(i, 0);

記憶體管理與引用計數

`Mat` 是一個結構體,它儲存矩陣/影像的特性(行數、列數、資料型別等)以及指向資料的指標。因此,擁有多個 `Mat` 例項對應同一資料是可行的。一個 `Mat` 維護一個引用計數,該計數指示當 `Mat` 的特定例項被銷燬時資料是否需要被釋放。以下是建立兩個不復制資料的矩陣的示例(僅限 C++):

std::vector<Point3f> points;
// .. 填充陣列
Mat pointsMat = Mat(points).reshape(1);

結果,我們得到一個三列的 `32FC1` 矩陣,而不是一列的 `32FC3` 矩陣。pointsMat 使用來自 `points` 的資料,並且在銷燬時不會釋放記憶體。然而,在這種特定情況下,開發人員必須確保 `points` 的生命週期長於 `pointsMat`。如果我們需要複製資料,可以透過例如 `cv::Mat::copyTo``cv::Mat::clone` 來完成。

可以為每個函式提供一個空的輸出 `Mat`。每個實現都會為目標矩陣呼叫 `Mat::create`。如果矩陣為空,此方法會為其分配資料。如果它不為空且具有正確的大小和型別,則此方法不執行任何操作。但是,如果大小或型別與輸入引數不同,則資料將被釋放(並丟失),並分配新的資料。例如:

基本操作

矩陣上定義了許多方便的運算子。例如,下面是如何從現有的灰度影像 img 建立一個黑色影像:

選擇感興趣區域

從彩色到灰度的轉換

將影像型別從 8UC1 更改為 32FC1

影像視覺化

在開發過程中檢視演算法的中間結果非常有用。OpenCV 提供了一種方便的影像視覺化方法。可以使用以下方法顯示 8U 影像:

呼叫 `waitKey()` 會啟動一個訊息傳遞迴圈,等待“image”視窗中的按鍵。32F 影像需要轉換為 8U 型別。例如:

注意
這裡不需要 `cv::namedWindow`,因為它緊接著 `cv::imshow`。然而,它可以用於更改視窗屬性或在使用 `cv::createTrackbar` 時。