2014-12-29 3 views
1

아래에 표시된 이미지 im1im2이 두 개 있습니다. im2 사진은 im1과 동일하지만 그 차이점은 색상뿐입니다. im1은 각 색상 채널에 대해 RGB 범위가 (0-255, 0-255, 0-255)이며 im2은 RGB 범위가 (201-255, 126-255, 140-255)입니다. 내 운동은 추가 효과를 바꾸어 최대한 을 im1으로 복원 할 수 있습니다. 나는 2 가지 생각을 염두에두고 있습니다. 첫 번째는 히스토그램을 일치시켜 두 색상이 동일합니다. histeq을 사용해 보았지만 이미지의 일부만 복원합니다. im2의 막대 그래프를 정확히 im1과 동일하게 변경하는 방법이 있습니까? 두 번째 방법은 각각의 픽셀 값을 im1에서 im2으로 복사하는 것이지만 원본 이미지 상태를 복원하지 않기 때문에 잘못되었습니다. 이미지를 복원 할 제안이 있습니까? 아래MATLAB에서 이미지 색상 보정

enter image description here

enter image description here

+0

'color1'과'color2' 사이에 선형 매핑을 사용할 수 없습니까? – NKN

+0

선형 매핑이라고하면 im2 행렬의 각 픽셀 값을 의미하므로 im1에 복사합니까? 이것은 단지 복사 붙여 넣기 여부입니다. – KostasRim

+0

아니요,'r = 220'처럼'im2'에서 값을 얻습니다. 그리고 그것을'im1' 범위의 값으로 매핑하려고합니다. 선형 방정식을 만들어이를 매핑 할 수 있습니다. 복사 붙여 넣기가 아닙니다. – NKN

답변

4

@sepdek 꽤 많이 언급 @NKN 방법을 제안,하지만 난 다른 접근 방식을 제공합니다. 제가 제안 할 수있는 또 다른 대안은 최소 제곱 평균 솔루션을 기반으로 색상 보정을 수행하는 것입니다. 여기서 암시하는 것은 픽셀을 im2에서 im1으로 변환하는 것은 가중치의 선형 조합을 필요로한다는 것입니다. 즉, 빨강, 녹색 및 파랑 구성 요소가 손상된 이미지 (im2)에서 3 x 1 벡터로 모양이 지정된 RGB 픽셀의 경우 깨끗한 이미지 (im1)에서 해당 픽셀을 얻는 선형 변환이 있습니다. 즉, 우리는 다음과 같은 관계를 가지고 있습니다.

A이 경우에는 3 x 3 매트릭스가됩니다. 이것은 근본적으로 행렬 곱셈을 수행하여 출력 보정 픽셀을 얻습니다. im2의 입력 RGB 픽셀은 X이고 im1의 출력 RGB 픽셀은 Y이됩니다. 픽셀을 im1im2 쌍으로 표시하면 YX에 따라 열을 설정할 수있는만큼 원하는만큼 픽셀까지 확장 할 수 있습니다. 일반적으로, 이것은 XY 내지 3 x N 행렬을 더 확장 할 것이다. A 행렬을 찾으려면 최소 평균 제곱 오류 솔루션을 찾으십시오. 나는 그것에 들어가지 않을 것이지만, A의 최적 행렬을 찾으려면, 이것은 의사 - 역행렬을 찾아야한다. 여기에 우리의 경우, A가에 따라서 동일한 것 :

이 매트릭스 A를 찾으면, 당신은 이미지의 각 픽셀을 가지고 그것이 3 × 1 벡터가되도록을 형성해야합니다, 위의 방법과 마찬가지로 A에이 벡터를 곱하십시오. 당신이 아마 스스로에게 묻는 한 가지 방법은 위의 접근 방식을 적용하기 위해 두 이미지에서 어떤 종류의 픽셀을 가져와야합니까? 사용자가 준수해야 할 지침 중 하나는 에서 두 이미지간에 동일한 공간 위치을 샘플링해야한다는 것입니다. 따라서, 행 4, 열 9에서 픽셀을 가져 오려면 im1im2의 두 픽셀이 동일한 행과 같은 열에서 나오는지 확인해야합니다. XY에있는 동일한 해당 열.

