#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define webcam 1
#define video 0
using namespace std;
using namespace cv;
void mvCalcHist(Mat &src, Mat &hist); // sample function
void mvEqualizeHist(const Mat &src, Mat &dst, Mat &hist);
void plotHist(Mat &hist);
Mat cvtGray(Mat& color);
int main()
{
unsigned int fps = 60; // 초당 프레임 값 지정
unsigned int window_resize_factor = 1; // 0: 출력창 리사이즈 가능, 1 : 불가
string output_data_format = "jpg"; // 저장할 이미지 포맷 설정
#if(webcam)
VideoCapture cap(0);
#elif(video)
VideoCapture cap("road.mp4");
#endif
if (!cap.isOpened()) // if not success, exit program
{
cout << "Cannot open the video cam" << endl;
return -1;
}
int input_key = -1;
int horizontal_flip_sign = 1;
int vertical_flip_sign = 2;
int flip_sign = 2;
bool pause_sign = false;
bool gray_sign = false;
bool save_sign = false;
bool reset_sign = false;
bool exit_sign = false;
unsigned int delay_waitKey = 1000 / fps;
time_t t;
Mat src, dst;
string output_data_name = "";
namedWindow("MyVideo", window_resize_factor);
while (1)
{
input_key = waitKey(delay_waitKey);
if (input_key == 'q' || input_key == 'Q') horizontal_flip_sign *= -1;
else if (input_key == 'w' || input_key == 'w') vertical_flip_sign *= -1;
else if (input_key == 'r' || input_key == 'R') reset_sign = !reset_sign;
else if (input_key == 's' || input_key == 'S') save_sign = !save_sign;
else if (input_key == 32) pause_sign = !pause_sign;
else if (input_key == 27) exit_sign = !exit_sign;
flip_sign = (horizontal_flip_sign + vertical_flip_sign + 1) / 2;
if (!pause_sign) {
bool bSuccess= cap.read(src);
if (!bSuccess) {
cout << "Cannot read a frame from video stream" << endl;
break;
}
}
src = cvtGray(src);
if (flip_sign <= 1)
flip(src, src, flip_sign);
else
src.copyTo(dst);
if (reset_sign)
{
vertical_flip_sign = 2;
horizontal_flip_sign = 1;
gray_sign = false;
pause_sign = false;
reset_sign = false;
}
if (save_sign)
{
output_data_name = to_string(time(&t));
output_data_name += ".";
output_data_name += output_data_format;
imwrite(output_data_name, dst);
save_sign = false;
}
if (exit_sign)
{
cout << "esc key is pressed by user" << endl;
break;
}
Mat hist1(1, 256, CV_32F, Scalar(0)); // Histogram of src image
Mat hist2(1, 256, CV_32F, Scalar(0)); // Histogram of dst image
mvCalcHist(src, hist1);
mvEqualizeHist(src, dst, hist1);
mvCalcHist(dst, hist2);
plotHist(hist2);
imshow("Source", src);
imshow("Equalized", dst);
}
return 0;
}
void mvCalcHist(Mat &src, Mat &hist) // Histogram Calculation function
{
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))++;
}
}
}
void mvEqualizeHist(const Mat &src, Mat &dst, Mat &hist) // Histogram Equlization function
{
int L = 256;
int M = src.rows;
int N = src.cols;
float sum_h = 0;
float temp = 0;
Mat S(1, L, CV_32FC1, Scalar(0)); //Mat S declaration
for (int i = 0; i < L; i++) //Global Histogram
{
sum_h = sum_h + hist.at<float>(0, i);
S.at<float>(0, i) = (L - 1)*sum_h / (M*N);
}
for (int i = 0; i < M; i++) // Replace intensity to new intensity S(k) for each pixel
for (int j = 0; j < N; j++)
{
temp = src.at<uchar>(i, j);
dst.at<uchar>(i, j) = S.at<float>(0, temp);
}
}
void plotHist(Mat &hist) // Histogram Plot function
{
int histSize = 256;
int hist_w = 2 * 256;
int hist_h = 400;
int bin_w = cvRound((double)hist_w / histSize); // bin_w=1
// Normalize the result to [ 0, histImage.rows ], histImage.rows=hist_h
Mat histImage(hist_h, hist_w, CV_32FC1, Scalar(0, 0, 0));
normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
// Draw for each channel - Line (pt1(x,y), pt2(x,y))
// x,y는 Top Left corner에서 0,0 으로 시작됨- 즉 histlevel=0은 hist_h [pixel] 로 표현됨
for (int i = 0; i < histSize; i++)
{
line(histImage, Point(bin_w*(i), hist_h), Point(bin_w*(i), hist_h - cvRound(hist.at<float>(0, i))), Scalar(255, 0, 0), 2, 8, 0);
}
namedWindow("Histogram", CV_WINDOW_AUTOSIZE);
imshow("Histogram", histImage);
}
Mat cvtGray(Mat& color)
{
if (color.channels() == 1)
return color;
else {
Mat gray;
cvtColor(color, gray, CV_RGB2GRAY);
return gray;
}
}