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

Часто применяемые операции с матрицами.

Recommended Posts

Написал утилиты, для вставки/удаления строк/столбцов , особо не отлаживал, но вроде работает (принимаются предложения по оптимизации):


// ----------------------------------------------------------
// М - матрица, изкоторой удаляем строки
// beg - номер удаляемой строки
// num - количество удаляемых строк
// ----------------------------------------------------------
void removeRows(Mat& M,int beg,int num)
{
//CV_Assert(0 <= beg && num>=0 && num<M.rows && beg <= CV_MAX_DIM && !M.empty());
int top_rows=beg;
int bot_rows=M.rows-beg-num;
int cols=M.cols;
if(beg>0 && beg+num<M.rows)
{
Mat topM(top_rows,cols,M.type());
Mat botM(bot_rows,cols,M.type());
topM=M(Rect(0,0,topM.cols,topM.rows));
botM=M(Rect(0,beg+num,botM.cols,botM.rows));
M.release();
M=Mat(topM.rows+botM.rows,topM.cols,topM.type());
topM.copyTo(M(Rect(0,0,topM.cols,topM.rows)));
botM.copyTo(M(Rect(0,topM.rows,botM.cols,botM.rows)));
}else if (top_rows==0)
{
M=M(Rect(0,num,M.cols,M.rows-num));
} else if (bot_rows==0)
{
M=M(Rect(0,0,M.cols,M.rows-num));
}
}

// ----------------------------------------------------------
// М - матрица, изкоторой удаляем столбцы
// beg - номер удаляемого столбца
// num - количество удаляемых столбцов
// ----------------------------------------------------------
void removeCols(Mat& M,int beg,int num)
{
//CV_Assert(0 <= beg && num>=0 && num<M.cols && beg <= CV_MAX_DIM && !M.empty());
int left_cols=beg;
int right_cols=M.cols-beg-num;
int rows=M.rows;
if(beg>0 && beg+num<M.cols)
{
Mat leftM(rows,left_cols,M.type());
Mat rightM(rows,right_cols,M.type());
leftM=M(Rect(0,0,leftM.cols,leftM.rows));
rightM=M(Rect(beg+num,0,rightM.cols,rightM.rows));
M.release();
M=Mat(rows,leftM.cols+rightM.cols,leftM.type());
leftM.copyTo(M(Rect(0,0,leftM.cols,leftM.rows)));
rightM.copyTo(M(Rect(leftM.cols,0,rightM.cols,rightM.rows)));
}else if (left_cols==0)
{
M=M(Rect(num,0,M.cols-num,M.rows));
} else if (right_cols==0)
{
M=M(Rect(0,0,M.cols-num,M.rows));
}
}
// ----------------------------------------------------------
// М - матрица, в которую вставляем столбцы
// pos - позиция вставки
// I - вставляемая матрица
// ----------------------------------------------------------
void insertCols(Mat& M,Mat& I,int pos)
{
//CV_Assert(0 <= pos && !I.empty() && I.rows==M.rows && pos <= CV_MAX_DIM);
int left_cols=pos;
int right_cols=M.cols-pos;
int rows=M.rows;
int type=I.type();
if(left_cols>0 && right_cols>0)
{
Mat leftM(rows,left_cols,type);
Mat rightM(rows,right_cols,type);
leftM=M(Rect(0,0,leftM.cols,leftM.rows));
rightM=M(Rect(pos,0,rightM.cols,rightM.rows));
M.release();
M=Mat(rows,leftM.cols+rightM.cols+I.cols,type);
leftM.copyTo(M(Rect(0,0,leftM.cols,leftM.rows)));
I.copyTo(M(Rect(leftM.cols,0,I.cols,I.rows)));
rightM.copyTo(M(Rect(leftM.cols+I.cols,0,rightM.cols,rightM.rows)));
}else if (left_cols==0 && right_cols>0)
{
Mat rightM(rows,right_cols,type);
rightM=M(Rect(pos,0,rightM.cols,rightM.rows));
M.release();
M=Mat(rows,rightM.cols+I.cols,type);
I.copyTo(M(Rect(0,0,I.cols,I.rows)));
rightM.copyTo(M(Rect(I.cols,0,rightM.cols,rightM.rows)));

} else if (right_cols==0 && left_cols>0)
{
Mat leftM(rows,left_cols,type);
leftM=M(Rect(0,0,leftM.cols,leftM.rows));
M.release();
M=Mat(rows,leftM.cols+I.cols,type);
leftM.copyTo(M(Rect(0,0,leftM.cols,leftM.rows)));
I.copyTo(M(Rect(leftM.cols,0,I.cols,I.rows)));
}
else if (right_cols==0 && left_cols==0)
{
M=I.clone();
}
}
// ----------------------------------------------------------
// М - матрица, в которую вставляем строки
// pos - позиция вставки
// I - вставляемая матрица
// ----------------------------------------------------------
void insertRows(Mat& M,Mat& I,int pos)
{
//CV_Assert(0 <= pos && !I.empty() && I.cols==M.cols && pos <= CV_MAX_DIM && !M.empty());
int top_rows=pos;
int bot_rows=M.cols-pos;
int cols=M.cols;
int type=I.type();
if(top_rows>0 && bot_rows>0)
{
Mat topM(top_rows,cols,type);
Mat botM(bot_rows,cols,type);
topM=M(Rect(0,0,topM.cols,topM.rows));
botM=M(Rect(0,pos,botM.cols,botM.rows));
M.release();

M=Mat(topM.rows+botM.rows+I.rows,cols,type);

topM.copyTo(M(Rect(0,0,topM.cols,topM.rows)));
I.copyTo(M(Rect(0,topM.rows,I.cols,I.rows)));
botM.copyTo(M(Rect(0,topM.rows+I.rows,botM.cols,botM.rows)));
}else if (top_rows==0 && bot_rows>0)
{
Mat botM(bot_rows,cols,type);
botM=M(Rect(0,pos,botM.cols,botM.rows));
M.release();
M=Mat(botM.rows+I.rows,cols,type);
I.copyTo(M(Rect(0,0,I.cols,I.rows)));
botM.copyTo(M(Rect(0,I.rows,botM.cols,botM.rows)));

} else if (bot_rows==0 && top_rows>0)
{
Mat topM(top_rows,cols,type);
topM=M(Rect(0,0,topM.cols,topM.rows));
M.release();
M=Mat(topM.rows+I.rows,cols,type);
topM.copyTo(M(Rect(0,0,topM.cols,topM.rows)));
I.copyTo(M(Rect(0,topM.rows,I.cols,I.rows)));
}
else if (bot_rows==0 && top_rows==0)
{
M=I.clone();
}
}
// ----------------------------------------------------------
[/code]

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


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