이 접근법의 또 다른 작은 경고는 좋은 해결책을 얻기 위해 이미지에서 많은 픽셀을 샘플링해야한다는 것과 샘플링의 확산이 전체 이미지에 있는지 확인해야한다는 것입니다 . 샘플링을 작은 영역에 국한 시키면 색 분포가 충분하지 않아 출력이 좋지 않게 보입니다. 문제에 대해 얼마나 많은 픽셀을 선택 하느냐는 사용자의 몫이지만, 경험상 출력물이 고원 상태에 이르러 아무런 차이가없는 지점까지 도달하게됩니다. 데모 목적으로 이미지 전체에서 무작위로 2000 픽셀을 선택했습니다.

마찬가지로 코드는 다음과 같습니다. 나는 을 사용하여 1에서 M까지 무작위 순열을 생성합니다. 여기서 M은 이미지의 총 픽셀 수입니다. 이들은 선형 인덱스를 생성하여 이미지에서 샘플링하고 행렬을 구성 할 수 있습니다. 위의 방정식을 적용하여 A을 찾은 다음 각 픽셀을 취하여 A과 함께 행렬 곱을 적용하여 출력을 얻습니다. 속히 :

close all; 
clear all; 
im1 = imread('http://i.stack.imgur.com/GtgHU.jpg'); 
im2 = imread('http://i.stack.imgur.com/wHW50.jpg'); 

rng(123); %// Set seed for reproducibility 
num_colours = 2000; 
ind = randperm(numel(im1)/size(im1,3), num_colours); 

%// Grab colours from original image 
red_out = im1(:,:,1); 
green_out = im1(:,:,2); 
blue_out = im1(:,:,3); 

%// Grab colours from corrupted image 
red_in = im2(:,:,1); 
green_in = im2(:,:,2); 
blue_in = im2(:,:,3); 

%// Create 3 x N matrices 
X = double([red_in(ind); green_in(ind); blue_in(ind)]); 
Y = double([red_out(ind); green_out(ind); blue_out(ind)]); 

%// Find A 
A = Y*(X.')/(X*X.'); 

%// Cast im2 to double for precision 
im2_double = double(im2); 

%// Apply matrix multiplication  
out = cast(reshape((A*reshape(permute(im2_double, [3 1 2]), 3, [])).', ... 
      [size(im2_double,1) size(im2_double,2), 3]), class(im2)); 

는 이제 서서히이 코드를 통해 가자. StackOverflow에서 직접 이미지를 읽습니다. 이후, 나는 rng을 사용하여 같은 결과를 재생산 할 수 있도록 시드를 설정합니다. 시드를 설정하면 내가 한 임의의 픽셀 선택을 재현 할 수 있기 때문에 유용합니다. 선형 인덱스를 생성 한 다음 im1im2에 대한 3 x N 행렬을 만듭니다. A을 찾는 것이 내가 설명한 방법이지만 정확히 rdivide// 연산자에 익숙하지 않은 것입니다. rdivide은 연산자의 오른쪽에서 역함수를 찾은 다음 왼쪽에있는 것과 곱합니다. 이것은 오른쪽면의 역수를 따로 계산하지 않고 계산을 수행하는보다 효율적인 방법입니다. 그런 다음 완료되면 왼쪽으로 곱합니다. 사실, MATLAB은 역수를 따로 계산하지 않도록 경고하고 대신 연산자를 나누어야합니다. 다음으로, A이 부동 소수점 값이 될 가능성이 높으므로 을 double으로 캐스팅 한 다음 각 픽셀을 A으로 곱하여 결과를 계산합니다. 이 코드의 마지막 줄은 꽤 겁나는 것처럼 보였습니다. 그러나 제가 이것을 파생시킨 방법을 알고 싶다면이 방법을 사용하여 빈티지 스타일의 사진을 만들었습니다.이 방법을 사용하면이 접근 방식과 같은 매트릭스 곱셈이 필요하며 여기에서 How do I create vintage images in MATLAB?을 읽을 수 있습니다. out은 최종 이미지를 저장합니다.

enter image description here

