Extract, merge color channels
Peponi │ 3/27/2025 │ 8m
Extract, merge color channels
Peponi
1. Introduction
OpenCvSharp4을 이용하면 이미지 색상 공간의 채널을 쉽게 분리, 추출하거나 병합할 수 있다. HSV 색상 공간의 경우 H, S, V 각 채널을 분리할 수 있으며, RGB 색상 공간의 경우 R, G, B 채널이 분리된다. 색상 추출 또한 가능한데, 원하는 범위의 색상 값을 이용하여 특정 색상만을 추려낼 수도 있다.
이런 작업은 실생활에 유용하게 활용될 수 있는데, 간략한 예는 다음과 같다.
- 의료기기 : MRI와 같은 기기를 이용하여 특정 병을 추적할 때 사용할 수 있다.
- 모니터링 : 항공 이미지를 이용하여 농작물의 상태를 모니터링할 수 있다. 감시 카메라 같은 경우에는 사람, 자동차 등을 구분하는 데 활용할 수 있다.
- 자율주행 : 도로의 차로, 횡단보도, 신호등 등을 인식하는 데 활용할 수 있다.
이 문서에서는 OpenCvSharp4의 Cv2.Split()
, Cv2.InRange()
, Cv2.Merge()
메서드를 이용하여 색상 채널을 분리, 추출하고 병합하는 방법을 간략하게 알아본다. 마지막으로, 색상 분리를 응용하여 이미지에서 특정 색상을 제거하는 방법을 알아본다.
실습에 사용할 이미지는 다음과 같다.

2. Split
2.1. BGR image




private void SplitBGR(Mat image)
{
// splitted에 B, G, R 순으로 할당
Mat[] splitted = Cv2.Split(image);
}
2.2. HSV image




private void SplitHSV(Mat image)
{
// HSV 색상 공간으로 변경
using var hsv = image.CvtColor(ColorConversionCodes.BGR2HSV);
// splitted에 H, S, V 순으로 할당
Mat[] splitted = Cv2.Split(hsv);
}
3. Extract
색상 추출의 경우 촬영 장비, 조건 등에 따라 이미지의 컨디션이 변하기 때문에 경우에 따라 가장 유리한 조건을 찾는 것이 필요하다.
3.1. BGR image




추출하려는 색상은 blue, green, red이며 구체적인 값의 범위는 다음과 같이 설정하였다.
- Blue :
(50, 0, 0)
~(255, 160, 160)
- Green :
(0, 50, 0)
~(160, 255, 160)
- Red :
(0, 0, 50)
~(160, 160, 255)
private void ExtractBGR(Mat image)
{
using var blue = new Mat();
using var green = new Mat();
using var red = new Mat();
// Cv2.InRange(input, lower bound, upper bound, output)
Cv2.InRange(image, new(50, 0, 0), new(255, 160, 160), blue);
Cv2.InRange(image, new(0, 50, 0), new(160, 255, 160), green);
Cv2.InRange(image, new(0, 0, 50), new(160, 160, 255), red);
}
3.2. HSV image




추출하려는 색상은 blue, green, red (Red의 경우 색상 공간 양쪽 끝에 걸쳐있어 따로 분리하여 추출한다) 이며 구체적인 값의 범위는 다음과 같이 설정하였다.
- Blue :
(90, 50, 50)
~(150, 255, 255)
- Green :
(30, 50, 50)
~(90, 255, 255)
- Red (Low) :
(0, 50, 50)
~(30, 255, 255)
- Red (High) :
(150, 50, 50)
~(180, 255, 255)
private void ExtractHSV(Mat image)
{
// H : 0 ~ 180 (360도까지의 값을 2로 나누어 입력), S : 0 ~ 255 , V : 0 ~ 255
// 색상 참조 : https://ko.rakko.tools/tools/30/
using var hsv = image.CvtColor(ColorConversionCodes.BGR2HSV);
using var blue = new Mat();
using var green = new Mat();
using var redLow = new Mat();
using var redHigh = new Mat();
Cv2.InRange(hsv, new(90, 50, 50), new(150, 255, 255), blue);
Cv2.InRange(hsv, new(30, 50, 50), new(90, 255, 255), green);
Cv2.InRange(hsv, new(0, 50, 50), new(30, 255, 255), redLow);
Cv2.InRange(hsv, new(150, 50, 50), new(180, 255, 255), redHigh);
using var red = redLow + redHigh;
}
4. Merge


여기서는 Blue, red 색상을 추출한 다음 해당 색상만 merge하여 이미지를 재생성한다. 예시의 이미지 색상 공간은 HSV로 진행한다.
private void MergeHSVWithBR(Mat image)
{
// HSV 색상 공간으로 변경
using var hsv = image.CvtColor(ColorConversionCodes.BGR2HSV);
using var blue = new Mat();
using var redLow = new Mat();
using var redHigh = new Mat();
Cv2.InRange(hsv, new(90, 50, 50), new(150, 255, 255), blue);
Cv2.InRange(hsv, new(0, 50, 50), new(30, 255, 255), redLow);
Cv2.InRange(hsv, new(150, 50, 50), new(180, 255, 255), redHigh);
using var red = redLow + redHigh;
using var merged = new Mat();
// BGR 순으로 할당
Cv2.Merge([blue, Mat.Zeros(image.Size(), MatType.CV_8UC1), red], merged);
}
5. Remove specific color



색상 추출과 bitwise 연산을 결합하면 특정 색상 영역을 제거한 이미지를 만들 수 있다. 다음 코드는 원본 이미지에서 blue, red를 추출하여 마스크를 생성, 이를 원본 이미지와 and 연산을 수행하여 green 색역을 제거하는 예시이다.
private void RemoveGreenUsingBRMask(Mat image)
{
// HSV 색상 공간으로 변경
using var hsv = image.CvtColor(ColorConversionCodes.BGR2HSV);
using var blue = new Mat();
using var redLow = new Mat();
using var redHigh = new Mat();
// Blue, red channel 추출 및 mask 생성
Cv2.InRange(hsv, new(90, 50, 50), new(150, 255, 255), blue);
Cv2.InRange(hsv, new(0, 50, 50), new(30, 255, 255), redLow);
Cv2.InRange(hsv, new(150, 50, 50), new(180, 255, 255), redHigh);
using var mask = blue + redLow + redHigh;
// And 연산을 통해 mask의 검정 영역 제거
using var greenRemoved = new Mat();
Cv2.BitwiseAnd(image, image, greenRemoved, mask);
}
TIP
Bitwise 연산에 대한 자세한 내용은 Bitwise operations를 참조한다.