#include <opencv2/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat img_input, img_gray, img_result;
//이미지 파일을 읽어와서 img_input에 저장
img_input = imread("input5.png", IMREAD_COLOR);
if (img_input.empty())
{
cout << "파일을 읽어올수 없습니다." << endl;
exit(1);
}
//입력영상을 그레이스케일 영상으로 변환
img_gray = Mat(img_input.rows, img_input.cols, CV_8UC1);
for (int y = 0; y < img_input.rows; y++)
{
for (int x = 0; x < img_input.cols; x++)
{
//img_input으로부터 현재 위치 (y,x) 픽셀의
//blue, green, red 값을 읽어온다.
uchar blue = img_input.at<Vec3b>(y, x)[0];
uchar green = img_input.at<Vec3b>(y, x)[1];
uchar red = img_input.at<Vec3b>(y, x)[2];
//blue, green, red를 더한 후, 3으로 나누면 그레이스케일이 된다.
uchar gray = (blue + green + red) / 3.0;
//Mat타입 변수 img_gray에 저장한다.
img_gray.at<uchar>(y, x) = gray;
}
}
//mean mask
int mask1[3][3] = { {1,1,1},
{ 1,1,1 },
{ 1,1,1 }};
int mask2[5][5] = { { 1,1,1,1,1 },
{ 1,1,1,1,1 },
{ 1,1,1,1,1 },
{ 1,1,1,1,1 },
{ 1,1,1,1,1 } };
int mask3[25][25] = {
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 },
{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1 } };
long int sum;
img_result = Mat(img_input.rows, img_input.cols, CV_8UC1);
int masksize = 3;
for (int y = 0; y < img_input.rows; y++)
{
for (int x = 0; x < img_input.cols; x++)
{
sum = 0;
for (int i = -1 * masksize / 2; i <= masksize / 2; i++)
{
for (int j = -1 * masksize / 2; j <= masksize / 2; j++)
{
//영상 범위를 벗어난 경우 테두리 값을 사용
int new_y = y + i;
int new_x = x + j;
if (new_y < 0) new_y = 0;
else if (new_y > img_input.rows - 1) new_y = img_input.rows - 1;
if (new_x < 0) new_x = 0;
else if (new_x > img_input.cols - 1) new_x = img_input.cols - 1;
//선택한 마스크 크기 따라 컨볼루션 계산
if ( masksize == 3 )
sum += img_gray.at<uchar>( new_y, new_x) * mask1[masksize / 2 +i][masksize / 2 +j];
else if ( masksize == 5 )
sum += img_gray.at<uchar>(new_y, new_x) * mask2[masksize / 2 + i][masksize / 2 + j];
else if ( masksize == 25 )
sum += img_gray.at<uchar>(new_y, new_x) * mask3[masksize / 2 + i][masksize / 2 + j];
}
}
//마스크 크기로 나누어 주어야 한다.
sum = sum / (double)(masksize*masksize);
//0~255 사이값으로 조정
if (sum > 255) sum = 255;
if (sum < 0) sum = 0;
img_result.at<uchar>(y, x) = sum;
}
}
//화면에 결과 이미지를 보여준다.
imshow("입력 영상", img_input);
imshow("입력 그레이스케일 영상", img_gray);
imshow("결과 영상", img_result);
//아무키를 누르기 전까지 대기
while (cvWaitKey(0) == 0);
//결과를 파일로 저장
imwrite("img_gray.jpg", img_gray);
imwrite("img_result.jpg", img_result);
}