이제 출력이 완전히 스크램블 보이지만, 색상 분포 다소 모방 입력 원본 이미지의 모습 :이 코드를 실행하고 out의 모습을 보여주는 후, 이것은 우리가 무엇을 얻을 수 있습니다. 왜 그런지에 대한 몇 가지 설명이 있습니다 :

  1. 양자화 잡음이 있습니다. 최종 이미지를 살펴보면 다양한 흰색 얼룩이 나타납니다. 이것은 아마도 이미지를 압축 할 때 도입 된 양자화 오류 때문일 것입니다. 이미지 사이에 같은 색상으로 매핑해야하는 픽셀은 양자화로 인해 약간의 차이가 있습니다. 그 결과 우리는 얼룩이 생깁니다.
  2. im1에 매핑되는 im2의 색상이 두 가지 이상 있습니다. im2에서 하나 이상의 색이 im1으로 매핑되는 경우 행렬 A을 사용한 선형 곱셈은 im2에 단일 픽셀이 주어진 경우 im1에 대해 두 가지 종류의 색상을 생성 할 수 없습니다.대신, 최소 제곱 평균 솔루션은 오류를 최소화하고 가능한 최상의 색상을 제공하는 색상을 생성하고 시도합니다. 이 정확한 이유 때문에 이미지의 얼굴과 다른 세부 묘사가 모호한 것 같습니다.
  3. 이미지가 시끄 럽습니다. im2이 완전히 깨끗하지 않습니다. 나는 또한 모든 채널에서 소금과 후추 소음의 다양한 지점을 볼 수 있습니다. 이 방법의 한 가지 나쁜 점은 이미지가 노이즈의 영향을 받으면이 방법은 원본 이미지를 충실하게 재구성하지 않는다는 것입니다. 귀하의 이미지는 만 잘못된 색상 매핑으로 인해 손상 될 수 있습니다. 다른 유형의 이미지 노이즈가있을 경우이 방법은 잡음이 많은 이미지를 기반으로 원래 이미지를 재구성하려는 경우에는 효과가 없습니다. 시끄러운 이미지에는 원본 이미지에 전혀 존재하지 않는 픽셀이 있으므로 이전과 같은 방식으로 되돌릴 수 있습니다.

    enter image description here

    나는를 생성하는 데 사용되는 코드 :

원본 이미지와 출력 이미지 사이의 각 채널의 막대 그래프를보고 싶을 경우, 이것은 우리가 무엇을 얻을 도 이상이었다 우측의 복원 영상에 대해 동일한 히스토그램을 나타내고있다

names = {'Red', 'Green', 'Blue'}; 
figure; 
for idx = 1 : 3 
    subplot(3,2,2*idx - 1); 
    imhist(im1(:,:,idx)); 
    title([names{idx} ': Image 1']); 
end 

for idx = 1 : 3 
    subplot(3,2,2*idx); 
    imhist(out(:,:,idx)); 
    title([names{idx} ': Output']); 
end 

왼쪽은 원본 이미지의 빨강, 초록, 파랑의 히스토그램을 보여준다. 일반적인 모양이 원본 이미지를 모방 한 것처럼 보일 수도 있지만 전체적으로 일부 스파이크가 있습니다. 양자화 노이즈 및 두 이미지의 색상 사이의 고유하지 않은 매핑 때문일 가능성이 큽니다.


모두 모두,이 내가 할 수있는 최선입니다,하지만 난 그게 가능하지 않은 것을 보여주기 위해 .... 운동의 요점이었다 생각합니다.

색상 보정을 수행하는 방법에 대한 자세한 내용은 Richard Alan Peters' II Digital Image Processing slides on colour correction을 확인하십시오. 이것이 내가 시작한 것이고, A을 계산하는 방법의 유도는 그의 슬라이드에서 찾을 수 있습니다. 아마도 당신은 미래의 일에서 그가 이야기하는 것을 사용할 수있을 것입니다.

행운을 빈다.

+0

답장을 보내 주셔서 감사합니다. 최종 이미지는 im1과 다릅니다. imhist()를 사용하여 out과 im1의 각 채널에 대한 RGB 색상을 비교했습니다. rgb 색상이 [0-255]의 범위에 똑같이 뻗어 있지만 im1 색상처럼 복원되지 않은 것 같습니다. im1의 히스토그램은 im2와 완전히 다릅니다. 같은 이미지이지만 im2는 붉다. 어떤 제안? Btw는 rgb 색상을 플러스 인 0 - 255 범위로 밝혀 냈습니다. 내가 지금 찾을 필요가 있다고 생각하는 것은 서로의 이미지를 일치시키기 위해 히스토그램을 변경하는 방법입니다. – KostasRim

