L*a*b* 컬러스페이스를 사용한 색 기반 분할
이 예제에서는 L*a*b* 컬러스페이스를 분석하여 직물에서 서로 다른 색을 식별하는 방법을 보여줍니다.
1단계: 영상 수집하기
형형색색의 직물을 촬영한 영상인 fabric.png
를 읽어 들입니다.
fabric = imread("fabric.png"); imshow(fabric) title("Fabric")
2단계: 각 영역의 샘플 색을 L*a*b* 컬러스페이스로 계산하기
영상에서 6가지 주요 색 즉, 배경색, 빨간색, 녹색, 자주색, 노란색, 자홍색을 볼 수 있습니다. 이러한 색을 눈으로 얼마나 쉽게 구별할 수 있는지 보십시오. L*a*b* 컬러스페이스(CIELAB 또는 CIE L*a*b*라고도 함)를 사용하면 이러한 시각적 차이를 수량화할 수 있습니다.
L*a*b* 컬러스페이스는 CIE XYZ 3자극값에서 파생됩니다. L*a*b* 컬러스페이스는 광도층 'L*'(밝기층에 해당함)과 색도층 'a*'(빨간색-녹색 축에 놓인 색의 위치를 나타냄)와 색도층 'b*'(파란색-노란색 축에 놓인 색의 위치를 나타냄)로 구성됩니다.
각 색에 대해 작은 샘플 영역을 선택하고 각 샘플 영역의 평균 색을 'a*b*' 컬러스페이스로 계산하는 접근 방식을 사용합니다. 이러한 색 마커는 각 픽셀을 분류하는 데 사용됩니다.
이 예제에서는 간단히 MAT 파일에 저장된 영역 좌표를 불러옵니다.
load regioncoordinates; nColors = 6; sample_regions = false([size(fabric,1) size(fabric,2) nColors]); for count = 1:nColors sample_regions(:,:,count) = roipoly(fabric,region_coordinates(:,1,count), ... region_coordinates(:,2,count)); end imshow(sample_regions(:,:,2)) title("Sample Region for Red")
rgb2lab
함수를 사용하여 직물 RGB 영상을 L*a*b* 영상으로 변환합니다.
lab_fabric = rgb2lab(fabric);
roipoly
를 사용하여 추출한 각 영역의 평균 'a*' 및 'b*' 값을 계산합니다. 이러한 값은 'a*b*' 컬러스페이스에서 색 마커로 사용됩니다.
a = lab_fabric(:,:,2); b = lab_fabric(:,:,3); color_markers = zeros([nColors, 2]); for count = 1:nColors color_markers(count,1) = mean2(a(sample_regions(:,:,count))); color_markers(count,2) = mean2(b(sample_regions(:,:,count))); end
예를 들어, a*b* 컬러스페이스에서 빨간색 샘플 영역의 평균 색은 다음과 같습니다.
disp([color_markers(2,1), color_markers(2,2)]);
69.8278 20.1056
3단계: 최근접이웃 규칙을 사용하여 각 픽셀 분류하기
이제 각 색 마커는 a* 값과 b* 값을 갖습니다. 해당 픽셀과 각 색 마커 사이의 유클리드 거리를 계산하여 lab_fabric
영상의 각 픽셀을 분류할 수 있습니다. 거리가 가장 작다는 것은 픽셀이 해당 색 마커와 거의 일치한다는 것을 의미합니다. 예를 들어, 픽셀과 빨간색 마커 간의 거리가 가장 작은 경우 이 픽셀은 빨간색 픽셀로 레이블이 지정됩니다.
다음의 색 레이블을 포함하는 배열을 만듭니다. 0 = 배경색, 1 = 빨간색, 2 = 녹색, 3 = 자주색, 4 = 자홍색, 5 = 노란색.
color_labels = 0:nColors-1;
최근접이웃 분류에 사용하기 위해 행렬을 초기화합니다.
a = double(a); b = double(b); distance = zeros([size(a), nColors]);
분류를 수행합니다.
for count = 1:nColors distance(:,:,count) = ( (a - color_markers(count,1)).^2 + ... (b - color_markers(count,2)).^2 ).^0.5; end [~,label] = min(distance,[],3); label = color_labels(label); clear distance;
4단계: 최근접이웃 분류에 대한 결과 표시하기
레이블 행렬에는 직물 영상의 각 픽셀에 대한 색 레이블이 포함되어 있습니다. 레이블 행렬을 사용하여 원래 직물 영상에 있는 객체를 색상별로 분리합니다.
rgb_label = repmat(label,[1 1 3]); segmented_images = zeros([size(fabric), nColors],"uint8"); for count = 1:nColors color = fabric; color(rgb_label ~= color_labels(count)) = 0; segmented_images(:,:,:,count) = color; end
5개의 분할된 색을 몽타주 형태로 표시합니다. 영상에서 색으로 분류되지 않은 배경 픽셀도 표시합니다.
montage({segmented_images(:,:,:,2),segmented_images(:,:,:,3) ... segmented_images(:,:,:,4),segmented_images(:,:,:,5) ... segmented_images(:,:,:,6),segmented_images(:,:,:,1)}); title("Montage of Red, Green, Purple, Magenta, and Yellow Objects, and Background")
5단계: 레이블이 지정된 색의 a* 값과 b* 값 표시하기
별도의 색으로 분류된 픽셀의 a* 값과 b* 값을 플로팅해 최근접이웃 분류가 서로 다른 색 모집단을 얼마나 잘 분리했는지 알 수 있습니다. 표시 목적으로 각 점의 색 레이블을 사용하여 해당 점에 레이블을 지정합니다. 자주색은 명명된 색 값이 아니므로 16진수 색 코드 값의 string형을 사용하여 자주색을 지정합니다.
purple = "#774998"; plot_labels = ["k", "r", "g", purple, "m", "y"]; figure for count = 1:nColors plot_label = plot_labels(count); plot(a(label==count-1),b(label==count-1),".", ... MarkerEdgeColor=plot_label,MarkerFaceColor=plot_label); hold on end title("Scatterplot of Segmented Pixels in a*b* Space"); xlabel("a* Values"); ylabel("b* Values");