6

I've been playing around with opencv2 implemented in C++ for a couple of days and noticed that the lookup tables are the fastest way to apply changes to an image. However, I've been having some troubles with using them for my purposes.

The code below shows an example of inverting pixels' values:

bool apply(Image& img) {
   int dim(256);
   Mat lut(1, &dim, CV_8U);
   for (int i=0; i<256; i++)
      lut.at<uchar>(i)= 255-i;
   LUT(img.final,lut,img.final);
   return true;
}

class Image {
public:
   const Mat& original;
   Mat final;
...
};

As it's very efficient, much more efficient than changing each pixel by one (verified by my own tests), I'd like to use this method for other operations. However to do this, I have to access each layer (each color, the picture is in BGR) separately. So for example, I'd like to change blue to 255-i, green to 255-i/2 and red to 255-i/3.

I've been searching the net for a while, but couldn't come up with a correct solution. As far as I know, it's possible (documentation) but I can't find a way to implement it.

1 Answer 1

6

The key is this paragraph in the docs:

the table should either have a single channel (in this case the same table is used for all channels) or the same number of channels as in the source array

So, you must create a multichannel LUT:

bool apply(Image& img) {
   int dim(256);

   Mat lut(1, &dim, CV_8UC(img.final.channels()));

   if( img.final.channels() == 1)
   {
      for (int i=0; i<256; i++)
         lut.at<uchar>(i)= 255-i;
   }
   else // stupid idea that all the images are either mono either multichannel
   {
      for (int i=0; i<256; i++)
      {
         lut.at<Vec3b>(i)[0]= 255-i;   // first channel  (B)
         lut.at<Vec3b>(i)[1]= 255-i/2; // second channel (G)
         lut.at<Vec3b>(i)[2]= 255-i/3; // ...            (R)
      }
   }

   LUT(img.final,lut,img.final); // are you sure you are doing final->final? 
   // if yes, correct the LUT allocation part

   return true;
}
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for the reply! I knew, it was possible because of that paragraph, but I couldn't find an example how to do it. Yes, I want to overwrite img.final. What do you mean by correcting the LUT allocation part? Having it like this: "Mat lut(1, &dim, CV_8U(img.final.channels()));" I get a compilation error: "‘0’ cannot be used as a function".
It's probably CV_8UC(channels); you can check the docs for the correct formula
I finally got it, the line should be as follows: "Mat lut(1, &dim, CV_8UC3);". Can you change it in the above code, so that other people can take use of the solution? Thanks for pointing me the right direction!
I know that way, but I want the piece of code to work regardless the number of channels - so if you have a grayscale it will build a 1-channel LUT, and if you have more channels, it will build a LUT with the same number of channels as the input.
hmmmm, my latest edit should work (I did not try it) and yours too, with the mention that it should be CV_MAKETYPE(CV_8U, img.final.channels()). You already specify the number of channels if you say CV_8UC3. it means 8bit unsigned, C-channels 3-channels number.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.