2015-11-09
*영상처리
#Pading 처리
가로의 길이가 4의 배수가 아닌 이미지의 경우 픽셀만 차곡차곡 읽어들이면 출력되는 이미지가 밀리는 현상이 발생할텐데, 이것은 패딩(padding)을 고려하지 않았기 때문이다. 예를 들어, bitmap type가 24bit인 경우, 한 픽셀의 크기는 3 바이트다. 그러나, 메모리에 존재하는 비트맵 이미지의 한 줄의 길이는 너비값 * 3이 아닐수도 있다(가로의 길이가 4가 아닌 경우). 한 줄의 길이를 4로 나누어 떨어지도록, 추가 바이트가 존재하기 때문이다. 따라서, 메모리에서 실제 스캔 라인의 길이는 너비와 픽셀 크기를 곱한 값에 패딩 바이트를 더한 값이다. 물론, 너비와 픽셀 당 바이트 수를 곱한 값이 4의 배수라면 추가 바이트는 없다.
그래서 이 패딩을 삽입하여 이미지가 밀리는 현상을 잡아보자.
기존의 코드는 다음과 같다.
ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 0)] = 0; ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 1)] = 0; ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 2)] = 0; |
여기서 비트맵 사이즈를 읽어들인 뒤 uiPad = ST_BFInfor.biWidth % 4;를 추가해준다.
가로가 4의 배수가 아닐때 그 나머지를 패딩에 저장한 뒤 실제 사용할 때에는 패딩비트에 값을 쓰지않고 바로 다음줄로 넘어가기 위한 코드이다.
ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 0) + (iCount_Y * uiPad)] = 0; ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 1) + (iCount_Y * uiPad)] = 0; ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 2) + (iCount_Y * uiPad)] = 0; |
이런식으로 코딩을 해주면 가로가 401이라도 올바르게 이미지가 표현이 된다.
![](https://t1.daumcdn.net/cfile/tistory/216C713756404BA818)
#Bitmap 이미지 Gray(흑백) 만들기
칼라 이미지를 흑백만으로 표현된 Gray 로 만들어 보자.
Gray로 표현하기 위해서는 한픽셀의 RBG값의 평균을 구하여 그 평균값으로 픽셀의 RGB를 구성해주면 된다.
for (iCount_Y = 0; iCount_Y < ST_BFInfor.biHeight; iCount_Y++) { for (iCount_X = 0; iCount_X < ST_BFInfor.biWidth; iCount_X++) { uiAverage = (ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 0) + (iCount_Y * uiPad)] + ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 1) + (iCount_Y * uiPad)] + ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 2) + (iCount_Y * uiPad)]) / 3;
ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 0) + (iCount_Y * uiPad)] = uiAverage; ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 1) + (iCount_Y * uiPad)] = uiAverage; ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 2) + (iCount_Y * uiPad)] = uiAverage; } } |
uiAverage에 픽셀의 RBG평균값을 넣어주고, 그값을 각각의 RGB에 동일하게 넣어준다.
![](https://t1.daumcdn.net/cfile/tistory/277BF23456404D0310)
#RGB 밝게 만들기
RGB값을 밝게 만들어 보자. RGB값을 밝게 만들기 위해서 현재 값에서 일정 수를 더해주면 된다.
for (iCount_Y = 0; iCount_Y < ST_BFInfor.biHeight; iCount_Y++) { for (iCount_X = 0; iCount_X < ST_BFInfor.biWidth; iCount_X++) { //B 밝게하기 uiAverage = ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 0) + (iCount_Y * uiPad)] + 50; if (uiAverage > 255) { uiAverage = 255; } ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 0) + (iCount_Y * uiPad)] = uiAverage;
//G 밝게하기 uiAverage = ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 1) + (iCount_Y * uiPad)] + 0; if (uiAverage > 255) { uiAverage = 255; } ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 1) + (iCount_Y * uiPad)] = uiAverage;
//R 밝게하기 uiAverage = ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 2) + (iCount_Y * uiPad)] + 0; if (uiAverage > 255) { uiAverage = 255; } ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 2) + (iCount_Y * uiPad)] = uiAverage; } } |
이런식으로 하면 각각의 색만 밝게 만들어 볼 수 있다.
![](https://t1.daumcdn.net/cfile/tistory/235ED64F56404F6D1C)
![](https://t1.daumcdn.net/cfile/tistory/245A054F56404F6F20)
![](https://t1.daumcdn.net/cfile/tistory/2754F04F56404F7125)
# 히스토그램 평탄화
![](https://t1.daumcdn.net/cfile/tistory/23769A3856404D4531)
![](https://t1.daumcdn.net/cfile/tistory/237BA63856404D472C)
이러한 기본 지식을 알고 코딩을 해보자
1단계. 히스토그램 구성하기
// 1단계 히스토그램 만들기 for (iCount_Y = 0; iCount_Y < ST_BFInfor.biHeight; iCount_Y++) { for (iCount_X = 0; iCount_X < ST_BFInfor.biWidth; iCount_X++) { ++(uiCountB[ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 0) + (iCount_Y * uiPad)]]); //Blue값 카운터증가 ++(uiCountG[ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 1) + (iCount_Y * uiPad)]]); //Green값 카운터증가 ++(uiCountR[ucBuf[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 2) + (iCount_Y * uiPad)]]); //Red값 카운터증가 } } |
2단계. 누적합 구하기
//2단계 누적합 구하기 //초기화 uiSumR[0] = uiCountR[0]; uiSumG[0] = uiCountG[0]; uiSumB[0] = uiCountB[0];
//누적합 구하기 for (iCount_X = 1; iCount_X < MAXCOLORLEVEL; iCount_X++) { uiSumR[iCount_X] = uiSumR[iCount_X - 1] + uiCountR[iCount_X]; uiSumG[iCount_X] = uiSumG[iCount_X - 1] + uiCountG[iCount_X]; uiSumB[iCount_X] = uiSumB[iCount_X - 1] + uiCountB[iCount_X]; } |
3단계. 정규화
//3단계 정규화 uiAverage = ST_BFInfor.biHeight * ST_BFInfor.biWidth; for (iCount_X = 0; iCount_X < MAXCOLORLEVEL; iCount_X++) { uiCountR[iCount_X] = (uiSumR[iCount_X] * 255) / uiAverage; uiCountG[iCount_X] = (uiSumG[iCount_X] * 255) / uiAverage; uiCountB[iCount_X] = (uiSumB[iCount_X] * 255) / uiAverage; } |
마지막으로 값 대입하기
//기존값에 정규화 시킨값 대체 for (iCount_Y = 0; iCount_Y < ST_BFInfor.biHeight; iCount_Y++) {
for (iCount_X = 0; iCount_X < ST_BFInfor.biWidth; iCount_X++) { ucBuf[(iCount_Y* ST_BFInfor.biWidth * 3) + (iCount_X * 3) + 0 + (iCount_Y*uiPad)] = uiCountB[ucOrg[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 0) + (iCount_Y * uiPad)]];
ucBuf[(iCount_Y* ST_BFInfor.biWidth * 3) + (iCount_X * 3) + 1 + (iCount_Y*uiPad)] = uiCountG[ucOrg[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 1) + (iCount_Y * uiPad)]];
ucBuf[(iCount_Y* ST_BFInfor.biWidth * 3) + (iCount_X * 3) + 2 + (iCount_Y*uiPad)] = uiCountR[ucOrg[(iCount_Y * ST_BFInfor.biWidth * 3) + (iCount_X * 3 + 2) + (iCount_Y * uiPad)]];
} } |
이러한 과정을 거치면 다음과 같은 변화를 알 수 있다. 평할화를 거치면 선명함이 올라간다.(옷의 주름등이 자세히 보인다.)
![](https://t1.daumcdn.net/cfile/tistory/24234C3856404E3313)
![](https://t1.daumcdn.net/cfile/tistory/2110BE3856404E3420)
![](https://t1.daumcdn.net/cfile/tistory/2236273856404E3503)
![](https://t1.daumcdn.net/cfile/tistory/2134463856404E3503)