낮은 랭크 SVD를 사용하여 이미지 압축하기
이 예제에서는 svdsketch
를 사용하여 이미지를 압축하는 방법을 보여줍니다. svdsketch
는 낮은 랭크 행렬 근삿값을 사용하여 이미지의 중요한 특징은 유지하고 덜 중요한 특징은 필터링합니다. svdsketch
와 함께 사용된 허용오차의 크기가 증가할수록 더 많은 특징이 필터링되고 이미지의 세부 수준이 변경됩니다.
이미지 불러오기
도시 도로 사진인 street1.jpg
이미지를 불러옵니다. 이 이미지를 구성하는 3차원 행렬은 uint8
형이므로 이미지를 회색조 행렬로 변환합니다. 원본 행렬의 랭크에 대한 주석을 포함해서 이미지를 봅니다.
A = imread('street1.jpg'); A = rgb2gray(A); imshow(A) title(['Original (',sprintf('Rank %d)',rank(double(A)))])
이미지 압축하기
svdsketch
를 사용하여 허용오차 1e-2
내에서 A
를 근사하는 낮은 랭크 행렬을 계산합니다. svdsketch
에 의해 반환된 SVD 인수를 곱하여 낮은 랭크 행렬을 구성하고 결과를 uint8
로 변환하고 결과 이미지를 봅니다.
[U1,S1,V1] = svdsketch(double(A),1e-2);
Anew1 = uint8(U1*S1*V1');
imshow(uint8(Anew1))
title(sprintf('Rank %d approximation',size(S1,1)))
svdsketch
는 랭크 288 근사를 생성하며, 그 결과로 생성된 이미지의 경계선 일부가 다소 거칠어 보입니다.
이제 1e-1
의 허용오차를 사용하여 이미지를 한 번 더 압축합니다. 허용오차의 크기가 증가할수록 svdsketch
에 의해 생성된 근사의 랭크는 일반적으로 감소합니다.
[U2,S2,V2] = svdsketch(double(A),1e-1);
Anew2 = uint8(U2*S2*V2');
imshow(Anew2)
title(sprintf('Rank %d approximation',size(S2,1)))
이번에는 svdsketch
가 랭크 48 근사를 생성합니다. 대부분의 이미지 특성은 여전히 표시되지만, 추가 압축으로 인해 흐릿함이 증가합니다.
부분공간 크기 제한하기
svdsketch
는 지정된 허용오차를 기반으로 행렬 스케치에 사용할 랭크를 적응 방식으로 결정합니다. 그러나 MaxSubspaceDimension
이름-값 쌍을 사용하여 행렬 스케치를 형성하는 데 사용해야 할 최대 부분공간 크기를 지정할 수 있습니다. 이 옵션을 사용하면 허용오차를 충족하지 않는 행렬이 만들어질 수 있는데, 지정한 부분공간이 너무 작을 수도 있기 때문입니다. 이 경우 svdsketch
는 허용되는 최대 부분공간 크기를 가진 행렬 스케치를 반환합니다.
허용오차가 1e-1
이고 최대 부분공간 크기가 15인 svdsketch
를 사용합니다. 상대 근사오차를 반환하도록 네 번째 출력을 지정합니다.
[U3,S3,V3,apxErr] = svdsketch(double(A),1e-1,'MaxSubspaceDimension',15);
결과의 상대 근사오차와 지정된 허용오차를 비교합니다. svdsketch
는 답을 계산하는 데 1회 반복만 필요하므로 apxErr
에는 하나의 요소가 포함되어 있습니다.
apxErr <= 1e-1
ans = logical
0
결과를 보면 행렬 스케치가 지정된 허용오차를 충족하지 않음을 알 수 있습니다.
심하게 압축된 랭크 15 이미지를 봅니다.
Anew3 = uint8(U3*S3*V3');
imshow(Anew3)
title(sprintf('Rank %d approximation',size(S3,1)))
결과 비교하기
마지막으로, 비교를 위해 모든 이미지를 나란히 봅니다.
tiledlayout(2,2,'TileSpacing','Compact') nexttile imshow(A) title('Original') nexttile imshow(Anew1) title(sprintf('Rank %d approximation',size(S1,1))) nexttile imshow(Anew2) title(sprintf('Rank %d approximation',size(S2,1))) nexttile imshow(Anew3) title(sprintf('Rank %d approximation',size(S3,1)))