久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

OpenCV-實現直方圖均衡化(對比cv::equalizeHist)

 翟天保的圖書館 2022-01-13

作者:翟天保Steven
版權聲明:著作權歸作者所有,商業(yè)轉載請聯系作者獲得授權,非商業(yè)轉載請注明出處

實現原理

? ? ? ?通過圖像數據的直方圖,可以快速判斷圖像的亮度和質量,。而直方圖均衡化就是通過圖像變換使得直方圖均勻分布,起到對比度增強的效果,。在圖像處理的課本中,針對離散形式的圖像數據,最常用的一種方法就是累計概率分布,。首先統計0-255灰度值所占像素個數;再計算出像素個數與總像素的比,表示為出現的概率;從0開始進行累計概率分布,即從0慢慢累加各層概率值直到1;則均衡化圖像的灰度值=原灰度值所對應的累計概率*255,。

? ? ? ?基于上述原理,我自定義了一個簡單的直方圖均衡化函數EqualizeHist,并定義了直方圖簡易繪制函數drawHistImg,用來作直觀對比,。

功能函數代碼

// 直方圖均衡化
cv::Mat EqualizeHist(cv::Mat src)
{
cv::Mat h = cv::Mat::zeros(1, 256, CV_32FC1);
cv::Mat hs = cv::Mat::zeros(1, 256, CV_32FC1);
cv::Mat hp = cv::Mat::zeros(1, 256, CV_32FC1);
cv::Mat result = cv::Mat::zeros(src.size(), src.type());
int sum = 0;
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
h.at<float>(0, src.at <uchar>(i, j))++;
sum++;
}
}
for (int i = 0; i < 256; ++i)
{
hs.at<float>(0, i) = h.at<float>(0, i) / sum;
if (i == 0)
{
hp.at<float>(0, i) = hs.at<float>(0, i);
}
else {
hp.at<float>(0, i) = hp.at<float>(0, i - 1) + hs.at<float>(0, i);
}
}
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
result.at <uchar>(i, j) = uchar(round(255 * hp.at<float>(0, src.at<uchar>(i, j))));
}
}
return result;
}

// 繪制簡易直方圖
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;
}

函數原型

? ? ? ?官方OpenCV庫中也有自帶的直方圖均衡化函數:

void equalizeHist( InputArray src, OutputArray dst );

參數說明

  1. InputArray類型的src,輸入圖像,如Mat類型,。
  2. OutputArray類型的dst,輸出圖像。

C++測試代碼

#include <iostream>
#include <time.h>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

cv::Mat EqualizeHist(cv::Mat src);
cv::Mat drawHistImg(cv::Mat &hist);

int main()
{
cv::Mat src = imread("test.jpg",0);
cv::Mat src1 = imread("test.jpg");
clock_t start1, start2, end1,end2;

// 繪制原圖直方圖
cv::Mat hI = drawHistImg(src);

// 自定義直方圖均衡化
start1 = clock();
cv::Mat result1 = EqualizeHist(src);
end1 = clock();
double dif1 = (end1 - start1) / CLOCKS_PER_SEC;
cout << "time1:" << dif1 << endl;
// 繪制均衡化后直方圖
cv::Mat hrI = drawHistImg(result1);

// 官方直方圖均衡化函數
start2 = clock();
cv::Mat result2;
equalizeHist(src, result2);
end2 = clock();
double dif2 = (end2 - start2) / CLOCKS_PER_SEC;
cout << "time2:" << dif2 << endl;
// 繪制均衡化后直方圖
cv::Mat hr2I = drawHistImg(result2);

// 彩色直方圖均衡化,三通道分別作均衡再合并
vector<cv::Mat> rgb,rgb_;
cv::Mat r, g, b;
cv::split(src1, rgb);
equalizeHist(rgb[0], b);
equalizeHist(rgb[1], g);
equalizeHist(rgb[2], r);
rgb_.push_back(b);
rgb_.push_back(g);
rgb_.push_back(r);
cv::Mat src1_;
cv::merge(rgb_, src1_);
imshow("original", src1);
imshow("result", src1_);
waitKey(0);

return 0;
}

// 直方圖均衡化
cv::Mat EqualizeHist(cv::Mat src)
{
cv::Mat h = cv::Mat::zeros(1, 256, CV_32FC1);
cv::Mat hs = cv::Mat::zeros(1, 256, CV_32FC1);
cv::Mat hp = cv::Mat::zeros(1, 256, CV_32FC1);
cv::Mat result = cv::Mat::zeros(src.size(), src.type());
int sum = 0;
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
h.at<float>(0, src.at <uchar>(i, j))++;
sum++;
}
}
for (int i = 0; i < 256; ++i)
{
hs.at<float>(0, i) = h.at<float>(0, i) / sum;
if (i == 0)
{
hp.at<float>(0, i) = hs.at<float>(0, i);
}
else {
hp.at<float>(0, i) = hp.at<float>(0, i - 1) + hs.at<float>(0, i);
}
}
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
result.at <uchar>(i, j) = uchar(round(255 * hp.at<float>(0, src.at<uchar>(i, j))));
}
}
return result;
}

// 繪制簡易直方圖
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;
}

測試效果

圖1?灰度原圖

? ? ? ?其直方圖如下:?

圖2?直方圖
圖3?均衡化后灰度圖

? ? ? ?兩個函數運行時間都在0.001s以下,其均衡化后直方圖略有差異,但都實現了均衡效果,。

? ? ? ?自定義函數:

圖4?自定義函數均衡化后直方圖

? ? ? ? 官方函數:

圖5?官方函數均衡化后直方圖

? ? ? ? ?對彩色圖的三通道分別進行直方圖均衡化,實現彩色均衡效果:

圖6?彩色原圖
圖7?彩色均衡化效果

? ? ? ?如果函數有什么可以改進完善的地方,非常歡迎大家指出,一同進步何樂而不為呢~

? ? ? ?如果文章幫助到你了,可以點個贊讓我知道,我會很快樂~加油!

    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章