티스토리 뷰
이 사진의 히스토그램을 구하면 다음과 같다.
누적 히스토그램(Cumulative Histogram) : 히스토그램의 빈도수에 따른 누적값
정규 히스토그램(Normalized Histogram) : 히스토그램의 모든 값을 더하면 1이 되도록 변환
히스토그램 평활화(Histogram Equalization) : 영상 품질 개선을 위한 명암의 동적 범위 수정
Source Code
Histogram.h
#define HISTOGRAM_SIZE 256
#define LEVEL 256
namespace LibImageProcessing {
class Histogram
{
public:
Histogram();
~Histogram();
void run(cv::Mat &image);
public:
void getHistogram(cv::Mat &image, int *hist);
void getCumulativeHistogram(int *hist, int *cumHist);
void getNormalizedHistogram(int imageSize, int *cumHist, int *norHist);
void getHistogramEqualization(int *hist, int *norHist, int *equHist);
private:
void showHistogram(int *);
};
}
Histogram.cpp
#include "Histogram.h"
namespace LibImageProcessing {
Histogram::Histogram() { }
Histogram::~Histogram() { }
void Histogram::run(cv::Mat &image) {
CV_Assert(image.type() == CV_8UC1);
CV_Assert(image.channels() == 1);
int imageSize = image.size().width * image.size().height;
// histogram
int histogram[HISTOGRAM_SIZE];
memset(histogram, 0, HISTOGRAM_SIZE * sizeof(int));
getHistogram(image, histogram);
// cumulative histogram
int cumulativeHistogram[HISTOGRAM_SIZE];
memset(cumulativeHistogram, 0, HISTOGRAM_SIZE * sizeof(int));
getCumulativeHistogram(histogram, cumulativeHistogram);
// histogram normalize
int normalizedHistogram[HISTOGRAM_SIZE];
memset(normalizedHistogram, 0, HISTOGRAM_SIZE * sizeof(int));
getNormalizedHistogram(imageSize, cumulativeHistogram, normalizedHistogram);
// histogram equalization
int histogramEqualization[HISTOGRAM_SIZE];
memset(histogramEqualization, 0, HISTOGRAM_SIZE * sizeof(int));
getHistogramEqualization(histogram, normalizedHistogram, histogramEqualization);
// convert from original image to enhanced image
cv::Mat newImage = image.clone();
for (int y = 0; y < image.rows; y++)
{
for (int x = 0; x < image.cols; x++)
{
newImage.at<uchar>(y, x) = normalizedHistogram[image.at<uchar>(y, x)];
}
}
cv::imshow("original image", image);
cv::imshow("converted image", newImage);
cv::waitKey(0);
}
void Histogram::getHistogram(cv::Mat &image, int *hist)
{
int cols = image.cols;
int rows = image.rows;
uchar *imageData = image.data;
int imageSize = image.size().width * image.size().height;
for (int i = 0; i < imageSize; i++)
{
++hist[imageData[i]];
}
}
void Histogram::getCumulativeHistogram(int *hist, int *cumHist)
{
for (int i = 1; i < HISTOGRAM_SIZE; i++)
{
cumHist[i] = cumHist[i - 1] + hist[i];
}
}
void Histogram::getNormalizedHistogram(int imageSize, int *cumHist, int *norHist)
{
for (int i = 0; i < HISTOGRAM_SIZE; i++)
{
norHist[i] = ((float)cumHist[i] / imageSize) * (LEVEL - 1);
}
}
void Histogram::getHistogramEqualization(int *hist, int *norHist, int *equHist)
{
for (int i = 0; i < HISTOGRAM_SIZE; i++)
{
equHist[norHist[i]] += hist[i];
}
}
void Histogram::showHistogram(int *hist) {
// create canvas image
cv::Mat base = cv::Mat::zeros(256, 256, CV_8UC1);
// get max value in array
int maxValue = 0;
for (int i = 0; i < HISTOGRAM_SIZE; i++)
{
maxValue = (maxValue < hist[i]) ? hist[i] : maxValue;
}
// draw line
for (int i = 0; i < HISTOGRAM_SIZE; i++)
{
int scaledHeight = ((float)hist[i] / maxValue) * 255;
cout << scaledHeight << endl;
cv::line(base, cv::Point(i, 255), cv::Point(i, 255 - scaledHeight), cv::Scalar(255), 1, CV_AA);
}
cv::namedWindow("histogram", CV_NORMAL);
cv::imshow("histogram", base);
cv::waitKey(0);
}
}
- Total
- Today
- Yesterday
- jitpack
- android serialization
- C++
- delete item
- data transfer
- qtwebengine
- build server
- Jenkins
- security.ubuntu.com
- weak_ptr
- auto depoly
- 오픈 소스 배포
- Apache
- type inference
- 자동 배포
- git server
- 리사이클러뷰 확장
- swip
- Git
- serializable
- android open source
- Parcelable
- git hook
- expandable recyclerview
- RecyclerView
- ubuntu 16.04
- remove item
- publish opensource
- kotlin
- kotlinx serialization
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |