First time here? Check out the FAQ!

Ask Your Question
1

copy even rows/cols to another Mat

asked Jan 12 '15

maystroh gravatar image

updated Jan 13 '15

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?

Preview: (hide)

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 (Jan 12 '15)edit

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

berak gravatar imageberak (Jan 12 '15)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 (Jan 12 '15)edit

2 answers

Sort by » oldest newest most voted
3

answered Jan 12 '15

berak gravatar image

updated Jan 13 '15

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]
Preview: (hide)

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 (Jan 13 '15)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 (Jan 13 '15)edit

see EDITED @berak

maystroh gravatar imagemaystroh (Jan 13 '15)edit
1

sorry again, typo, : 0 , not -1

berak gravatar imageberak (Jan 13 '15)edit

Thanks, that's it

maystroh gravatar imagemaystroh (Jan 13 '15)edit
1

answered Feb 18 '16

updated Feb 18 '16

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]
Preview: (hide)

Question Tools

2 followers

Stats

Asked: Jan 12 '15

Seen: 5,321 times

Last updated: Feb 18 '16