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.
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;
}