еще append матриц бы не помешал.

я так понимаю что без копирований нельзя ибо это нарушает непрерывность матрицы.

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


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

По поводу Append, я думаю можно использовать функции hconcat и vconcat см. в конце листинга.

Еще одна утилита в копилку:

Нужна для составления матриц из подматриц.

Задаем матрицу (тип MatOfMat) с типом элемента Mat, и функцией expandMat разворачиваем её в обычную матрицу, состоящую из заданных подматриц.

Или можно использовать ф-цию Combine в таком виде

пример вызова

Combine(3,2,A,B,C,D,E,F);

создаст матрицу

    A D
M= B E
C F[/code] первый параметр количество строк матрицы матриц второй параметр кол-во столбцов матрицы матриц дальше идут матрицы, которые заполняют сначала столбцы, затем строки. Пример использования есть ниже. Так-же добавил аналог матлабовского [color=#0000FF]repmat[/color].
[code]#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdarg.h>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "fstream"
#include "iostream"
using namespace std;
using namespace cv;

//------------------------------------------------------------------------------------------
// Определяем динамический двумерный массив матриц
//------------------------------------------------------------------------------------------
typedef vector<vector<Mat>> MatOfMat;
//------------------------------------------------------------------------------------------
// Для удобства создания массивов матриц
//------------------------------------------------------------------------------------------
MatOfMat Create(int rows,int cols)
{
return MatOfMat(MatOfMat(rows,vector<Mat>(cols)));
}
//------------------------------------------------------------------------------------------
// Функция, разворачиавющая массив двумерных матриц в одну большую двумерную матрицу
// Необходимым условием является равенство количества столбцов в матрицах одного столбца и
// количества строк в матрицах одной строки
//------------------------------------------------------------------------------------------
Mat expandMat(MatOfMat M)
{
// определим шаги сетки и размер результирующей матрицы
// разбиение по строкам
vector<int> rowSteps;
vector<int> colSteps;
int totalRows=0,totalCols=0;
for(int i=0;i<M.size();i++)
{
rowSteps.push_back(M[i][0].rows);
totalRows+=M[i][0].rows;
}
// разбиение по столбцам
for(int j=0;j<M[0].size();j++)
{
colSteps.push_back(M[0][j].cols);
totalCols+=M[0][j].cols;
}
// текущая позиция втавки прямоугольной подматрицы
int currentRow=0;
int currentCol=0;
int type=M[0][0].type();
Mat Result(totalRows,totalCols,type);

for(int i=0;i<M.size();i++)
{
currentCol=0;
for(int j=0;j<M[i].size();j++)
{
M[i][j].copyTo(Result(Rect(currentCol,currentRow,colSteps[j],rowSteps[i])));
currentCol+=colSteps[j];
}
currentRow+=rowSteps[i];
}
rowSteps.clear();
colSteps.clear();
return Result;
}
//-----------------------------------------------------------------------------------------------------
// пример вызова Combine(3,2,A,B,C,D,E,F);
// создаст матрицу
// A D
// M= B E
// C F
//-----------------------------------------------------------------------------------------------------
Mat Combine(int rows,int cols,...)
{
va_list vl;
va_start(vl,cols);
MatOfMat M=Create(rows,cols);
for (int i=0;i<rows;i++)
{
for (int j=0;j<cols;j++)
{
Mat m=va_arg(vl,Mat);
m.copyTo(M[i][j]);
}
}
va_end(vl);
Mat Result = expandMat(M);
M.clear();
return Result;
}
//-----------------------------------------------------------------------------------------------------
// Аналог матлабовского repmat.
// Результат представляет собой большую матрицу, состоящую из повторений маленькой матрицы
// nr раз по-вертикали и nc раз по-горизонтали
//-----------------------------------------------------------------------------------------------------
Mat repmat(Mat& m,int nr,int nc)
{
MatOfMat M=Create(nr,nc);
for (int i=0;i<nr;i++)
{
for (int j=0;j<nc;j++)
{
m.copyTo(M[i][j]);
}
}
Mat Result = expandMat(M);
M.clear();
return Result;
}
//-----------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------
int main( int argc, char** argv )
{
// Первый вариант
MatOfMat M=Create(2,2);
M[0][0]=Mat::eye(3,4,CV_32FC1); // матрицы с единицами по диагонали
M[1][0]=Mat::eye(3,4,CV_32FC1);
M[0][1]=Mat::eye(3,3,CV_32FC1);
M[1][1]=Mat::eye(3,3,CV_32FC1);
Mat M_expanded=expandMat(M);
cout << M_expanded << endl;
M.clear();

// Второй вариант
Mat A=Mat::eye(3,4,CV_32FC1); // матрицы с единицами по диагонали
Mat B=Mat::eye(3,4,CV_32FC1);
Mat C=Mat::eye(3,3,CV_32FC1);
Mat D=Mat::eye(3,3,CV_32FC1);

Mat E=Combine(2,2,A,C,B,D);
cout << E << endl;
// Объединение по горизонтали
vector<Mat> M1;
M1.push_back(A);
M1.push_back(B);
Mat ABh;
cv::hconcat(M1,ABh);
cout << ABh << endl;

// Объединение по вертикали
vector<Mat> M2;
M2.push_back(A);
M2.push_back(B);
Mat ABv;
cv::vconcat(M2,ABv);
cout << ABv << endl;

// repmat
Mat rm=repmat(A,4,3);
cout << rm << endl;
getchar();

return 0;
}

  • Like 1

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


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

у меня с ними вроде как были ошибки.

Combine

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

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


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

Аналог матлабовского find. Взял отсюда: http://code.opencv.org/issues/2205

#include <opencv2/core/core.hpp>
#include <vector>

/*! @brief find non-zero elements in a Matrix
*
* Given a binary matrix (likely returned from a comparison
* operation such as compare(), >, ==, etc, return all of
* the non-zero indices as a std::vector<cv::Point> (x,y)
*
* This function aims to replicate the functionality of
* Matlab's command of the same name
*
* Example:
* \code
* // find the edges in an image
* Mat edges, thresh;
* sobel(image, edges);
* // theshold the edges
* thresh = edges > 0.1;
* // find the non-zero components so we can do something useful with them later
* vector<Point> idx;
* find(thresh, idx);
* \endcode
*
* @param binary the input image (type CV_8UC1)
* @param idx the output vector of Points corresponding to non-zero indices in the input
*/
void find(const cv::Mat& binary, std::vector<cv::Point> idx) {

assert(binary.cols > 0 && binary.rows > 0 && binary.channels() == 1 && binary.depth() == CV_8U);
const int M = binary.rows;
const int N = binary.cols;
for (int m = 0; m < M; ++m) {
const char* bin_ptr = binary.ptr<char>(m);
for (int n = 0; n < N; ++n) {
if (bin_ptr[n] > 0) idx.push_back(cv::Point(n,m));
}
}
} [/code]

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


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

Чтение-запись матрицы в бинарный файл (сделал для однослойных матриц) можно приделать цикл по слоям, но лень.

//==============================================================================
void writeMatToBin(std::ofstream& fs,const Mat& m)
{
int rows,cols;
int depth;


rows = m.rows;
cols = m.cols;
depth = m.depth();

fs.write((const char*)(&rows),sizeof(int));
fs.write((const char*)(&cols),sizeof(int));
fs.write((const char*)(&depth),sizeof(int));

char vc;
short vs;
unsigned short int vus;
int vi;
float vf;
double vd;

for(int i=0;i<m.rows;++i)
{
for(int j=0;j<m.cols;++j)
{
switch (depth)
{
case CV_8U:
vc=m.at<char>(i,j);
fs.write((const char*)(&vc),sizeof(char));
break;
case CV_16U:
vus=m.at<unsigned short int>(i,j);
fs.write((const char*)(&vus),sizeof(unsigned short int));
break;
case CV_16S:
vs=m.at<short int>(i,j);
fs.write((const char*)(&vs),sizeof(short int));
break;
case CV_32S:
vi=m.at<int>(i,j);
fs.write((const char*)(&vi),sizeof(int));
break;
case CV_32F:
vf=m.at<float>(i,j);
fs.write((const char*)(&vf),sizeof(float));
break;
case CV_64F:
vd=m.at<float>(i,j);
fs.write((const char*)(&vd),sizeof(double));
break;
}
}
}
}
//==============================================================================
void readMatFromBin(std::ifstream& fs,Mat& m)
{
int rows,cols;
int depth;

fs.read((char*)(&rows),sizeof(int));
fs.read((char*)(&cols),sizeof(int));
fs.read((char*)(&depth),sizeof(int));

m=Mat(rows,cols,depth,1);

char vc;
short vs;
unsigned short int vus;
int vi;
float vf;
double vd;

for(int i=0;i<m.rows;++i)
{
for(int j=0;j<m.cols;++j)
{
switch (depth)
{
case CV_8U:
fs.read((char*)(&vc),sizeof(char));
m.at<char>(i,j)=vc;
break;
case CV_16U:
fs.read((char*)(&vus),sizeof(unsigned short int));
m.at<unsigned short int>(i,j)=vus;
break;
case CV_16S:
fs.read((char*)(&vs),sizeof(short int));
m.at<short int>(i,j)=vs;
break;
case CV_32S:
fs.read((char*)(&vi),sizeof(int));
m.at<int>(i,j)=vi;
break;
case CV_32F:
fs.read((char*)(&vf),sizeof(float));
m.at<float>(i,j)=vf;
break;
case CV_64F:
fs.read((char*)(&vd),sizeof(double));
m.at<float>(i,j)=vd;
break;
}
}
}
}
[/code]

И библиотека для чтения МАТЛАБ-овских матриц в OpenCV (VS2010 проект с демкой применения):

MatIOLib.rar

  • Like 1

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×