- 행렬의 덧셈과 뺄셈으로 간단하게 영상의 밝기 조절 가능
- openCV에서 제공하는 영상의 밝기 조절
- 사용자가 직접 영상의 픽셀 값을 참조하여 밝기 조절
- 트랙바를 이용하여 실시간으로 밝기 조절
▶그레이스케일 영상
- Why 그레이? ->과거에 개발되었던 많은 영상 처리 알고리즘이 주로 그레이스케일 영상을 대상으로! ->컬러영상의 경우 R,G,B로 이루어져 그레이 스케일보다 3배의 메모리와 연산시간이 필요
º 그레이스케일 형태의 Mat 객체를 생성하는 3가지 방법
①imread 두번째 인자에 IMREAD_GRAYSCALE
Mat img1 = imread("lenna.bmp", IMREAD_GRAYSCALE);
②cvtColor() 함수 사용
Mat img3 = imread("minjin.bmp", IMREAD_COLOR);
Mat img4;
cvtColor(img3, img4, COLOR_BGR2GRAY);
-Mat 객체에 저장된 색상 정보를 변경할 때 사용하는 함수
-전달인자: 입력 영상, 출력 영상, 컬러변환코드
③그레이스케일 영상을 저장할 새로운 Mat 객체 생성 -> CV_8UC1 타입 객체 생성
Mat img2(480, 640, CV_8UC1, Scalar(0));
▶openCV에서 제공하는 함수를 통해 영상의 밝기 조절
- 영상의 전체적인 밝기를 조절하여 좀 더 밝거나 어두운 영상을 만드는 작업
- 모든 픽셀에 양수의 값을 + -> 영상이 밝아짐, 양수의 값 - -> 영상이 어두워짐
- 영상의 밝기 조절을 수식으로 표현
dst(x,y) = src(x,y) + n
-dst = 출력영상, src = 입력영상, n = 양수(밝기↑), 음수(밝기↓)
※영상의 픽셀 값은 그레이스케일의 최대값인 255와 최솟값인 0으로 설정!
∴ 원소자료형이 가질 수 있는 값의 범위를 벗어나는 경우 해당 자료형의 최소/최대로 설정하는 연산인 포화(saturate)연산 사용!
dst(x,y) = saturate(src(x,y) + n);
▶영상의 밝기 조절 직접 구현
(openCV에서 제공하는 함수를 사용하지 않고 직접 구현하는 방법)
=>Mat 행렬의 원소값 참조 방법 사용
= 입력 영상의 모든 픽셀을 방문하면서 픽셀값에 일정한 상수를 더하거나 or 뺌
Mat dst(src.rows, src.cols, src.type());
- 입력 영상 src와 크기, 타입이 같은 결과 영상인 dst 생성
- cf) 사용자가 직접 만들 수 있지만 dst 영상의 픽셀값을 참조하려고 하면 에러가 발생할 수 있음
dst.at<uchar>(j,i) = src.at<uchar>(j,i) + 100;
- 입력 영상에서 (i,j) 좌표에서의 픽셀 값에 100을 더하여 결과 영상의 픽셀값으로 설정
- Mat::at() 함수의 첫번째 인자 = y축 좌표에 해당하는 j, 두 번째인자 = x축 좌표에 해당하는 i (즉, (j = y축 좌표, i = x축 좌표)
※ 포화 연산을 수행하지 않으면 밝은 픽셀 주변에서 급격하게 어두운 픽셀이 나타남 ※
why?
unsigned char a = 256;
count << "a = " << a << end1;
- C/C++에서 unsigned char 자료형은 1바이트의 메모리 공간 사용 -> 0~255 정수값 사용 => 256 대입시 자동으로 0으로 변환되어 저장
- 즉, 위 코드를 실행 시 입력 영상의 픽셀에 100을 더하고 255보다 큰 픽셀은 오히려 0에 가까운 어두운 픽셀로 바뀜
그렇다면,
for (int j = 0; j < src.rows; j++){
for(int i = 0 i < src.cols; i++){
int v = src.at<uchar>(j,i) + 100;
dst.at<uchar>(j,i) = v > 255 ? 255 : v < 0 ? 0 : v;
}
}
- 변수 v는 int로 선언하여 255보다 큰 변수 저장 가능
- 삼항 조건 연산자를 통해 조건에 맞지 않는다면 0-255 사이로 변환
But, OpenCV에서는 행렬의 자료형에 맞게끔 포화 연산을 수행하는 saturate_cast()라는 캐스팅 함수 지원!
template<> inline
uchar saturate_cast<uchar>(int v);
- <> 괄호 사이에 사용하는 자료형 명시
▶영상의 명암비 조절
- 명암비 = 영상에서 밝은 영역과 어두운 영역 사이에 드러나는 밝기 차이의 강도
- 전체 픽셀에 적절한 시루를 곱하는 곱셈 연산 사용
- 명암비가 낮은 영상 = 객체 간의 구분이 잘 되지 않아 전반적으로 흐릿한 느낌
- 명암비가 높은 영상 = 사물의 구분이 잘 되며 선명한 느낌
dst(x,y) = saturate(s*src(x,y))
- 기본적인 명암비 조절 수식
- 상수 s = 0보다 큰 양의 실수 => 255보다 큰 경우가 발생할 수 있으므로 포화 연산도 함께 사용
- But, 영상이 전반적으로 어두워지거나, 결과 영상의 밝기가 너무 쉽게 포화되는 단점
▶효과적인 명암비 조절 방법
- 명암비를 효과적으로 높이기 위해 => 밝은 픽셀은 더욱 밝게, 어두운 픽셀은 더욱 어둡게!
- 픽셀의 밝고 어두움의 기준은? 그레이스케일 범위 중간값인 128을 기준으로 or 입력 영상으 평균 밝기
dst(x,y) = src(x,y) + (src(x,y) - 128)*α
▶히스토그램 분석
① 히스토그램 구하기
- 히스토그램(histogram) = 영상의 픽셀 값 분포를 그래프 형태로 표현
- 빈(bin) = 히스토그램에서의 가로축
-그레이스케일 영상의 경우 256개의 빈을 가지는 히스토그램을 구하는 것이 일반적
But! 히스토그램의 빈 개수가 항상 픽셀 값 범위와 같아야 하는 것은 아니다
히스토그램의 빈 개수가 줄어들면 히스토그램이 표현하는 영상의 픽셀 값 분포 모양이 좀 더 대략적인 형태로 바뀜
- calcHist() = OpenCV에서 영상의 히스토그램을 구하는 함수
void calcHist(const Mat* images, int nimages, const int* channels,
InputArray mask, OutputArray hist, int dims, const int* histSize,
const float** ranges, bool uniform = true, bool accumulate = false);
-모두 10개인 인자, uniform과 accumulate의 경우 기본값(true, false)을 가지고 있으므로 최소 8개의 인자 설정
② 히스토그램 스트레칭
- 영상의 히스토그램이 그레이스케일 전 구간에 걸쳐서 나타나도록 변경하는 선형 변환 기법
- 명암비가 낮은 영상의 경우 히스토그램이 특정 구간에 집중 -> 이러한 히스토그램을 펼쳐서 히스토그램 그래프가 그레이스케일 전 구간에서 나타나도록 변환하는 기법
- 히스토그램 스트레칭을 수행한 영상은 명암비가 높아지기 때문에 대체로 보기 좋게 바뀜
③ 히스토그램 평활화
- 영상의 픽셀 값 분포가 그레이스케일 전체 영역에서 골고루 나타나도록 변경하는 알고리즘 = 픽셀 값 분포 조절
- equalizeHist() = 그레이스케일 영상의 히스토그램 평활화를 수행하는 함수
void equalizeHist(InputArray src, OutputArray dst);
'컴퓨터 비전' 카테고리의 다른 글
영상의 산술 및 논리 연산 (0) | 2020.02.25 |
---|---|
OpenCV 주요 기능 (0) | 2020.02.14 |
OpenCV 주요 클래스 (0) | 2020.02.12 |
댓글