Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining template type when accessing OpenCV Mat elements

I'm using the following code to add some noise to an image (straight out of the OpenCV reference, page 449 -- explanation of cv::Mat::begin):

void
simulate_noise(Mat const &in, double stddev, Mat &out)
{
    cv::Size s = in.size();
    vector<double> noise = generate_noise(s.width*s.height, stddev);

    typedef cv::Vec<unsigned char, 3> V4;
    cv::MatConstIterator_<V4> in_itr = in.begin<V4>();
    cv::MatConstIterator_<V4> in_end = in.end<V4>();
    cv::MatIterator_<V4> out_itr = out.begin<V4>();
    cv::MatIterator_<V4> out_end = out.end<V4>();

    for (; in_itr != in_end && out_itr != out_end; ++in_itr, ++out_itr)
    {
        int noise_index = my_rand(noise.size());
        for (int j = 0; j < 3; ++j)
            (*out_itr)[j] = (*in_itr)[j] + noise[noise_index];
    }
}

Nothing overly complicated:

  • in and out are allocated cv::Mat objects of the same dimensions and type
  • iterate over the input image in
  • at each position, pick a random value from noise (my_rand(int n) returns a random number in [0..n-1]
  • sum the pixel from in with the random noise value
  • put the summation result into out

I don't like this code because the following statement seems unavoidable:

typedef cv::Vec<unsigned char, 3> V4;

It has hard-coded two things:

  1. The images have 3 channels
  2. The channel depth is 8bpp

If I get this typedef wrong (e.g. wrong channel depth or wrong number of channels), then my program segfaults. I originally used typedef cv::Vec<unsigned char, 4> V4 to handle images with an arbitrary number of channels (the max OpenCV supports is 4), but this caused a segfault.

Is there any way I can avoid hard-coding the two things above? Ideally, I want something that's as generic as:

typedef cv::Vec<in.type(), in.size()> V4;
like image 834
mpenkov Avatar asked Jan 20 '11 06:01

mpenkov


People also ask

How do I know what type of CV mat I have?

We can check the Data Type of a cv::Mat using “type()” method. This is a method you can use for checking the type of an cv::Mat.

What is use of mat class in OpenCV?

The Mat class of OpenCV library is used to store the values of an image. It represents an n-dimensional array and is used to store image data of grayscale or color images, voxel volumes, vector fields, point clouds, tensors, histograms, etc.


1 Answers

I know this comes late. However, the real solution to your problem is to use OpenCV functionality to do what you want to do.

  1. create noise vector as you do already (or use the functions that OpenCV provides hint!)
  2. shuffle noise vector so you don't need individual noise_index for each pixel; or create vector of randomised noise beforehand
  3. build a matrix header around your shuffled/random vector: cv::Mat_<double>(noise);
  4. use matrix operations for computation: out = in + noise; or cv::add(in, noise, out);
  5. PROFIT!

Another advantage of this method is that OpenCV might employ multithreading, SSE or whatever to speed-up this massive-element operation, which you do not. Your code is simpler, cleaner, and OpenCV does all the nasty type handling for you.

like image 172
ypnos Avatar answered Nov 10 '22 00:11

ypnos