作者:翟天保Steven
著作權宣告:著作權歸作者所有,商業轉載請聯系作者獲得授權,非商業轉載請注明出處
需求說明
在對影像進行處理時,經常會有這類需求:想要觀察影像的直方圖分布,例如灰度圖中0-255區間數值的分布情況,從而可以進行后續的操作,如閾值分割二值化、直方圖均衡化等等,本文設計了一個能繪制簡易直方圖的簡單函式DrawHistImg,可以幫助大家快速掌味訓制的原理,可以根據自己的創意對其進行改善和補充,
下面介紹具體實作流程,
具體流程
1)取影像的灰度圖,并遍歷統計0-255各個灰度值所出現的次數,
cv::Mat src = imread("test.jpg", 0);
cv::Mat hist = cv::Mat::zeros(1, 256, CV_32FC1);
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
hist.at<float>(0, src.at <uchar>(i, j))++;
}
}
2)定義直方圖影像histImage,并初始化一些引數,其中bins是數值最大值,即255;scale為每個灰度值所對應的直方圖寬度;histHeight為直方圖高度最大值,也是直方圖影像的寬,
cv::Mat histImage = cv::Mat::zeros(540, 1020, CV_8UC1);
const int bins = 255;
int scale = 4;
int histHeight = 540;
3)利用minMaxLoc函式得出哪個灰度值的出現次數最高,為歸一化做準備,
double maxValue;
cv::Point2i maxLoc;
cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);
4)遍歷hist中每個灰度值,并根據其出現次數繪制直方圖,height是歸一化后的高度,
for (int i = 0; i < bins; i++)
{
float binValue = (hist.at<float>(i));
int height = cvRound(binValue * histHeight / maxValue);
cv::rectangle(histImage, cv::Point(i * scale, histHeight),
cv::Point((i + 1) * scale - 1, histHeight - height), cv::Scalar(255), -1);
}
5)函式執行完畢,
功能函式
// 繪制簡易直方圖
cv::Mat DrawHistImg(cv::Mat &src)
{
cv::Mat hist = cv::Mat::zeros(1, 256, CV_32FC1);
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
hist.at<float>(0, src.at <uchar>(i, j))++;
}
}
cv::Mat histImage = cv::Mat::zeros(540, 1020, CV_8UC1);
const int bins = 255;
double maxValue;
cv::Point2i maxLoc;
cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);
int scale = 4;
int histHeight = 540;
for (int i = 0; i < bins; i++)
{
float binValue = (hist.at<float>(i));
int height = cvRound(binValue * histHeight / maxValue);
cv::rectangle(histImage, cv::Point(i * scale, histHeight),
cv::Point((i + 1) * scale - 1, histHeight - height), cv::Scalar(255), -1);
}
return histImage;
}
C++測驗代碼
#include <iostream>
#include <time.h>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
cv::Mat DrawHistImg(cv::Mat &hist);
int main()
{
cv::Mat src = imread("test.jpg", 0);
// 繪制均衡化后直方圖
cv::Mat hrI = DrawHistImg(src);
imshow("original", src);
imshow("hist", hrI);
waitKey(0);
return 0;
}
// 繪制簡易直方圖
cv::Mat DrawHistImg(cv::Mat &src)
{
cv::Mat hist = cv::Mat::zeros(1, 256, CV_32FC1);
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
hist.at<float>(0, src.at <uchar>(i, j))++;
}
}
cv::Mat histImage = cv::Mat::zeros(540, 1020, CV_8UC1);
const int bins = 255;
double maxValue;
cv::Point2i maxLoc;
cv::minMaxLoc(hist, 0, &maxValue, 0, &maxLoc);
int scale = 4;
int histHeight = 540;
for (int i = 0; i < bins; i++)
{
float binValue = (hist.at<float>(i));
int height = cvRound(binValue * histHeight / maxValue);
cv::rectangle(histImage, cv::Point(i * scale, histHeight),
cv::Point((i + 1) * scale - 1, histHeight - height), cv::Scalar(255), -1);
}
return histImage;
}
測驗效果
如果函式有什么可以改進完善的地方,非常歡迎大家指出,一同進步何樂而不為呢~
如果文章幫助到你了,可以點個贊讓我知道,我會很快樂~加油!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/377234.html
標籤:其他
上一篇:關于如何在視頻中合成聲音
