Как изменить код Matlab, чтобы функция imshow () показывала правильные цвета? - PullRequest
0 голосов
/ 20 апреля 2019

Я написал простой код Matlab, который загружает изображение и выполняет перевод по осям X и Y.Если изображение должно быть переведено на 10 пикселей по оси x, я заполняю первые 10 столбцов 0, сдвигаю все столбцы на 10 единиц вправо и обрезаю правую часть изображения на 10 пикселей.Когда я вставляю положительные значения x, загруженная картинка больше не показывает правильные цвета (с отрицательными значениями это делает), хотя значения RGB верны, когда я печатаю их на экране!

Я уже читал дальшеИнтернет, что imshow () выполняет какое-то масштабирование, но это мне не очень помогло.

Так вот код:

clear;
clc;

picture_in = imread('landscape.jpg');    %load picture
[P,Q,RGB]=size(picture_in);              %obtain size of dimension

%Translation
tx=2;
ty=0;

k=0;
j=0;
h=0;
while k<Q
    j=0;
    while j<P
        h=0;
        while h<RGB
            if (round(k+1-tx)>0)&&(round(k+1-tx)<=Q)&&(round(j+1+ty)>0)&&(round(j+1+ty)<=P) 
                picture_out(j+1,k+1,h+1)=picture_in(round(j+1+ty),round(k+1-tx),h+1);
            else
                picture_out(j+1,k+1,h+1)=0;
            end

            h=h+1;
        end
        j=j+1;
    end
    k=k+1;
end
picture_out;
imagesc(picture_out);

Я был бы очень признателен за помощь.Как я уже упоминал: - если перевод отрицательный, то цвета правильные - когда я смотрю на тензор небольшого изображения (например, 10x10), которое сдвигается на 2 пикселя, я вижу, что первые два столбца равны 0и следующие столбцы содержат значения, которые они должны содержать.Поэтому я думаю, что это проблема imshow ()

EDIT (дополнительный комментарий): выходное изображение имеет только значения 0 или 255 для значений RGB, но ничего между ними нет.

Ответы [ 2 ]

0 голосов
/ 20 апреля 2019

Ваш код работает правильно для меня.

Одна из ваших проблем заключается в том, что вы не выделяете picture_out Он создается при первом назначении ему значения и расширяется каждый раз, когда вы назначаете ему другое значение. Первое значение, которое вы назначаете ему, определяет его тип. Если вы назначите 0 (a double), он станет массивом double. Если вы присвоите значение из picture_in (a uint8), оно станет массивом uint8. В зависимости от того, в каком направлении вы сдвинете изображение, произойдет одно или другое.

A uint8 изображение имеет значения 0-255. Это ваши входные значения. double изображение может хранить значения практически любой величины, но MATLAB всегда предполагает, что такое изображение имеет значения в диапазоне 0-1. Поскольку вы помещаете значения в диапазоне 0-255 в массив double, MATLAB при вызове imagesc будет предполагать, что все, что больше 1, должно быть 1, и поэтому покажет вам полностью белое изображение.

Итак, когда вы сдвигаете изображение влево, вы получаете uint8 выходное изображение, и оно будет отображаться правильно. Когда вы смещаете изображение вправо, вы получаете double выходное изображение, и оно будет отображать все белое.

Решение состоит в том, чтобы правильно распределить массив перед циклами:

picture_out = zeros(size(picture_in),'uint8');

Это дополнительно ускорит ваш код.


Нежелательный совет:

Вы должны научиться использовать петли for, они намного проще, чем петли while. Вместо:

k=0;
while k<Q
    % do something
    k=k+1;
end

вы получите

for k = 1:Q
    % do something
end

Кроме того, вместо цикла с k=0, в то время как k<Q, в MATLAB более естественно выполнять цикл с k=1 при k<=Q, как в цикле for выше.


Однако во многих случаях вам вообще не нужно выполнять цикл. Ваш код может быть переписан намного эффективнее как

picture_out = zeros(size(picture_in),'uint8');
picture_out(:,1+tx:end,:) = picture_in(:,1:end-tx,:);

(для случая tx>0; вы можете изменить индексирование для смещения в другую сторону.)


В качестве альтернативы используйте circshift:

picture_out = circshift(picture_in,tx,2);

Здесь tx также может быть отрицательным.

0 голосов
/ 20 апреля 2019

Поэтому я немного поигрался с кодом и обнаружил, что если я не введу 0 в предложение else вручную, а вместо этого просто возьму его из тензора изображения следующим образом:

else
                picture_out(j+1,k+1,h+1)=picture_in(1,1,1);

тогда все отлично работает. Углубившись немного глубже, я обнаружил, что могу вводить значения вручную, НО мне нужно ввести их как переменную uint8().

В конце код сработает, если я изменю предложение else следующим образом:

else
                picture_out(j+1,k+1,h+1)=uint8(0);
...