文章目錄
- 1 要使用到的函數 和 原理
- 1.1 cv::meanStdDev 函數詳解——計算均值和標準差
- 1 .2 方差的通俗解釋
- 2 代碼實現
- 3 問題
- 3.1 入口參數const cv::Mat& img 和 const cv::Mat img區別
項目要求:
- C++ OPenCV 中 圖像img ,
- 當 string ROIdirection =“H”時,代表橫向線條,則在圖像寬度的一半處取一列像素,計算方差;
- 當 string ROIdirection =“V”時,代表豎向線條,則在圖像高度的一半處取一行像素,計算方差;
要求寫一個獨立的函數實現該功能,計算的方差有入口參數帶出來;
1 要使用到的函數 和 原理
1.1 cv::meanStdDev 函數詳解——計算均值和標準差
OpenCV的cv::meanStdDev
函數用于同時計算輸入矩陣的均值和標準差。函數定義如下:
void cv::meanStdDev(InputArray src, OutputArray mean, OutputArray stddev, InputArray mask=noArray());
參數:
src:
輸入數組,必須是單通道或多通道的圖像。mean:
輸出參數,返回各個通道的均值。stddev:
輸出參數,返回各個通道的標準差。mask:
可選的操作掩碼,用于指定需要計算的區域。如果不提供,默認計算整個圖像。
功能:
meanStdDev
計算輸入矩陣src的均值和標準差。均值是數據的平均值,標準差是數據偏離均值的程度。
代碼示例及詳細解釋
假設我們有一個一維矩陣linePixels1D,我們可以使用meanStdDev函數來計算它的均值和標準差。具體代碼如下:
cv::Scalar mean, stddev;
cv::meanStdDev(linePixels1D, mean, stddev);
linePixels1D
:輸入矩陣,這里是一維的像素值數組。mean
:輸出參數,存儲均值結果。stddev
:輸出參數,存儲標準差結果。
例子詳細解釋:
假設linePixels1D包含以下像素值:
[100, 150, 200, 250, 150, 100, 200, 250]
執行cv::meanStdDev后,計算過程如下:
然后計算這些偏差平方的平均值:
(5625 + 625 + 625 + 5625 + 625 + 5625 + 625 + 5625)/8 = 3593.75;
最后計算標準差(方差的平方根):
sqrt{3593.75} = 59.94;
3.函數結果:
mean[0]
將包含均值:175stddev[0]
將包含標準差:59.94
1 .2 方差的通俗解釋
方差是一個統計學概念,用于衡量一組數據的分散程度。通俗地講,方差告訴我們數據點離平均值有多遠。理解方差可以幫助我們了解數據的波動情況。
舉例說明:
假設我們有兩組學生的考試成績:
組A:90, 91, 89, 92, 88
組B:60, 95, 85, 70, 100
這兩組的平均分可能相同或相近,但數據的分散情況不同。組A的成績比較集中,組B的成績波動較大。
計算步驟:
結果解讀:
- 組A的方差為2,組B的方差為226。說明組A的成績比較集中,而組B的成績波動較大。
- 方差越大,數據分布越分散。方差越小,數據越集中。
方差的通俗意義
- 方差提供了一種量化數據分散程度的方法。
- 在實際應用中,方差可以幫助我們理解和比較不同數據集的穩定性。例如,在股票市場中,較大的方差意味著股票價格波動較大,風險較高;較小的方差意味著價格波動較小,風險較低。
2 代碼實現
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>// 計算圖像指定方向的像素方差
void calculateVariance(const cv::Mat& img, const std::string& ROIdirection, double& variance) {// 檢查圖像是否為空if (img.empty()) {std::cerr << "錯誤: 圖像為空!" << std::endl;return;}// 檢查方向參數是否有效if (ROIdirection != "H" && ROIdirection != "V") {std::cerr << "錯誤: 無效的ROIdirection!請使用 'H' 或 'V'。" << std::endl;return;}// 用于存儲提取的像素線條cv::Mat linePixels;if (ROIdirection == "H") {// 如果是水平方向,在圖像一半寬度處取一列像素int colIndex = img.cols / 2;linePixels = img.col(colIndex);} else if (ROIdirection == "V") {// 如果是垂直方向,在圖像一半高度處取一行像素int rowIndex = img.rows / 2;linePixels = img.row(rowIndex);}// 將像素線條轉換為一維數組以便計算方差cv::Mat linePixels1D = linePixels.reshape(1, linePixels.total());// 計算均值和標準差cv::Scalar mean, stddev;cv::meanStdDev(linePixels1D, mean, stddev);// 方差是標準差的平方variance = stddev[0] * stddev[0];
}int main() {// 加載示例圖像(為了簡單起見,使用灰度模式)cv::Mat img = cv::imread("path_to_image.jpg", cv::IMREAD_GRAYSCALE);if (img.empty()) {std::cerr << "錯誤: 無法加載圖像!" << std::endl;return -1;}// 計算圖像一半寬度處列像素的方差double varianceH = 0.0;calculateVariance(img, "H", varianceH);std::cout << "圖像一半寬度處列像素的方差: " << varianceH << std::endl;// 計算圖像一半高度處行像素的方差double varianceV = 0.0;calculateVariance(img, "V", varianceV);std::cout << "圖像一半高度處行像素的方差: " << varianceV << std::endl;return 0;
}
3 問題
3.1 入口參數const cv::Mat& img 和 const cv::Mat img區別
const cv::Mat& img:
傳遞的是圖像的引用,不會復制圖像數據,只是創建一個對原圖像的引用。這在處理大圖像時更加高效,因為避免了不必要的數據復制。const cv::Mat img:
傳遞的是圖像的副本,函數內部將持有圖像數據的一個拷貝。這會導致額外的內存開銷和時間消耗,尤其是在圖像很大的時候。