目錄
1.直方圖統(tǒng)計(jì)
2.直方圖均衡化
3.直方圖匹配
1.直方圖統(tǒng)計(jì)
? ? ? ?直方圖統(tǒng)計(jì)是一種用于分析圖像或數(shù)據(jù)的統(tǒng)計(jì)方法,它通過統(tǒng)計(jì)每個(gè)數(shù)值或像素值的頻率分布來了解數(shù)據(jù)的分布情況。
在OpenCV中,可以使用函數(shù)cv::calcHist()
來計(jì)算圖像的直方圖。
calcHist() 函數(shù)的原型如下:
void calcHist(const Mat* images, int nimages, const int* channels,
InputArray mask, OutputArray hist, int dims,
const int* histSize, const float** ranges,
bool uniform = true, bool accumulate = false);
參數(shù)說明:
-
images: 輸入圖像數(shù)組,可以是單張圖像或多張圖像的數(shù)組。
-
nimages: 輸入圖像的數(shù)量。
-
channels: 要計(jì)算直方圖的通道索引數(shù)組。例如,對于灰度圖像,只有一個(gè)通道,因此?channels?設(shè)置為?{0};而對于彩色圖像,可以指定?{0, 1, 2}?對應(yīng)于 B、G、R 三個(gè)通道。
-
mask: 掩碼圖像,用于指定計(jì)算直方圖的區(qū)域。如果不需要使用掩碼,可以傳入空的?Mat()。
-
hist: 輸出的直方圖,用于存儲(chǔ)計(jì)算結(jié)果。
-
dims: 直方圖的維度,通常為 1。
-
histSize: 直方圖的大小,即每個(gè)維度的條目數(shù)量。
-
ranges: 直方圖的范圍,可以使用?{0, 256}?表示像素值范圍為 [0, 256)。
-
uniform: 指示直方圖條目是否均勻分布,默認(rèn)為?true。
-
accumulate: 指示是否累積直方圖,默認(rèn)為?false。
下面是一個(gè)示例代碼,展示如何使用cv::calcHist()函數(shù)計(jì)算圖像的直方圖:
#include <opencv2/opencv.hpp>
void hist(Mat image){
// 定義直方圖參數(shù)
int histSize = 256; // 直方圖條目數(shù)量
const int channels[1]={0};//通道索引
float range[] = { 0, 256 }; // 像素值范圍
const float* histRange = { range };
bool uniform = true; // 直方圖條目是否均勻分布
bool accumulate = false; // 直方圖是否累積
// 計(jì)算直方圖
cv::Mat hist;
cv::calcHist(&image, 1, channels, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
// 繪制直方圖
int histWidth = 512;
int histHeight = 400;
int binWidth = cvRound((double)histWidth / histSize);
cv::Mat histImage(histHeight, histWidth, CV_8UC4, cv::Scalar(0, 0, 0));
cv::normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
for (int i = 1; i < histSize; ++i){
cv::line(histImage, cv::Point(binWidth * (i - 1), histHeight - cvRound(hist.at<float>(i - 1))),
cv::Point(binWidth * (i), histHeight - cvRound(hist.at<float>(i))),
cv::Scalar(255, 255, 255), 2, 8, 0);
}
// 顯示直方圖
cv::imwrite("/sdcard/DCIM/histImage.jpg", histImage);
}
示例代碼中將原圖像image轉(zhuǎn)換為單通道灰度圖像。然后定義了直方圖的參數(shù),包括直方圖條目數(shù)量、像素值范圍、均勻性和累積性。接下來使用 cv::calcHist() 函數(shù)計(jì)算了圖像的直方圖,存儲(chǔ)在 hist 中。最后,通過繪制直方圖數(shù)據(jù)到 histImage 中,實(shí)現(xiàn)了直方圖的可視化。
2.直方圖均衡化
? ? ? ? 直方圖均衡化是一種用于增強(qiáng)圖像對比度的圖像處理技術(shù)。它通過重新分布圖像像素值的頻率分布來增強(qiáng)圖像的亮度和細(xì)節(jié)。
在OpenCV中,可以使用cv::equalizeHist()函數(shù)來進(jìn)行直方圖均衡化。該函數(shù)的原型如下:
void equalizeHist(InputArray src, OutputArray dst);
參數(shù)說明:
-
src:需要直方圖均衡化的CV 8UC1圖像。
-
dst: 直方圖均衡化后的輸出圖像,與src具有相同尺寸和數(shù)據(jù)類型
下面是一個(gè)示例代碼,展示如何使用cv::equalizeHist()函數(shù)來進(jìn)行直方圖均衡化:
#include <opencv2/opencv.hpp>
void drawHist(Mat &hist,string name){//歸一化并繪制直方圖函數(shù)
int histSize = 256; // 直方圖條目數(shù)量
// 繪制直方圖
int histWidth = 512;
int histHeight = 400;
int binWidth = cvRound((double)histWidth / histSize);
cv::Mat histImage(histHeight, histWidth, CV_8UC4, cv::Scalar(0, 0, 0));
cv::normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
for (int i = 1; i < histSize; ++i)
{
cv::line(histImage, cv::Point(binWidth * (i - 1), histHeight - cvRound(hist.at<float>(i - 1))),
cv::Point(binWidth * (i), histHeight - cvRound(hist.at<float>(i))),
cv::Scalar(255, 255, 255), 2, 8, 0);
}
// 顯示直方圖
cv::imwrite("/sdcard/DCIM/"+name+".jpg", histImage);
}
void EqualImage(Mat image){
//灰度化
Mat gray;
cvtColor(image,gray,COLOR_BGR2GRAY);
//將灰度圖進(jìn)行直方圖均衡化
Mat equalImg;
equalizeHist(gray,equalImg);
cv::imwrite("/sdcard/DCIM/equalImg.jpg", equalImg);
// 定義直方圖參數(shù)
int histSize = 256; // 直方圖條目數(shù)量
const int channels[1]={0};//通道索引
float range[] = { 0, 256 }; // 像素值范圍
const float* histRange = { range };
bool uniform = true; // 直方圖條目是否均勻分布
bool accumulate = false; // 直方圖是否累積
// 計(jì)算直方圖
cv::Mat hist;
cv::calcHist(&equalImg, 1, channels, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
drawHist(hist,"hist1");
}
示例代碼中將原圖像image轉(zhuǎn)換為單通道灰度圖像,然后將灰度圖進(jìn)行直方圖均衡化,之后定義了直方圖的參數(shù),包括直方圖條目數(shù)量、像素值范圍、均勻性和累積性。接下來使用 cv::calcHist() 函數(shù)計(jì)算了圖像的直方圖,存儲(chǔ)在 hist 中。最后,通過繪制直方圖數(shù)據(jù)到 histImage 中,實(shí)現(xiàn)了直方圖的可視化。
3.直方圖匹配
? ? ? ?直方圖匹配(Histogram Matching)是一種圖像處理技術(shù),用于將一副圖像的直方圖映射到另一副圖像上,從而使它們的亮度分布或顏色分布相似。該技術(shù)常用于圖像增強(qiáng)、風(fēng)格轉(zhuǎn)換、顏色校正等應(yīng)用中。
以下是一個(gè)使用OpenCV實(shí)現(xiàn)直方圖匹配的示例代碼:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void drawHist(Mat &hist,string name){//歸一化并繪制直方圖函數(shù)
int histSize = 256; // 直方圖條目數(shù)量
// 繪制直方圖
int histWidth = 512;
int histHeight = 400;
int binWidth = cvRound((double)histWidth / histSize);
cv::Mat histImage(histHeight, histWidth, CV_8UC4, cv::Scalar(0, 0, 0));
cv::normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
for (int i = 1; i < histSize; ++i)
{
cv::line(histImage, cv::Point(binWidth * (i - 1), histHeight - cvRound(hist.at<float>(i - 1))),
cv::Point(binWidth * (i), histHeight - cvRound(hist.at<float>(i))),
cv::Scalar(255, 255, 255), 2, 8, 0);
}
// 顯示直方圖
cv::imwrite("/sdcard/DCIM/"+name+".jpg", histImage);
}
void Histogram_matching(Mat img1,Mat img2){
Mat hist1,hist2;
//計(jì)算兩張圖像直方圖
const int channels[1]={0};
float inRanges[2]={0,255};
const float *ranges[1]={inRanges};
const int bins[1]={256};
calcHist(&img1,1,channels,Mat(),hist1,1,bins,ranges);
calcHist(&img2,1,channels,Mat(),hist2,1,bins,ranges);
//歸一化兩張圖像的直方圖
drawHist(hist1,"hist1");
drawHist(hist2,"hist2");
//計(jì)算兩張圖像直方圖的累計(jì)概率
float hist1_cdf[256]={hist1.at<float>(0)};
float hist2_cdf[256]={hist2.at<float>(0)};
for(int i=1;i<256;i++){
hist1_cdf[i]=hist1_cdf[i-1]+hist1.at<float>(i);
hist2_cdf[i]=hist2_cdf[i-1]+hist1.at<float>(i);
}
//構(gòu)建累積概率誤差矩陣
float diff_cdf[256][256];
for(int i=0; i<256; i++){
for(int j=0; j<256; j++){
diff_cdf[i][j] = fabs(hist1_cdf[i] - hist2_cdf[j]);
}
}
uchar lutone[256];
for(int i=0;i<256;i++){
//查找源灰度級為i的映射灰度
//和i的累積概率差值最小的規(guī)定化灰度
float min=diff_cdf[i][0];
int index=0;
//尋找累積概率誤差矩陣中每一行中的最小值
for(int j=1;j<256;j++){
if(min>diff_cdf[i][j]){
min=diff_cdf[i][j];
index=j;
}
}
lutone[i]=index;
}
//生成LUT映射表
Mat lut(1,256,CV_8UC1,lutone);
Mat result,hist3;
LUT(img1,lut,result);
imwrite("/sdcard/DCIM/result.png",result);
calcHist(&result,1,channels,Mat(),hist3,1,bins,ranges);
drawHist(hist3,"hist3");
}
示例代碼:計(jì)算原始圖像和目標(biāo)圖像的直方圖,歸一化直方圖,計(jì)算累計(jì)直方圖,構(gòu)建累積概率誤差矩陣,根據(jù)最小差值構(gòu)建映射表,最后將原始圖像的灰度級根據(jù)映射表調(diào)整為目標(biāo)圖像的灰度級。下面是原始圖像和直方圖匹配后圖片,可以看出直方圖匹配后的圖片使得圖像中的細(xì)節(jié)更加清晰可見。
? ? ? ? ? ? ? ????
文章來源:http://www.zghlxwxcb.cn/news/detail-695544.html
? ? ? ? ? ? ? 原圖? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??直方圖匹配的結(jié)果文章來源地址http://www.zghlxwxcb.cn/news/detail-695544.html
到了這里,關(guān)于OpenCV(十八):圖像直方圖的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!