Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimising getting OR of Mat Channels

Tags:

c++

opencv

I want to to convert a BGR cv::Mat to gray using this formula Gray=B OR G OR R; pixel-wise operation. I tried this:

cv::Mat diff_channels[3];
cv::split(diff, diff_channels);
diff = diff_channels[0] | diff_channels[1] | diff_channels[2];

Can this be achieved with better approach?

Also, if I want to achieve Gray=MAX(B,G,R); pixel-wise operation any suggestion ?

like image 365
Humam Helfawi Avatar asked Dec 11 '22 19:12

Humam Helfawi


1 Answers

OpenCV doesn't contain any suitable built-in function to process separate channels in such way. If you want to get maximum performance you may implement this procedure by yourself. I suggest you something like this:

void calcOrChannels(const cv::Mat& src, cv::Mat& dst)
{
  CV_Assert(src.type() == CV_8UC3);
  int rows = src.rows, cols = src.cols;

  dst.create(src.size(), CV_8UC1);

  if (src.isContinuous() && dst.isContinuous())
  {
    cols = rows * cols;
    rows = 1;
  }

  for (int row = 0; row < rows; row++)
  {
    const uchar* src_ptr = src.ptr<uchar>(row);
    uchar* dst_ptr = dst.ptr<uchar>(row);

    for (int col = 0; col < cols; col++)
    {
      dst_ptr[col] = src_ptr[0] | src_ptr[1] | src_ptr[2]; // std::max(src_ptr[0], std::max(src_ptr[1], src_ptr[2]))
      src_ptr += 3;
    }
  }
}

Please note that you need to test performance of this function on your hardware, since it loses benefits by using SIMD instruction and parallelism which implemented (or maybe implemeted later) in OpenCV. But this procedure use less additional memory and arithmetical operations. I guess that it would work faster on the most systems (especially embedded). It also depends on sizes of your matrices.

Timings on my system (Core i7-4790):

| Matrix size | OpenCV (ms) | My (ms) |
|:-----------:|------------:|---------|
| 1280*720    | 4           | 1       |
| 1920*1080   | 8           | 2       |
| 4096*3112   | 41          | 17      |
like image 168
akarsakov Avatar answered Dec 13 '22 10:12

akarsakov