+0

@KostasRim - 실제로 이미지를 게시 한 경우 도움이됩니다. 이것은 자신을 (그리고 다른 사람들이) 추측하는 것을 막을 수 있습니다. 또한, 확실하게 히스토그램 매칭을 수행 했습니까? 세 가지 채널 모두에 대해 별도로 처리 했습니까? 편집을 시도하고보십시오. – rayryeng

+0

@ KostasRim - 아마도 색상 표준화와 히스토그램 매칭 **의 조합을 사용합니까? 내가 처음 제안한 것을 시도하고, 나의 편집에서 나의 다른 제안들 중 하나를 따르고, 당신이 얻는 것을 보아라. – rayryeng

0

im2의 값을 im1의 값으로 매핑하려면 크기 조정 기능이 필요합니다. 이것은 매우 간단하며 그러한 경우에 사용할 수 있도록 스케일링 함수를 작성할 수 있습니다. 다음 기본적인 스케일링 매핑 일 것이다 :

out_value = min_output + (in_value - min_input) * (outrange/inrange) 

inrange=max_input-min_input의 범위 및 사상은 다양한 outrange=max_output-min_output 내에 출력값 out_value 결과 입력 값 in_value가 주어진. 정확한 매핑을 위해서는 최소 입력 및 출력 범위 범위 ( min_inputmin_output)도 고려해야합니다.
은 스케일링 함수의 예를 들면 다음과 같은 코드를 참조 :

% 
% scale the values of a matrix using a set of limits 
% possible ways to use: 
% y = scale(x, in_range, out_range) --> ex. y = scale(x, [8 230], [0 255]) 
% y = scale(x, out_range)   --> ex. y = scale(x, [0 1]) 
% 
function y = scale(x, varargin); 
    if nargin<2, 
     error([upper(mfilename),':: Syntax: y=',mfilename,'(x[,in_range],out_range)']); 
    end; 
    if nargin==2, 
     inrange=[min(x(:)) max(x(:))];  % compute the limits of the input variable 
     outrange=varargin{1};    % get the output limits from the arguments 
    else 
     inrange=varargin{1};    % get the input limits from the arguments 
     outrange=varargin{2};    % get the output limits from the arguments 
    end; 

    if diff(inrange)==0,     % row or column vector matrix or scalar 
     % just do a clipping... 
     if x>=outrange(2), 
      y=outrange(2); 
     elseif x<=outrange(1), 
      y=outrange(1); 
     else 
      y=x; 
     end; 
    else 
     % actually scale the data 
     % using: out = min_output + (x-min_input) * (outrange/inrange) 
     y = outrange(1) + (x-inrange(1))*abs(diff(outrange))/abs(diff(inrange)); 
    end; 

이 함수 값의 행렬을 얻고, 원하는 범위로 스케일링.귀하의 경우
는 그것을 다음과 같이 (가변 img를 스케일링 im2이다)을 사용할 수있다 :

for i=1:size(im1,3),  % for each of the input/output image channels 
    output_range = [min(min(im1(:,:,i))) max(max(im1(:,:,i)))]; 
    img(:,:,i) = scale(im2(:,:,i), output_range); 
end; 

im2이 방법은 한 번에 하나의 채널 im1의 값의 범위를 확장한다. 출력 변수 img이 원하는 것이어야합니다.

+0

답장을 보내 주셔서 감사 드리며, 크기를 조정하려했지만 결과 이미지가 im1과 같지 않았습니다. – KostasRim

+0

@KostasRim 맞습니까? 나는 이미 그것을 테스트하고 잘 작동합니다. 모든 테이블은 double [0 ... 255]입니다. 더블은 필수품입니다.값에 따라 나누기 때문에 반올림 오류가 발생할 수 있지만 9 번째 자리까지 발생해야합니다. – sepdek

+0

@ KostasRim 이제 질문에 포함 된 이미지를 보았을 때 문제가 훨씬 더 복잡하다고 믿었습니다. 일반적으로 저하 된 이미지로 이어진 초기 변형에 대한 지식이 있고 가역성이면 데이터의 정수 특성으로 인한 양자화 오류를 고려해 볼 때이를 뒤집을 수 있습니다. – sepdek

관련 문제