반응형
ㅇ Brightness(밝기)와 Contrast조절
ㅇ 영상처리 기술들 중에서 간단하면서도 직관적인 것이 brightness와 contrast 조절입니다.
- 우선 둘 중에 직관적으로 이해하기 쉬운 brightness부터 살펴 보겠습니다.
ㅇ Brightness는 영상을 밝기를 뜻합니다.
- 밝기를 조절하기 위해서는 픽셀의 intensity를 바꾸면 됩니다.
- Intensity값을 증가시키면, 영상이 밝아집니다.
- 반대로 감소시키면, 어두워집니다.
ㅇ Contrast는 영상에서 밝은 부분과 어두운 부분의 차이를 의미합니다.
- 방금 설명했던 brightness보다는 직관적으로 이해가 하기가 쉽지 않을 겁니다.
- 예를 들어 보겠습니다.
- 이미지 안의 대부분 픽셀들의 intensity가 비슷하다면,
- 어떤 물체가 있는지 쉽게 알 수가 없습니다.
- 이런 경우가 contrast가 낮은 것입니다.
- 반대로, 이것이 높다는 것은 픽셀들간의 Intensity 차이가 많이 난다는 겁니다.
- 이 경우, 물체의 모양이나 윤곽을 한 눈에 알아볼 수 있을 겁니다.
- 해가 비치는 부분과 그림자 진 부분을 쉽게 구분할 수 있는 것 처럼 말입니다.
ㅇ 그러면, brightness 조절은 어떻게 할까요?
- 쉽습니다. 모든 픽셀들의 intensity에 모두 같은 값만큼 더하거나 빼면 됩니다.
- 더하면 이미지가 환해져서 brightness가 증가됩니다.
- 빼는 것은 더하는 것의 반대 경우이구요.
ㅇ Brightness를 조절한 이미지의 예를 보겠습니다.
- 우선 아래 그림은 조절 전의 이미지입니다.
- 이미지가 두 구역으로 나뉘어져 있고, 왼쪽 편 픽셀들의 intensity가 오른편보다 큰것을 알 수 있습니다.
- 입력이미지
|
- Intensity에 같은 양수를 더해 brightness를 증가시킨 결과입니다.
- 왼편은 거의 흰색에 가까울 정도로 밝아졌고,
- 오른편도 그만큼 밝아졌습니다.
- 이렇듯 brightness 조절은 쉽습니다.
- brightness를 증가한 경우
- 좌측과 우측 모두 환해진 것을 알 수 있다.
|
ㅇ Contrast 증가의 예를 살펴보겠습니다.
- 동일한 입력이미지를 사용했을 때,
- 왼편은 흰색으로 매우 밝아졌지만,
- 오른편은 별 차이가 없습니다.
- 대신 왼쪽과 오른쪽의 intensity 차이가 분명해져서, 선명해졌습니다.
- contrast를 증가한 경우,
- 좌측은 환해졌지만, 오른쪽은 원래보다 더 어두워졌다.
- 밝았던 부분은 더 밝아지고,
- 어두웠던 부분은 더 어두워지기 때문에,
- 두 부분간의 대비 (contrast)가 증가했다.
|
ㅇ Contrast 증가의 원리
- 이것은 밝은 부분과 어두운 부분의 차이를 크게 하는 것을 목적으로 하여,
- 핵심은 곱하기입니다.
- 즉, intensity에 값을 곱하는 겁니다.
- 왜 이러한 곱셈이 contrast를 증가시키는지 알아보겠습니다.
- 예를 들어, 두 개의 픽셀 A, B가 있고,
- 각각의 intensity A = 100, B = 50 라고 하겠습니다.
- Contrast조절을 위해 두 픽셀에 같은 1.5를 곱한다고 하면
- A = 150, B= 75이 됩니다.
- 곱셈에 의해 A는 50만큼 증가하였고, B는 25만큼 증가하였습니다.
- 이로 인해 밝은 부분인 A가 B보다 더 환해졌기 때문에, A와 B간의 차이가 증가하여 contrast가 증가됩니다.
-자세히 살펴보면, 조절전에는 두 픽셀간의 intensity차이 (A - B)가 50 = (100- 50)이었다면,
- 조절후에는 75로 1.5배 만큼 늘어났습니다.
ㅇ 실제 이미지를 이용해서 brightness와 contrast 조절 실험을 진행해 보겠습니다.
- 입력이미지는 아래와 같습니다.
- 도시의 야경을 gray로 촬영한 입력이미지
|
- Brightness를 증가시켜보겠습니다.
- Brightness를 증가시키면
- 이미지가 전체적으로 밝아진다.
- 이는 모든 픽셀의 intensity값이 증가했기 때문입니다.
|
- 위의 실험에서 조절 전후 이미지의 히스토그램이 어떻게 변하는지 살펴보겠습니다.
- 이것을 보면, brightness 조절이 어떤 역할을 하는지 보다 정확히 알 수 있습니다.
- 아래 그림에서
- 1번 히스토그램은 입력이미지의 히스토그램이고,
- 2번은 brightness 증가 후의 것입니다.
- 봉우리가 오른쪽으로 이동한 것이 관찰되는데,
- 픽셀들의 intensity가 전반적으로 증가했기 때문입니다.
|
- 이번에는 contrast를 증가시켜보겠습니다.
- Contrast가 증가되면,
- 어두웠던 부분은 더 어두워지고,
- 밝았던 부분은 더 밝아지면서
- 두 부분이 좀 더 극명하게 대비되는 효과를 볼 수 있습니다.
|
- Contrast 변화가 히스토그램에 어떠한 영향을 끼치는지 살펴보겠습니다.
- 아래 히스토그램들은
- 1번은 입력이미지, 2번은 contrast 증가 후의 것입니다.
- 2번에서 어두운 픽셀의 개수가 크게 증가하였다는 것을 볼 수 있다.
- 밝은 픽셀의 수는 별로 증가하지 않았는데,
- 이는 contrast 적용공식의 작동 방식 때문입니다.
- 여기에 대해서 좀 더 자세히 알아보겠습니다.
|
ㅇ Contrast와 Brightness를 조절하는 공식
- 위의 예에서 보았듯이,
- 조절하는 공식의 기본 아이디어는
- brightness의 경우는 픽셀 intensity를 전체적으로 증가 혹은 감소하는 것이고,
- contrast는 intensity에 비례하여 값을 변화시키는 것입니다.
- 이것을 수학공식으로 표현하면 다음과 같습니다.
- x가 픽셀의 intensity라고 할 때
- 1) contrast를 조절하기 위해서는 적절한 alpha를 계산하여 곱한다.
- 2) brightness를 조절하기 위해서는 beta를 더한다.
- 그렇다면, alpha와 beta는 어떻게 계산하는 것일까요?
|
ㅇ alpha와 beta의 결정
- 우선 contrast와 brightness는 둘 다 1 ~ 200까지 변동가능하다고 가정하겠습니다.
- 그리고 100은 입력이미지 상태그대로를 의미한다고 하겠습니다.
- 따라서, < 100 이면, contrast와 brightness가 감소되는 것을 의미하고,
- > 100이면, 증가하는 것을 의미합니다.
- 아래 코드는 alpha (=a)와 beta (=b)를 결정하는 소스코드입니다.
|
ㅇ Brightness 조절에 따른 alpha와 beta값의 변화
- brightness를 1부터 200까지 조절할 때, alpha와 beta가 어떻게 변하는지 그래프를 그려보겠습니다.
- (brightness == 100)은 조절하지 않음.
- (brightness > 100)은 이미지를 환하게
- (brightness < 100)은 이미지를 어둡게
- 아래 그래프에서 x축은 brightness (1 ~ 200)을 나타내고,
- y축은 alpha와 beta값입니다.
- brightness 조절은 alpha값을 변화시키지는 않습니다.
- alpha = 1을 유지합니다.
|
- beta값은 brightness에 정비례하여 증가 혹은 감소합니다.
|
ㅇ Contrast 변화에 따른 alpha와 beta의 조절
- 이번에는 brightness는 100으로 고정시키고 ( 변경시키지 않는다는 뜻입니다.),
- contrast를 1 ~ 200까지 변화시키면서, alpha와 beta가 어떻게 변하는지 보겠습니다.
- 실제 그래프에서는 1 ~ 180까지만 표시했습니다.
- 이번에도 contrast = 100은 변화가 없다는 것입니다.
- x축은 contrast의 값, y축은 alpah와 beta값입니다.
- Contrast가 증가할 수록
- alpha값이 빠르게 증가합니다.
|
- beta값은 contrast와는 반대로 움직입니다.
- 이것은 alpha값에 의한 변화를 보상하기 위해서입니다.
- 예를 들어, contrast > 100인 경우,
- alpha값이 1보다 커져서, intensity에 곱해서 나오는 결과도 커집니다.
- 따라서, beta는 음수가 되어 이 결과를 조금 작게 할 필요가 있습니다.
- contrast < 100인 경우는 반대로 이해하면 되겠습니다.
|
ㅇ 위그래프를 생성해내기 위한 MATLAB 소스코드
- 소스코드
ㅇ 구현
- Brightness와 contrast 이미지 처리기술을 OpenCV를 이용해서 구현해 보겠습니다.
- 앞서 설명했듯이 픽셀 intensity에 alpha를 곱하고, beta를 더하는 연산이 필요합니다.
- 이러한 연산을 편하게 할 수 있는 함수를 OpenCV가 제공하는데,
- Mat 클래스의 메소드인 convertTo( )입니다.
- convertTo 메소드는, 각 픽셀에 곱할 alpha와 더할 beta를 인수로 받습니다.
- 인수 m은 계산결과를 담은 Mat 객체입니다.
- 이 함수를 이용하면 위에서 설명한 조절을 쉽게 구현할 수 있습니다.
|
ㅇ Brightness와 Contrast 이미지 프로세싱 C++ 구현 코드
- 슬라이드바 (Slide bar)를 이용해서 brightness와 contrast를 조절하는 프로그램을 짜 보았습니다.
- 각각의 조절에 따른 이미지 변화를 관찰할 수 있는 편리한 프로그램입니다.
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
#include <opencv2/opencv.hpp> #include <opencv2/highgui.hpp> #include <iostream> using namespace cv; using namespace std; // // 슬라이드 바의 위치에 해당하는 값 // 최소 0에서 최대 200까지 움직인다. // int init_brightness = 100; int init_contrast = 100; Mat image; const char* keys = { "{@imageName1| img_osaka_night.jpg |input image file} \\ {@imageName2| fruits.jpg|input image file} \\ {N | 1.0 | this is double value} \\ {help h ? | | this is help}" }; void updateBrightnessContrast(int, void*) { int histSize = 255; int var_brightness = init_brightness - 100; int var_contrast = init_contrast - 100; double a, b; if (var_contrast > 0) { double delta = 127.0*var_contrast / 100; a = 255.0 / (255.0 - delta * 2); b = a*(var_brightness - delta); } else { double delta = -128.0*var_contrast / 100; a = (256.0 - delta * 2) / 255.0; b = a*var_brightness + delta; } cout << "a: " << a << " b: " << b << endl; Mat dst, hist; // // image의 각 픽셀값을 변경하여, dst를 만들어 화면에 표시 // pixel = a*pixel + b // image.convertTo(dst, CV_8U, a, b); imshow("image", dst); // dst의 히스토그램을 계산한다. calcHist(&dst, 1, 0, Mat(), hist, 1, &histSize, 0); Mat histImage = Mat::ones(200, 320, CV_8U) * 255; // 320 * 200의 흰색이미지를 만든다. normalize(hist, hist, 0, histImage.rows, CV_MINMAX, CV_32F); int binW = cvRound((double)histImage.cols / histSize); for (int i = 0; i < histSize; i++) { Point leftUp = Point(i*binW, histImage.rows); Point rightDown = Point((i + 1)*binW, histImage.rows - cvRound(hist.at<float>(i))); rectangle(histImage, leftUp, rightDown, Scalar::all(0), -1, 8, 0); imshow("histogram", histImage); } } /* read in an image as a gray */ int main(int argc, char** argv) { CommandLineParser parser(argc, argv, String(keys)); parser.about("This is test program for commandlineparser of opencv"); string inputImage1 = parser.get<string>("@imageName1"); image = imread(inputImage1, IMREAD_GRAYSCALE); if (image.empty() == true) { cout << "Unable to read the image " << inputImage1 << "." << endl; return -1; } namedWindow("image", WINDOW_KEEPRATIO); namedWindow("histogram", WINDOW_KEEPRATIO); createTrackbar("brightness", "image", &init_brightness, 200, updateBrightnessContrast); createTrackbar("contrast", "image", &init_contrast, 200, updateBrightnessContrast); // 이 함수를 호출해야 // 이미지를 화면에 표시할 수 있다. // updateBrightnessContrast(0, 0); waitKey(); return 0; } |
반응형
'Computer Vision by OpenCV' 카테고리의 다른 글
Gamma correction (0) | 2017.05.23 |
---|---|
Histogram Matching, Color mapping, Color Transfer (2) | 2017.04.19 |
CommandLineParser: 명령행 인수의 처리, Command line arguments (0) | 2017.04.13 |
Histogram Equalization의 원리 (0) | 2017.04.11 |
OpenCV normalize (0) | 2017.04.07 |