3

If I have an OpenCV cv::Mat, and I have a column of integers:

[1;2;3;1;2;3;1;2;3]

How can select a range of indices by value (ie 1), set those indices to a different value (ie 0), and keep the remaining values unmodified?

If this were MATLAB, I could very easily do:

A = [1;2;3;1;2;3;1;2;3];
A(A==1) = 0;

Resulting in:

[0;2;3;0;2;3;0;2;3]
Dennis Jaheruddin
  • 21,208
  • 8
  • 66
  • 122
trianta2
  • 3,952
  • 5
  • 36
  • 52
  • 1
    this might help http://opencv.willowgarage.com/documentation/cpp/basic_structures.html#mat – Shiva Aug 14 '13 at 13:57
  • It seems you're asking to execute an operation on a `cv::Mat` given a predicate. I'm not sure if this is possible. Obviously one way to do it is just to loop through every pixel and check if your condition is true -- if so, then perform the operation you desire. It's more than one line, but that's all the one-liner would be doing anyway. You can't avoid looking at every pixel/entry in the matrix. – aardvarkk Aug 14 '13 at 13:59
  • It is not as simple in OpenCV as it is in Matlab. But you can use some built-in threshold functions of OpenCV. [I've just answered a similar question yesterday](http://stackoverflow.com/a/18212476/1121420). Also, [see this answer](http://stackoverflow.com/a/17094621/1121420) – Alexey Aug 14 '13 at 14:50
  • I have my own function for that. In the function, I cast data attribute of the matrix for corresponding type of array and loop through the array to get what I want. Remember you are compensating convenience for performance by using c++ rather than matlab. – Tae-Sung Shin Aug 14 '13 at 19:35

1 Answers1

5

It's not quite as succinct in OpenCV as it is in MATLAB, but it's close. The setTo() function is what you want. This takes advantage of the fact that some logical operations on cv::Mat, like == and !=, produce masks which can be passed to other functions:

uchar data[] = {1, 2, 3, 1, 2, 3, 1, 2, 3};
cv::Mat A(9, 1, CV_8UC1, data);
A.setTo(0, A == 1);

Which will give the result as expected:

[0; 2; 3; 0; 2; 3; 0; 2; 3]
Aurelius
  • 11,111
  • 3
  • 52
  • 69