Почему значения изображений различаются в Matlab и OpenCV? - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть оригинальное изображение:

enter image description here

Затем я читаю его, создаю PSF и размываю его в Matlab:

lenawords1=imread('lenawords.bmp');
%create PSF
sigma=6;
PSFgauss=fspecial('gaussian', 8*sigma+1, sigma);

%blur it
lenablur1=imfilter(lenawords1, PSFgauss, 'conv');
lenablurgray1=mat2gray(lenablur1);
PSFgaussgray = mat2gray(PSFgauss);

и я сохранил размытое изображение:

imwrite(lenablurgray1, 'lenablur.bmp');

Когда я отображаю в нем некоторые значения, я получаю

disp(lenablurgray1(91:93, 71:75))

0.5556    0.5778    0.6000    0.6222    0.6444
0.6000    0.6444    0.6667    0.6889    0.6889
0.6444    0.6889    0.7111    0.7333    0.7333

Затем я открываю это размытое изображение в OpenCV и отображаю егозначения с одинаковыми индексами:

Mat img = imread("lenablur.bmp");

for (int r = 91; r < 94; r++) {
    for (int c = 71; c < 76; c++) {
        cout << img.at<double>(r, c) << " ";
    }
    cout << endl;
}
cout << endl;

Полученный результат не соответствует значениям, указанным выше:

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

Почему это так?

РЕДАКТИРОВАТЬ: img.at<unsigned int>(r, c) дает

1903260029 1533437542 ...
2004318088 ...
....

Если я сохраняю размытое изображение в виде файла png:

imwrite(lenablurgray1, 'lenablur.png');

Затем, когда я читаю его в OpenCV:

Mat img = imread("lenablur.png");
img.convertTo(img, CV_64F);

затем img.at<double>(r, c) дает

17 11 11 11 6
17 11 11 11 6
17 11 11 11 11

, который все еще не соответствует значениям из Matlab

EDIT2 : теперь я вижу, что значения неправильны дляядро.В Matlab я получаю

imwrite(PSFgaussgray, 'PSFgauss.bmp');
disp(PSFgaussgray(7:9, 7:9)*256)

.0316 .0513 .0812
.0513 ...
...

, тогда как в OpenCV:

Mat kernel = imread("PSFgauss.bmp");
cvtColor(kernel, kernel, cv::COLOR_BGR2GRAY);
kernel.convertTo(kernel, CV_64F);

for (int r = 6; r < 9 ; r++) {
    for (int c = 6; c < 9; c++) {
        cout << kernel.at<double>(r, c) << " ";
    }
    cout << endl;
}
cout << endl;

Полученный результат не соответствует значениям, указанным выше:

0 0 0
0 0 0
0 0 0

1 Ответ

0 голосов
/ 20 сентября 2018

Чтобы понять несоответствие, которое вы видите, вам нужно знать, как MATLAB сохраняет изображения в файл BMP или PNG и как OpenCV читает его.

Предполагается, что MATLAB имеет тип double как есть.в этом случае его диапазон интенсивности составляет [0,1].То есть значения пикселей ниже 0 и выше 1 не ожидаются.Такие изображения умножаются на 255 и преобразуются в 8-битные целые числа (которые имеют диапазон [0,255]) при сохранении в файл.

Таким образом, если

>> disp(lenablurgray1(91:93, 71:75))
0.5556    0.5778    0.6000    0.6222    0.6444
0.6000    0.6444    0.6667    0.6889    0.6889
0.6444    0.6889    0.7111    0.7333    0.7333

, то что сохраняетсяis

>> uint8( lenablurgray1(91:93, 71:75) * 255 )

142   147   153   159   164
153   164   170   176   176
164   176   181   187   187

Далее OpenCV будет читать этот файл как RGB (или, скорее, BGR, неуклюжий порядок цветов OpenCV) и как 8-разрядное целое число без знака (CV_8U).Чтобы отобразить эти данные, либо извлеките один из цветовых каналов, либо преобразуйте в значение серого, используя

cvtColor(img, img, cv::COLOR_BGR2GRAY);

Затем прочитайте 8-битные значения без знака с помощью

img.at<uchar>(r, c)

Если вы прочиталиих с img.at<double>(), группы из 8 последовательных пикселей будут рассматриваться как значение одного пикселя (a double имеет 8 байтов).

Далее, помните, что индексирование MATLAB начинается с 1, тогда как OpenCV начинается с 0Таким образом, ваш цикл должен выглядеть следующим образом:

for (int r = 90; r < 93; r++) {     // matches MATLAB's 91:93 indexing
    for (int c = 70; c < 75; c++) { // matches MATLAB's 71:75 indexing
        cout << (int)img.at<uchar>(r, c) << " ";
    }
    cout << '\n';
}
cout << '\n';

Наконец, в случае вашего ядра, обратите внимание, что его значения при умножении на 255 по-прежнему намного меньше единицы: .0316 .0513 .0812.Эти значения будут записаны как 0 в файл BMP или PNG.Если вы хотите сохранить эти значения, вам нужно масштабировать ядро ​​так, чтобы его максимальное значение было 1:

PSFgauss = PSFgauss / max(PSFgauss(:));
imwrite(PSFgauss, 'PSFgauss.bmp');

(Обратите внимание, что это ядро ​​уже является изображением серого цвета, вам не нужно использоватьmat2gray на нем.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...