OpenCV 自學筆記33. 計算圖像的均值、标準差和平均梯度
均值、标準差和平均梯度是驗證圖像品質的常用名額。其中:
- 均值反映了圖像的亮度,均值越大說明圖像亮度越大,反之越小;
- 标準差反映了圖像像素值與均值的離散程度,标準差越大說明圖像的品質越好;
- 平均梯度反映了圖像的清晰度和紋理變化,平均梯度越大說明圖像越清晰;
那麼,如何使用OpenCV計算圖像的均值、标準差和平均梯度呢?
OpenCV提供了幾個函數,可以用來幫助我們計算。
1、計算圖像的平均梯度
meanStdDev()函數用于計算一個矩陣的均值和标準差,它的聲明如下:
void cv::meanStdDev (
InputArray src,
OutputArray mean,
OutputArray stddev,
InputArray mask =
函數參數
- src:輸入的源圖像或矩陣
- mean:輸出的均值矩陣
- stddev:輸出的标準差矩陣
- mask:可選的掩碼矩陣
使用meanStdDev計算均值和标準差的代碼如下:
// 輸入圖像的路徑
// 計算圖像的标準差
void cal_mean_stddev(string path) {
Mat src = imread(path);
Mat gray, mat_mean, mat_stddev;
cvtColor(src, gray, CV_RGB2GRAY); // 轉換為灰階圖
meanStdDev(gray, mat_mean, mat_stddev);
double m, s;
m = mat_mean.at<double>(0, 0);
s = mat_stddev.at<double>(0, 0);
cout << path << "的灰階均值是:" << m << endl;
cout << path << "的标準差是:"
标準差的計算公式如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cGcq5SNwMzMxQDZ1ATN3YDOhRDMzYzX5UzMxgTMzIzLchDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.jpg)
其中, M * N表示圖像的大小, P(i, j) 表示第i行、第j列的像素值, u表示均值。
2、計算圖像的平均梯度
平均梯度的計算公式如下:
// 輸入圖像的路徑
// 計算圖像的平均梯度
void cal_mean_gradient(string path) {
Mat src = imread(path);
Mat img;
cvtColor(src, img, CV_RGB2GRAY); // 轉換為灰階圖
img.convertTo(img, CV_64FC1);
double tmp = 0;
int rows = img.rows - 1;
int cols = img.cols - 1;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
double dx = img.at<double>(i, j + 1) - img.at<double>(i, j);
double dy = img.at<double>(i + 1, j) - img.at<double>(i, j);
double ds = std::sqrt((dx*dx + dy*dy) / 2);
tmp += ds;
}
}
double imageAvG = tmp / (rows*cols);
cout << path << "的平均梯度是:"
3、測試圖像為:
images/image7.jpg
測試結果如下:
/*************************************************
Copyright:bupt
Author: lijialin [email protected]
Date:2017-11-21
Description:寫這段代碼的時候,隻有上帝和我知道它是幹嘛的
現在隻有上帝知道
**************************************************/
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
/***************** 函數聲明部分 start ****************/
void cal_mean_stddev(string path); // 計算圖像的标準差
void cal_mean_gradient(string path); // 計算圖像的平均梯度
/***************** 函數聲明部分 end ****************/
int main() {
string path = "images/image7.jpg"; // image7.jpg在images目錄下
cal_mean_stddev(path);
cal_mean_gradient(path);
system("pause"); // 暫停
return 0;
}
// 計算圖像的标準差
void cal_mean_stddev(string path) {
Mat src = imread(path);
Mat gray, mat_mean, mat_stddev;
cvtColor(src, gray, CV_RGB2GRAY); // 轉換為灰階圖
meanStdDev(gray, mat_mean, mat_stddev);
double m, s;
m = mat_mean.at<double>(0, 0);
s = mat_stddev.at<double>(0, 0);
cout << path << "的灰階均值是:" << m << endl;
cout << path << "的标準差是:" << s << endl;
}
// 計算圖像的平均梯度
void cal_mean_gradient(string path) {
Mat src = imread(path);
Mat img;
cvtColor(src, img, CV_RGB2GRAY); // 轉換為灰階圖
img.convertTo(img, CV_64FC1);
double tmp = 0;
int rows = img.rows - 1;
int cols = img.cols - 1;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
double dx = img.at<double>(i, j + 1) - img.at<double>(i, j);
double dy = img.at<double>(i + 1, j) - img.at<double>(i, j);
double ds = std::sqrt((dx*dx + dy*dy) / 2);
tmp += ds;
}
}
double imageAvG = tmp / (rows*cols);
cout << path << "的平均梯度是:"