Smorodov 579 Жалоба Опубликовано August 18, 2012 Еще одна техника сжатия/аппроксимации. Используется так-же для восстановления полной матрицы по её частично заполненному начальному приближению. см. matrix rank approximation. Ранг = 25; Чем выше регулярность изображения и чем оси этой регулярности ближе к вертикали и горизонтали, тем ниже его ранг. Для ортогональной решетки (см.ниже), уменьшение ранга производит эффект усреднения внешнего вида всех ячеек. Ранг = 7; (можно и ранг=3 поставить, это чуть размоет изображение, но существенно не ухудшит). Ранг = 2; и #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] Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано December 12, 2014 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 ранг 15 ранг 100 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах