天天看點

OpenCV 自學筆記33. 計算圖像的均值、标準差和平均梯度

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 << "的标準差是:"      

标準差的計算公式如下:

OpenCV 自學筆記33. 計算圖像的均值、标準差和平均梯度

其中, M * N表示圖像的大小, P(i, j) 表示第i行、第j列的像素值, u表示均值。

2、計算圖像的平均梯度

平均梯度的計算公式如下:

OpenCV 自學筆記33. 計算圖像的均值、标準差和平均梯度
// 輸入圖像的路徑
// 計算圖像的平均梯度
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

OpenCV 自學筆記33. 計算圖像的均值、标準差和平均梯度

測試結果如下:

/*************************************************

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 << "的平均梯度是:"      

繼續閱讀