opencv

Color Transform

꼰대코더 2025. 10. 30. 15:27

이미지의 각 픽셀에 들어있는 R, G, B 값을 새로운 R′, G′, B′ 값으로 변환하려면 Color Transform(색 변환) 기법을 고려할 수 있습니다.
OpenCV는 내부적으로 BGR 순서를 사용하므로 예제를 읽을 때 채널 순서에 주의하세요.

예시(스캔된 채널의 최대값이 다음과 같을 때 — OpenCV 배열은 BGR 순서):

R 채널 최댓값 = (10, 10, 230)
G 채널 최댓값 = (10, 230, 10)
B 채널 최댓값 = (230, 10, 10)
 

목표: 스펙트럼(명도·색분포)을 넓혀 대비를 개선하고 싶다면, 각 채널의 타겟 값을 다음처럼 조정할 수 있습니다.

목표 R = (1, 1, 250)
목표 G = (1, 250, 1)
목표 B = (250, 1, 1)
 
 

이렇게 채널별로 값을 재배치하거나 스케일링하면 결과적으로 히스토그램이 확장되어(contrast stretching) 이미지 전체의 색상과 밝기 범위가 넓어집니다. 실무에서는 cv::transform이나 채널별 LUT(lookup table)를 사용해 안전하고 빠르게 적용할 수 있으며, 원하는 효과를 얻기 위해 채널별 정규화나 감마 보정과 함께 사용하는 것이 일반적입니다.

 

변환 매트릭스(M) 구하기

여기서 det(A)는 행렬식(Deterninat)이고 adj(A)는 수반행렬이다.

각각 구하는 식의 이론은 아래 사이트에서 확인하길 바란다.
https://m.blog.naver.com/lagrange0115/222087882248

https://portrait-of-youngblood.tistory.com/12

 

OpenCV (C++)에서의 M 계산 방법

    // Source colors (A)
    cv::Mat A = (cv::Mat_<double>(3,3) <<
        10, 10, 230,    // RED
        10, 230, 10,    // GREEN
        230, 10, 10     // BLUE
    );

    // Target colors (B)
    cv::Mat B = (cv::Mat_<double>(3,3) <<
        1, 1, 250,
        1, 250, 1,
        250, 1, 1
    );

    // Compute inverse of A
    cv::Mat A_inv = A.inv();

    // Compute M = A⁻¹ × B
    cv::Mat M = A_inv * B;

    cout << "Transformation matrix M:" << endl << M << endl;

Transformation matrix M:
[1.090545454545455, -0.04127272727272727, -0.04127272727272727;
 -0.04127272727272727, 1.090545454545454, -0.04127272727272727;
 -0.04127272727272727, -0.04127272727272727, 1.090545454545454]

 

OpenCV (C++)에서 M 을 칼러이미지 전체에 적용

cv::Mat image = cv::imread("d:\\image.png");
cv::Mat img64;
image.convertTo(img64, CV_64F);
cv::Mat result;
cv::transform(img64, result, M);

result.convertTo(result, CV_8U, 1.0, 0.0);