jashliao 用 VC++ 實現 fanfuhan OpenCV 教學010 ~ opencv-010-圖像像素值統計函數[minMaxLoc(一維陣列<灰階>最大最小值&位置座標) / meanStdDev(計算每一顏色通道平均值&標準差) / 普通圖像轉化為二值化圖像 / 彩色圖的相似顏色都標成相同區域,簡易分割圖片方式]
jashliao 用 VC++ 實現 fanfuhan OpenCV 教學010 ~ opencv-010-圖像像素值統計函數[minMaxLoc(一維陣列<灰階>最大最小值&位置座標) / meanStdDev(計算每一顏色通道平均值&標準差) / 普通圖像轉化為二值化圖像 / 彩色圖的相似顏色都標成相同區域,簡易分割圖片方式]
資料來源: https://fanfuhan.github.io/
https://fanfuhan.github.io/2019/03/25/opencv-010/
GITHUB:https://github.com/jash-git/fanfuhan_ML_OpenCV
https://github.com/jash-git/jashliao-implements-FANFUHAN-OPENCV-with-VC
★前言:

★主題:
OPENCV提供計算圖像(陣列/數列)最大值、最小值、均值與標準方差的功能(統計數學),其功能函數條列如下:
最大最小值minMaxLoc
計算均值與標準方差meanStdDev
★C++
// VC_FANFUHAN_OPENCV010.cpp : 定義主控台應用程式的進入點。
//
/*
// Debug | x32
通用屬性
| C/C++
| | 一般
| | 其他 Include 目錄 -> C:\opencv\build\include
|
| 連結器
| |一一般
| | 其他程式庫目錄 -> C:\opencv\build\x64\vc15\lib
|
| |一輸入
| | 其他相依性 -> opencv_world411d.lib;%(AdditionalDependencies)
// Releas | x64
組態屬性
| C/C++
| | 一般
| | 其他 Include 目錄 -> C:\opencv\build\include
|
| 連結器
| |一般
| | 其他程式庫目錄 -> C:\opencv\build\x64\vc15\lib
|
| |一輸入
| | 其他相依性 -> opencv_world411.lib;%(AdditionalDependencies)
*/
#include "stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
void pause()
{
printf("Press Enter key to continue...");
fgetc(stdin);
}
int main()
{
Mat src_bgr = imread("../../images/test.png");
Mat src_gray;
cvtColor(src_bgr, src_gray, COLOR_BGR2GRAY);
if (src_bgr.empty() || src_gray.empty())
{
cout << "could not load image.." << endl;
pause();
return -1;
}
else
{
imshow("input_bgr", src_bgr);
imshow("input_gray", src_gray);
// 计算灰度图像的最大最小值
double minVal, maxVal;
Point minLoc, maxLoc;//座標位置
/*
1 minMaxLoc尋找矩陣(一維陣列當作向量,用Mat定義) 中最小值和最大值的位置.
2 參數若不需要,則置為NULL或者0,即可.
3 minMaxLoc針對Mat和MatND的重載中 ,第5個參數是可選的(optional),不使用不傳遞即可.
*/
minMaxLoc(src_gray, &minVal, &maxVal, &minLoc, &maxLoc);//搜尋灰階影像中的最大與最小值
cout << "paramenters of src_gray:" << endl;
printf("min:%.2f, max:%.2f \n", minVal, maxVal);
printf("min loc: (%d, %d) \n", minLoc.x, minLoc.y);
printf("max loc: (%d, %d) \n", maxLoc.x, maxLoc.y);
Mat mean_g, stddev_g;
/*
計算矩陣的均值和標準偏差。
C++: void meanStdDev(InputArray src,OutputArray mean, OutputArray stddev, InputArray mask=noArray())
C: void cvAvgSdv(constCvArr* arr, CvScalar* mean, CvScalar* std_dev, const CvArr* mask=NULL )
Python: cv.AvgSdv(arr,mask=None) -> (mean, stdDev)
parameter:
src:輸入矩陣,這個矩陣應該是1-4通道的,這可以將計算結果存在Scalar_ ‘s中
mean:輸出引數,計算均值
stddev:輸出引數,計算標準差
mask:可選引數
*/
meanStdDev(src_gray, mean_g, stddev_g);
printf("gray channel mean:%.2f, stddev: %.2f \n\n", mean_g.at<double>(0, 0), stddev_g.at<double>(0, 0));
for (int row = 0; row < src_bgr.rows; ++row) {
for (int col = 0; col < src_bgr.cols; ++col) {
Vec3b bgr = src_gray.at<Vec3b>(row, col);
bgr[0] = bgr[0] < mean_g.at<double>(0, 0) ? 0 : 255;
src_gray.at<Vec3b>(row, col) = bgr;
}
}
imshow("gray_binary", src_gray);
// 普通图像转二值图像 [彩色二值化圖]
Mat mean, stddev;
meanStdDev(src_bgr, mean, stddev);
cout << "paramenters of src_bgr:" << endl;
printf("blue channel mean:%.2f, stddev: %.2f \n", mean.at<double>(0, 0), stddev.at<double>(0, 0));
printf("green channel mean:%.2f, stddev: %.2f \n", mean.at<double>(1, 0), stddev.at<double>(1, 0));
printf("red channel mean:%.2f, stddev: %.2f \n", mean.at<double>(2, 0), stddev.at<double>(2, 0));
for (int row = 0; row < src_bgr.rows; ++row) {
for (int col = 0; col < src_bgr.cols; ++col) {
Vec3b bgr = src_bgr.at<Vec3b>(row, col);
bgr[0] = bgr[0] < mean.at<double>(0, 0) ? 0 : 255;
bgr[1] = bgr[1] < mean.at<double>(1, 0) ? 0 : 255;
bgr[2] = bgr[2] < mean.at<double>(2, 0) ? 0 : 255;
src_bgr.at<Vec3b>(row, col) = bgr;
}
}
imshow("bgr_binary", src_bgr);
waitKey(0);
}
return 0;
}
★Python
import cv2 as cv
import numpy as np
src = cv.imread("../images/test.png", cv.IMREAD_GRAYSCALE)
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)
min, max, minLoc, maxLoc = cv.minMaxLoc(src)
print("min: %.2f, max: %.2f"% (min, max))
print("min loc: ", minLoc)
print("max loc: ", maxLoc)
means, stddev = cv.meanStdDev(src)
print("mean: %.2f, stddev: %.2f"% (means, stddev))
src[np.where(src < means)] = 0
src[np.where(src > means)] = 255
cv.imshow("binary", src)
cv.waitKey(0)
cv.destroyAllWindows()
★結果圖:

★延伸說明/重點回顧:
透過OPENCV提供計算圖像(陣列/數列)最大值、最小值、均值與標準方差的功能(統計數學),可以讓我們更有效率且系統化知道圖像相關資訊