2023. 6. 6. 15:01ㆍComputer/영상처리
트루컬러 비트맵 하나의 픽셀이 R, G, B 세 개의 색상 성분 조합으로 표현되는 비트맵이다.
최대 256^3가지의 색상을 표현할 수 있다.(R은 256가지가 가능한데 0부터 시작하므로 최대는 255이다. 실수에 주의하자)
트루컬러 비트맵 처리하기(IppImage 클래스와 RGBBYTE 클래스 이용)
트루컬러 BMP 영상을 불러와 IppDib 클래스 타입의 객체를 생성하고 이후 이 IppDib 객체는 트루컬러 영상 처리가 가능한 IppRgbImage 타입으로 변환한다.(그레이스케일 BMP 영상은 IppDib 타입의 객체를 생성하고 그레이스케일 영상처리를 적용하기 위하여 IppDib 타입의 객체를 IppByteImage 타입으로 변환하였다. 그 후 결과 영상은 다시 IppDib 타입으로 변환하여 화면에 나타낸다.)
typedef IppImage<RGBBYTE> IppRgbImage;
IppImage 클래스에서 컬러 픽셀 참조 방법
IppRgbImage img;
// img에 영상 불러오기
// 1차원 배열 형태로 픽셀 값 참조
RGBBYTE* p1 = img.GetPixels();
// 2차원 배열 형태로 픽셀 값 참조
RGBBYTE** p2 = img.GetPixels2D();
(x, y) 좌표의 색상 값을 받아오기 위해서는 p2[y][x]라고 작성하면 되고, 실제 r, g, b 색상 성분의 값을 알아내기 위해서는 p2[y][x] 바로 뒤에 구조체의 멤버 연산자(.)를 붙여서 각 멤버에 접근하면 된다.
트루컬러 영상처리
- 트루컬러 영상의 반전
void IppInverse(IppRgbImage& img)
{ // 트루컬러 영상의 반전 함수 선언 및 구현
int size = img.GetSize();
RGBBYTE* p = img.GetPixels();
for (int i = 0; i < size; i++) {
p[i].r = 255 - p[i].r;
p[i].g = 255 - p[i].g;
p[i].b = 255 - p[i].b;
}
}
- 트루컬러 영상을 그레이스케일 영상으로 변환
컬러영상을 그레이스케일 영상으로 변환하여 영상처리를 수행하는 이유? 데이터 처리 속도를 빠르게 하기위해
#define RGB2GRAY(r,g,b) (0.299*(r) + 0.587*(g) + 0.114*(b))
트루컬러 영상을 그레이스케일 영상으로 변환하기 위해서는 영상의 모든 픽셀에 대하여 위 공식대로 그레이스케일 값으로 변환해주어야 한다. Convert 함수 내부 for 루프에서 전체 픽셀 개수만큼 호출된다.
class IppImage{
void Convert(const IppImage<RGBBYTE>& img); //템플릿 전문화 추가
}
template<typename T>
void IppImage<T>::Convert(const IppImage<RGBBYTE>& img)
{
CreateImage(img.GetWidth(), img.GetHeight());
int size = GetSize();
T* p1 = GetPixels();
RGBBYTE* p2 = img.GetPixels();
for (int i = 0; i < size; i++)
p1[i] = static_cast<T>(RGB2GRAY(p2[i].r, p2[i].g, p2[i].b));
}
IppRgbImage 타입인 경우에는 기존의 범용적인 템플릿 멤버 함수 Convert(const IppImage<U>& img, bool use_limit = false)가 실행되지 않고 새로 정의한 Convert(const IppImage<RGBBYTE> & img) 함수가 호출된다. 이것을 템플릿 전문이라고 한다. 템플릿 전문화 기법을 이용하여 트루컬러 영상을 그레이스케일 영상으로 변환한다.
다양한 색 모델
영상 처리에서 주로 사용되는 색 모델에는 RGB, HSI, YUV, YIQ, CMYK 등이 있으며, 각각의 색 모델은 상호 변환이 가능하다.
색(color) : 사람의 눈에 있는 원추 세포가 빛의 파장에 따라 다르게 반응 하여 인지하는 것, 가시 광선의 파장: 400~700nm
현재의 색상 표현은 특정 이론에 근거하고 있다. '모든 색상은 세가지 원색(primary color)의 조합으로 표현된다'는 근거로 색 모델들이 있다.
- RGB 색 모델
- 가산 혼합 모델, 빛의 삼원색
- 감산 혼합 모델, 색의 삼원색
- HSI 색 모델, 색상(Hue) : 색의 종류 / 채도(Saturation) : 색의 탁하고 선명한 정도 / 명도(Intensity) : 빛의 밝기
RGB → HIS 변환, 쎄타가 사용된다
HIS → RGB 변환, 구간별로 수식이 다르다, 0도 <= H < 120도 120도 <= H <240도 ... 인 경우,
void RGB_TO_YUV(BYTE R, BYTE G, BYTE B, BYTE& Y, BYTE& U, BYTE& V)
{ // (BYTE) 연산 결과인 실수 값을 다시 BYTE 타입으로 변환
Y = (BYTE)limit(0.299 * R + 0.587 * G + 0.114 * B + 0.5);
U = (BYTE)limit(-0.169 * R - 0.331 * G + 0.500 * B + 128 + 0.5);
V = (BYTE)limit(0.500 * R - 0.419 * G - 0.081 * B + 128 + 0.5);
}
void YUV_TO_RGB(BYTE Y, BYTE U, BYTE V, BYTE& R, BYTE& G, BYTE& B)
{
R = (BYTE)limit(Y + 1.4075 * (V - 128) + 0.5);
G = (BYTE)limit(Y - 0.3455 * (U - 128) - 0.7169 * (V - 128) + 0.5);
B = (BYTE)limit(Y + 1.7790 * (U - 128) + 0.5);
}
- YUV 색 모델
Y : 밝기 정보(luma) / U, V : 색상 정보(chroma)
컬러 비디오 표준에 사용되는 색 모델, 흑백tv는 Y 성분만 Y, U, V는 컬러tv
색상 평면 나누기와 합치기
//YUV 색상 평면 분할
void IppColorSplitYUV(IppRgbImage& imgColor, IppByteImage& imgY, IppByteImage& imgU, IppByteImage&
imgV)
{
int w = imgColor.GetWidth();
int h = imgColor.GetHeight();
int size = imgColor.GetSize();
imgY.CreateImage(w, h);
imgU.CreateImage(w, h);
imgV.CreateImage(w, h);
RGBBYTE* pColor = imgColor.GetPixels();
BYTE* pY = imgY.GetPixels();
BYTE* pU = imgU.GetPixels();
BYTE* pV = imgV.GetPixels();
for (int i = 0; i < size; i++) {
RGB_TO_YUV(pColor[i].r, pColor[i].g, pColor[i].b, pY[i], pU[i], pV[i]);
}
}
//YUV 색상 평면을 합치는 함수
bool IppColorCombineYUV(IppByteImage& imgY, IppByteImage& imgU, IppByteImage& imgV, IppRgbImage& imgColor)
{
int w = imgY.GetWidth();
int h = imgY.GetHeight();
int size = imgY.GetSize();
if (imgU.GetWidth() != w || imgU.GetHeight() != h ||
imgV.GetWidth() != w || imgV.GetHeight() != h)
return false;
imgColor.CreateImage(w, h);
BYTE* pY = imgY.GetPixels();
BYTE* pU = imgU.GetPixels();
BYTE* pV = imgV.GetPixels();
RGBBYTE* pColor = imgColor.GetPixels();
for (int i = 0; i < size; i++)
{
YUV_TO_RGB(pY[i], pU[i], pV[i], pColor[i].r, pColor[i].g, pColor[i].b);
}
return true;
}
컬러 영상 처리 - 컬러 엣지 검출
컬러 영상에서 엣지를 찾는 가장 간단한 방법은 단순히 입력 영상을 그레이스케일 영상으로 변환하여 엣지를 찾는 방법이다. 그러나 색상 및 채도는 다르지만 명도는 유사한 경우, 그레이스케일 정보만을 사용하여 엣지를 찾는 것은 불가능하다.
컬러 영상에서 엣지를 찾기 위해서는 보통 각각의 색상 평면에서 엣지를 찾은 후, 각각의 엣지 성분을 이용하여 유클리디언 거리(Euclidean distance)를 계산하는 방법을 사용한다.
입력 영상을 YUV 색상 평면으로 나눈 후, 각 평면에 대하여 엣지 검출 필터를 사용하여 엣지 정보를 얻는다. 이를 각각 EY, EU, EV라고 표현하기로 하고, 유클리디언 거리를 계산한다.
색상이랑 채도는 다르지만 명도가 유사해서 엣지 검출이 안되는 경우 YUV모델을 이용해서 컬러 경계선을 검출
void IppColorEdge(IppRgbImage& imgSrc, IppByteImage& imgEdge)
{
IppByteImage imgY, imgU, imgV;
IppColorSplitYUV(imgSrc, imgY, imgU, imgV); // 입력 영상을 YUV 색상 평면으로 나누기
IppByteImage edgeY, edgeU, edgeV; // 각 색상 평면에 대하여 프리윗 엣지 검출 마스크 연산을 수행
IppEdgePrewitt(imgY, edgeY);
IppEdgePrewitt(imgU, edgeU);
IppEdgePrewitt(imgV, edgeV);
int w = imgSrc.GetWidth();
int h = imgSrc.GetHeight();
int size = imgSrc.GetSize();
imgEdge.CreateImage(w, h);
BYTE* pEdge = imgEdge.GetPixels();
BYTE* pY = edgeY.GetPixels();
BYTE* pU = edgeU.GetPixels();
BYTE* pV = edgeV.GetPixels();
double dist; // 각 색상 평면의 엣지 성분 값을 이용하여 유클리디언 거리를 계산
for (int i = 0; i < size; i++)
{ // Y 색상 성분에 대하여 가중치 1, U와 V 색상 성분의 엣지 성분에 대해서는 가중치 0.5. 색상, 채도 성분보다 명도 차이에 의한 엣지 차이에 더욱 비중을 둠
dist = (pY[i] * pY[i]) +
(0.5 * pU[i]) * (0.5 * pU[i]) +
(0.5 * pV[i]) * (0.5 * pV[i]);
pEdge[i] = static_cast<BYTE>(limit(sqrt(dist)));
}
}
컬러 영상 처리 - 컬러 히스토그램 균등화
히스토그램 균등화는 영상의 히스토그램을 전체 그레이스케일 영역으로 골고루 펴주는 역할을 함으로써 영상을 보기 좋게 만드는 기법이다.
모든 색상 성분에 히스토그램 균등화를 수행하면 색감이 크게 변함 ➔ 밝기 성분에만 히스토그램 균등화를 수행
'Computer > 영상처리' 카테고리의 다른 글
영상 날카롭게 만들기 (0) | 2023.06.07 |
---|---|
영상의 특징값 추출 방법 (0) | 2023.05.25 |
영상 새로 만들기 기능 구현(대화 상자 만들기) (0) | 2023.05.23 |
영상의 기하학적 변환 (0) | 2023.05.16 |
잡음 생성과 제거 (0) | 2023.05.09 |