Перейти к содержимому
Compvision.ru
Smorodov

Понижение ранга матрицы изображения (matrix rank approximation)

Recommended Posts

Еще одна техника сжатия/аппроксимации.

Используется так-же для восстановления полной матрицы по её частично заполненному начальному приближению.

см. matrix rank approximation.

Ранг = 25;

post-1-0-22463700-1345308889_thumb.jpg

Чем выше регулярность изображения и чем оси этой регулярности ближе к вертикали и горизонтали, тем ниже его ранг.

Для ортогональной решетки (см.ниже), уменьшение ранга производит эффект усреднения внешнего вида всех ячеек.

Ранг = 7; (можно и ранг=3 поставить, это чуть размоет изображение, но существенно не ухудшит).

post-1-0-50137500-1345309698_thumb.jpg

Ранг = 2;

post-1-0-33850100-1345309956_thumb.jpg

и

post-1-0-14986500-1345310382_thumb.jpg


#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/legacy/legacy.hpp"
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
using namespace cv;
//----------------------------------------------------------
// Точка входа
//----------------------------------------------------------
int main(int argc, char* argv[])
{
setlocale(LC_ALL, "Russian");
// Матрица изображения
Mat img;
Mat result;
//---------------------------------------------
//
//---------------------------------------------
namedWindow("Исходное изображение");

namedWindow("Результат");
// Грузим изображение
img=imread("C:\\ImagesForTest\\cat.bmp",0);
img.convertTo(img,CV_32FC1,1.0/255.0);
cout << "Исходный размер:" << img.rows*img.cols <<" элементов "<< endl;
// создаем SVD вычислятор
cv::SVD s;
// память под результат разложения
Mat w,u,vt;
// вычисляем
s.compute(img,w,u,vt);

// собираем матрицу Sigma (по-диагонали собственные числа, остальное нули)
// так как функция вернула нам их в виде вектора, а нам нужна диагональная матрица
Mat W=Mat::zeros(w.rows,w.rows,CV_32FC1);
for(int i=0;i<w.rows;i++)
{
W.at<float>(i,i)=w.at<float>(i);
}

// Понижаем ранг до k
int k=25;
W=W(Range(0,k),Range(0,k));
u=u(Range::all(),Range(0,k));
vt=vt(Range(0,k),Range::all());

// Собираем изображение обратно
result=u*W*vt;
cout << "Размер после снижения ранга:" << u.rows*u.cols+k+vt.rows*vt.cols <<" элементов "<< endl;
//---------------------------------------------
//
//---------------------------------------------
imshow("Исходное изображение", img);
imshow("Результат", result);
cvWaitKey(0);
return 0;
}
[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
clc, clear

k = 100; % rank

% A is the mxn matrix we want to decompose

A = im2double(rgb2gray(imread('low_rank_img.jpg')))';

sz= size(A)

%make black hole

A(100:100+sz(1)/8,100:100+sz(2)/10)=0;

kmax= min(size(A));

if(k>kmax)

    k= kmax;

end

tic

% Compute SVD of A directly

[u0, S0, V0] = svd(A,'econ');

A0 = U0(:,1:k) * S0(1:k,1:k) * V0(:,1:k)';

rank(A0)%test if rank = k

toc

display(['SVD Error: ' num2str(norm(A(:)-A0(:)) / norm(A(:)))])

clear U0 S0 V0

 

тоже самое на матлабе, ранг конечной матрицы будет равен k, так же в коде тестируется, что будет если проделать в изображении дырку.

ранг 5

rank_5.PNG

ранг 15

rank_15.PNG

ранг 100

rank_100.PNG

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×