Ask Your Question
1

copy even rows/cols to another Mat

asked 2015-01-12 09:44:37 -0600

maystroh gravatar image

updated 2015-01-13 04:24:06 -0600

I would like to get the even rows/cols of a mat of 3 channels, something like this:

A = 1 0 1 0 1 0
    1 0 1 0 1 0
    1 0 1 0 1 0

result = 1 1 1
         1 1 1

How to can I do this using openCV?

Thanks in advance.

EDITED:

Here is the code I could integrate:

 Mat img_object = imread(patternImageName);
 Mat B;
 for (int i = 0; i < img_object.cols; i += 2)
 {
      B.push_back(img_object.col(i));
 }
 // now we got 1 large 1d flat (column) array with all the collected elements,
 // let's make a 3x3 Mat of it again:
 B = B.reshape(-1,3);// 1 elem per channel, 3 rows.
 B = B.t();          // transpose it
 Mat B2;
 for (int i = 0; i < B.rows; i += 2)
 {
      B2.push_back(B.row(i));
 }
 imwrite("as.png",B2);

But it throws the following expection:

OpenCV Error: Assertion failed (src.dims <= 2 && esz <= (size_t)32) in transpose, file /build/buildd/opencv-2.4.8+dfsg1/modules/core/src/matrix.cpp, line 2007
terminate called after throwing an instance of 'cv::Exception'
  what():  /build/buildd/opencv-2.4.8+dfsg1/modules/core/src/matrix.cpp:2007: error: (-215) src.dims <= 2 && esz <= (size_t)32 in function transpose

Am I missing something?

edit retag flag offensive close merge delete

Comments

Do you mean the value for the 3 channels at each even/even position or do you mean something weird like "even byte"?

codingTornado gravatar imagecodingTornado ( 2015-01-12 11:31:13 -0600 )edit

maystroh, this is not matlab, we start indexing at 0 in c++, so you're already 'one-off', hee

berak gravatar imageberak ( 2015-01-12 12:43:33 -0600 )edit

I'm not quite sure if it works, but you could have luck with cv::resize and the INTER_NEAREST (or maybe INTER_AREA) flags. A different approach would be cv::remap with two custom created maps.

FooBar gravatar imageFooBar ( 2015-01-12 13:27:03 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
3

answered 2015-01-12 13:49:21 -0600

berak gravatar image

updated 2015-01-13 04:30:51 -0600

opencv has nice row(i) col(i) functions, you can use those to build a new Mat from another one:

// this is only used for the easy initialization in this demo,
// usually you will have a plain Mat A:
Mat_<float> A(3,6);
A << 1,2,3,4,5,6,
     1,2,3,4,5,6,
     1,2,3,4,5,6;
// now we can start collecting the even cols of A,
// unfortunately opencv insists on pushing into *rows* here, 
// so we will need to transpose the result later..
Mat B;
for (int i=0; i<A.cols; i+=2)
{
    B.push_back(A.col(i));
}
// now we got 1 large 1d flat (column) array with all the collected elements,
// let's make a 3x3 Mat of it again:
B = B.reshape(0,A.cols/2); // keep channel count, but rearrange to half the cols we had before.
B = B.t();           // transpose it
cerr << B << endl;
[1, 3, 5;
  1, 3, 5;
  1, 3, 5]

// here's the same thing for rows(no transpose needed):    
Mat_<float> A2(6,3);
A2 << 1,1,1,
     2,2,2,
     3,3,3,
     4,4,4,
     5,5,5,
     6,6,6;

Mat B2;
for (int i=0; i<A2.rows; i+=2)
{
    B2.push_back(A2.row(i));
}
// also, since we were pushing row vectors already, we can skip the reshape:
cerr << B2<< endl;  
[1, 1, 1;
  3, 3, 3;
  5, 5, 5]
edit flag offensive delete link more

Comments

This works if A has only one channel but what if I have a Mat of 3 channels? I'm sorry for this kind of question but I'm still newbie in openCV and don't know exactly how manipulate the variables

maystroh gravatar imagemaystroh ( 2015-01-13 04:11:45 -0600 )edit

oh sorry my bad. using 0 as first arg to the reshape will preserve the original number of channels

^^ see edit please. helpful ?

berak gravatar imageberak ( 2015-01-13 04:13:29 -0600 )edit

see EDITED @berak

maystroh gravatar imagemaystroh ( 2015-01-13 04:23:44 -0600 )edit
1

sorry again, typo, : 0 , not -1

berak gravatar imageberak ( 2015-01-13 04:28:59 -0600 )edit

Thanks, that's it

maystroh gravatar imagemaystroh ( 2015-01-13 04:45:19 -0600 )edit
1

answered 2016-02-18 08:50:55 -0600

updated 2016-02-18 09:30:03 -0600

i tested @FooBar 's comment with the code below.

as he said cv:resize() with INTER_NEAREST flag do the trick.

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    Mat m = (Mat_<uchar>(6,6) <<
             0,2,0,2,0,2,
             0,2,0,2,0,2,
             0,2,0,2,0,2,
             0,2,0,2,0,2,
             0,2,0,2,0,2,
             0,2,0,2,0,2);

    cout << "Mat m = (Mat_<uchar>(6,6) << 0,2,...)\n" << m << "\n" << endl;

    Mat m_resized;

    resize( m, m_resized, Size(), 0.5, 0.5, INTER_NEAREST );

    cout << "resized m ( with INTER_NEAREST flag )\n" << m_resized << "\n" << endl;

    resize( m, m_resized, Size(), 0.5, 0.5, INTER_LINEAR );

    cout << "resized m ( with INTER_LINEAR flag )\n" << m_resized << "\n" << endl;

    resize( m, m_resized, Size(), 0.5, 0.5, INTER_AREA );

    cout << "resized m ( with INTER_AREA flag )\n" << m_resized << "\n" << endl;
    return 0;
}

output of the code:

Mat m = (Mat_<uchar>(6,6) << 0,2,...)
[  0,   2,   0,   2,   0,   2;
   0,   2,   0,   2,   0,   2;
   0,   2,   0,   2,   0,   2;
   0,   2,   0,   2,   0,   2;
   0,   2,   0,   2,   0,   2;
   0,   2,   0,   2,   0,   2]

resized m ( with INTER_NEAREST flag )
[  0,   0,   0;
   0,   0,   0;
   0,   0,   0]

resized m ( with INTER_LINEAR flag )
[  1,   1,   1;
   1,   1,   1;
   1,   1,   1]

resized m ( with INTER_AREA flag )
[  1,   1,   1;
   1,   1,   1;
   1,   1,   1]
edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2015-01-12 09:44:37 -0600

Seen: 5,092 times

Last updated: Feb 18 '16